Naive brute force will look something like this:
n = 3200724; lim = sqrt (n) + 1; for (a = 0; a <= lim; a++) for (b = 0; b <= lim; b++) for (c = 0; c <= lim; c++) for (d = 0; d <= lim; d++) if (a * a + b * b + c * c + d * d == n) printf ("%d %d %d %d\n", a, b, c, d);
Unfortunately, this will lead to more than a trillion cycles, but not too efficient.
In fact, you can do it much better if you take into account the huge number of impossibilities at each level with something like:
#include <stdio.h> int main(int argc, char *argv[]) { int n = atoi (argv[1]); int a, b, c, d, na, nb, nc, nd; int count = 0; for (a = 0, na = n; a * a <= na; a++) { for (b = 0, nb = na - a * a; b * b <= nb; b++) { for (c = 0, nc = nb - b * b; c * c <= nc; c++) { for (d = 0, nd = nc - c * c; d * d <= nd; d++) { if (d * d == nd) { printf ("%d %d %d %d\n", a, b, c, d); count++; } tot++; } } } } printf ("Found %d solutions\n", count); return 0; }
This is still brute force, but not so cruel, because it understands when it is necessary to stop each level of the cycle as soon as possible.
In my (relatively) modest field, which takes the second (a) to get all the solutions for numbers up to 50,000. In addition, it starts to take more time:
n time taken ---------- ---------- 100,000 3.7s 1,000,000 6m, 18.7s
For n = ten million
, it lasted about an hour and a half before I killed him.
So, I would say that brute force is quite acceptable to a certain point. In addition, more mathematical solutions will be required.
For greater efficiency, you can only check those solutions where d >= c >= b >= a
. This is because you could collect all the solutions from these combinations into permutations (with possible duplication, where the values ββof two or more of a
, b
, c
or d
identical).
In addition, the body of cycle d
does not need to check each value of d
, only the last possible.
Getting results for 1,000,000
in this case takes less than ten seconds, and no more than six minutes:
0 0 0 1000 0 0 280 960 0 0 352 936 0 0 600 800 0 24 640 768 : : : : 424 512 512 544 428 460 500 596 432 440 480 624 436 476 532 548 444 468 468 604 448 464 520 560 452 452 476 604 452 484 484 572 500 500 500 500 Found 1302 solutions real 0m9.517s user 0m9.505s sys 0m0.012s
This code follows:
#include <stdio.h> int main(int argc, char *argv[]) { int n = atoi (argv[1]); int a, b, c, d, na, nb, nc, nd; int count = 0; for (a = 0, na = n; a * a <= na; a++) { for (b = a, nb = na - a * a; b * b <= nb; b++) { for (c = b, nc = nb - b * b; c * c <= nc; c++) { for (d = c, nd = nc - c * c; d * d < nd; d++); if (d * d == nd) { printf ("%4d %4d %4d %4d\n", a, b, c, d); count++; } } } } printf ("Found %d solutions\n", count); return 0; }
And, according to DSM's suggestion, cycle d
can disappear altogether (since there is only one possible value of d
(discounting negative numbers), and it can be calculated), which leads to one million cases up to two seconds for me, and ten million cases for a much more manageable 68 seconds.
This version is as follows:
#include <stdio.h>
(a) : All timings are done with internal printf
commented out, so I / O does not distort the numbers.