digitalmars.D.learn - Puzzle (8-14)
- Wyverex (5/5) Aug 14 2008 1) Find the smallest x + y + z with integers x y z 0 such that x +
- Steven Schveighoffer (94/99) Aug 14 2008 attempt 1:
- bearophile (36/38) Aug 14 2008 ...
- bearophile (33/33) Aug 14 2008 Using a simple handmade perfect hash the running time of this program be...
- bearophile (6/12) Aug 15 2008 Can be replaced with just:
- bearophile (61/61) Aug 15 2008 Python+Psyco version:
- BCS (6/11) Aug 14 2008 http://www.dsource.org/projects/scrapple/browser/trunk/bignum/bignum.d
1) Find the smallest x + y + z with integers x y z 0 such that x + y, x - y, x + z, x - z, y + z, y - z are all perfect squares. 2) Develop a bigint type. should be able to + - * / %. Should also be printable! 2.5) make bigfloat.
Aug 14 2008
"Wyverex" wrote1) Find the smallest x + y + z with integers x y z 0 such that x + y, x - y, x + z, x - z, y + z, y - z are all perfect squares.attempt 1: import tango.io.Stdout; import tango.math.Math; bool issquare(long x) { auto r = sqrt(cast(double)x); auto lr = cast(long)r; if(lr * lr == x || (lr + 1) * (lr + 1) == x) return true; return false; } void main() { for(long x = 3; ; x++) { for(long i = 1; i * i < x; i++) { long y = x - (i * i); if(issquare(x + y)) { for(long j = 1; j * j < y; j++) { long z = y - (j * j); if(issquare(y + z) && issquare(x + z) && issquare(x - z)) { Stdout(x, y, z).newline; return; } } } } } } execution time: real 0m27.115s user 0m27.115s sys 0m0.001s answer: 434657, 420968, 150568 attempt 2 (little bit of cheating, because I know the answer fits within an int): bool issquare(int x) { auto r = sqrt(cast(double)x); auto lr = cast(int)r; if(lr * lr == x || (lr + 1) * (lr + 1) == x) return true; return false; } void main() { int[][int] pairs; for(int x = 3; ; x++) { for(int i = 1; i * i < x; i++) { int y = x - (i * i); if(issquare(x + y)) { int[] *arr = y in pairs; if(arr !is null) { foreach(z; *arr) { if(issquare(x - z) && issquare(x + z)) { Stdout(x, y, z).newline; return; } } } arr = x in pairs; if(arr is null) { pairs[x] = new int[0]; arr = x in pairs; } *arr ~= y; } } } } runtime: real 0m11.303s user 0m11.299s sys 0m0.005s When I did this same solution with longs, it was about 23 seconds, so caching the pairs of possible adjacent values doesn't really save a whole lot.2) Develop a bigint type. should be able to + - * / %. Should also be printable!Yeah, right. I don't have a week to kill :P2.5) make bigfloat.ditto. -Steve
Aug 14 2008
Steven Schveighoffer:attempt 2 (little bit of cheating, because I know the answer fits within an int):... I have modified your code a little, using a poor's man set to speed up the code: import std.stdio: putr = writefln; import std.math: sqrt; void main() { int[][int] pairs; int[int] squares; for (int i = 1; i < short.max; i++) squares[i * i] = 0; for (int x = 3; ; x++) { for (int i = 1; i * i < x; i++) { int y = x - (i * i); if ((x + y) in squares) { auto arr = y in pairs; if (arr !is null) { foreach (z; *arr) { if ((x - z) in squares && (x + z) in squares) { putr(x, " ", y, " ", z); return; } } } arr = x in pairs; if (arr is null) { pairs[x] = new int[0]; arr = x in pairs; } *arr ~= y; } } } } On my 2 GHz PC it takes 6.97 s to run. I have another trick to try, we'll see if it works... Later, bearophile
Aug 14 2008
Using a simple handmade perfect hash the running time of this program becomes 1.3 s on my 2 GHz PC (this also shows why I say that D AAs are slow). import std.stdio: putr = writefln; void main() { auto squares = new int[70_001]; for (int i = 1; i < short.max; i++) squares[(i * i) % squares.length] = i * i; int[][int] pairs; for (int x = 3; ; x++) { for (int i = 1; i * i < x; i++) { int y = x - (i * i); if (squares[(x + y) % squares.length] == x + y) { auto arr = y in pairs; if (arr !is null) { foreach (z; *arr) { if (squares[(x - z) % squares.length] == (x - z) && squares[(x + z) % squares.length] == (x + z)) { putr(x, " ", y, " ", z); return; } } } arr = x in pairs; if (arr is null) { pairs[x] = new int[0]; arr = x in pairs; } *arr ~= y; } } } } Bye, bearophile
Aug 14 2008
Just for reference, all this stuff:arr = x in pairs; if (arr is null) { pairs[x] = new int[0]; arr = x in pairs; } *arr ~= y;Can be replaced with just: pairs[x] ~= y; Because arrays in D are structs, not referenced objects. Bye, bearophile
Aug 15 2008
Python+Psyco version: from collections import defaultdict from sys import maxint from array import array def main(): pairs = defaultdict(list) squares_len = 65537 #squares for i in xrange(1, 1 << 15): squares[(i * i) % squares_len] = i * i for x in xrange(3, maxint): i = 1 while i * i < x: y = x - i * i if squares[(x + y) % squares_len] == (x + y): if y in pairs: for z in pairs[y]: if (squares[(x - z) % squares_len] == (x - z) and squares[(x + z) % squares_len] == (x + z)): print x, y, z return pairs[x].append(y) i += 1 import psyco; psyco.full() main() C++ (MinGW) version: #include <vector> #include <ext/hash_map> using namespace std; using namespace __gnu_cxx; int main() { vector<int> squares(65537, 0); for (long long i = 1; i < (1 << 15); i++) squares[(i * i) % squares.size()] = i * i; typedef hash_map<int, vector<int> > Map; Map pairs; for (int x = 3; ; x++) for (int i = 1; i * i < x; i++) { int y = x - i * i; if (squares[(x + y) % squares.size()] == (x + y)) { Map::iterator arr = pairs.find(y); if (arr != pairs.end()) { int nitems = arr->second.size(); for (int j = 0; j < nitems; j++) { int z = arr->second[j]; if (squares[(x - z) % squares.size()] == (x - z) && squares[(x + z) % squares.size()] == (x + z)) { printf("%d %d %d\n", x, y, z); return 0; } } } pairs[x].push_back(y); } } return 0; } D version takes 1.29 s (DMD), C++ 1.45 s, Psyco 2.74 s. I don't know why the C++ version is so slow. Bye, bearophile
Aug 15 2008
Reply to wyverex,2) Develop a bigint type. should be able to + - * / %. Should also be printable!http://www.dsource.org/projects/scrapple/browser/trunk/bignum/bignum.d no % fixed size at compile time but work(ed) for > 1024 bit / only does Bignum/uint and not Bignum/Bignum2.5) make bigfloat.no thanks
Aug 14 2008