Pythagorean quadruples

From Rosetta Code
Pythagorean quadruples is a draft programming task. It is not yet considered ready to be promoted as a complete task, for reasons that should be found in its talk page.


One form of   Pythagorean quadruples   is   (for positive integers   a,   b,   c,   and   d):


  a2   +   b2   +   c2     =     d2


An example:

  22   +   32   +   62     =     72
which is:
  4   +   9   +   36     =     49


Task

For positive integers up   2,200   (inclusive),   for all values of   a,   b,   and   c,
find   (and show here)   those values of   d   that   can't   be represented.

Show the values of   d   on one line of output   (optionally with a title).


Related task



ALGOL 68

As with the optimised REXX solution, we find the values of d for which there are no a^2 + b^2 = d^2 - c^2. <lang algol68>BEGIN

   # find values of d where d^2 =/= a^2 + b^2 + c^2 for any integers a, b, c #
   # where d in [1..2200], a, b, c =/= 0                                     #
   # max number to check #
   INT max number = 2200;
   INT max square = max number * max number;
   # table of numbers that can be the sum of two squares #
   [ 1 : max square ]BOOL sum of two squares; FOR n TO max square DO sum of two squares[ n ] := FALSE OD;
   FOR a TO max number DO
       INT a2 = a * a;
       FOR b FROM a TO max number WHILE INT sum2 = ( b * b ) + a2;
                                        sum2 <= max square DO
           sum of two squares[ sum2 ] := TRUE
       OD
   OD;
   # now find d such that d^2 - c^2 is in sum of two squares #
   [ 1 : max number ]BOOL solution; FOR n TO max number DO solution[ n ] := FALSE OD;
   FOR d TO max number DO
       INT d2 = d * d;
       FOR c TO d - 1 WHILE NOT solution[ d ] DO
           INT diff2 = d2 - ( c * c );
           IF sum of two squares[ diff2 ] THEN
               solution[ d ] := TRUE
           FI
       OD
   OD;
   # print the numbers whose squares are not the sum of three squares #
   FOR d TO max number DO
       IF NOT solution[ d ] THEN
           print( ( " ", whole( d, 0 ) ) )
       FI
   OD;
   print( ( newline ) )

END</lang>

Output:
 1 2 4 5 8 10 16 20 32 40 64 80 128 160 256 320 512 640 1024 1280 2048

C

Five seconds on my Intel Linux box. <lang C>#include <stdio.h>

  1. include <math.h>
  2. include <string.h>
  1. define N 2200

int main(int argc, char **argv){

  int a,b,c,d;
  int r[N+1];
  memset(r,0,sizeof(r));	// zero solution array
  for(a=1; a<=N; a++){
     for(b=a; b<=N; b++){

int aabb; if(a&1 && b&1) continue; // for positive odd a and b, no solution. aabb=a*a + b*b; for(c=b; c<=N; c++){ int aabbcc=aabb + c*c; d=(int)sqrt((float)aabbcc); if(aabbcc == d*d && d<=N) r[d]=1; // solution }

     }
  }
  for(a=1; a<=N; a++)
     if(!r[a]) printf("%d ",a);	// print non solution
  printf("\n");

}</lang>

Output:
$ clang -O3 foo.c -lm
$ ./a.out
1 2 4 5 8 10 16 20 32 40 64 80 128 160 256 320 512 640 1024 1280 2048 

Kotlin

This uses a similar approach to the REXX optimized version. It also takes advantage of a hint in the C entry that there is no solution if both a and b are odd (confirmed by Wikipedia article). Runs in about 7 seconds on my modest laptop which is more than 4 times faster than the brute force version would have been: <lang scala>// version 1.1.3

const val MAX = 2200 const val MAX2 = MAX * MAX - 1

fun main(args: Array<String>) {

   val found = BooleanArray(MAX + 1)       // all false by default
   val p2 = IntArray(MAX + 1) { it * it }  // pre-compute squares
   // compute all possible positive values of d * d - c * c and map them back to d
   val dc = mutableMapOf<Int, MutableList<Int>>()
   for (d in 1..MAX) {
       for (c in 1 until d) {
           val diff = p2[d] - p2[c]              
           val v = dc[diff]
           if (v == null)
               dc.put(diff, mutableListOf(d))
           else if (d !in v)
               v.add(d)
       }
   }
 
   for (a in 1..MAX) {
       for (b in 1..a) {
           if ((a and 1) != 0 && (b and 1) != 0) continue
           val sum = p2[a] + p2[b]
           if (sum > MAX2) continue
           val v = dc[sum]
           if (v != null) v.forEach { found[it] = true }
       }
   }
   println("The values of d <= $MAX which can't be represented:")
   for (i in 1..MAX) if (!found[i]) print("$i ")
   println()

}</lang>

Output:
The values of d <= 2200 which can't be represented:
1 2 4 5 8 10 16 20 32 40 64 80 128 160 256 320 512 640 1024 1280 2048 

REXX

brute force

This version is a brute force algorithm, with some optimization (to save compute time)
which pre-computes some of the squares of the positive integers used in the search.
Integers too large for the precomputed values use an optimized integer square root. <lang rexx>/*REXX pgm computes/shows (integers), D that aren't possible for: a² + b² + c² = d² */ parse arg hi . /*obtain optional argument from the CL.*/ if hi== | hi=="," then hi=2200; high=2*hi**2 /*Not specified? Then use the default.*/ @.=. /*array of integers to be squared. */ !.=. /* " " " squared. */

      do j=1  for high                          /*precompute possible squares (to max).*/
      jj=j*j;   !.jj=j;   if j<=hi  then @.j=jj /*define a square; D  value; squared # */
      end   /*j*/

d.=. /*array of possible solutions (D) */

      do       a=1  for hi-2                    /*go hunting for solutions to equation.*/
         do    b=a   to hi-1;   ab = @.a + @.b  /*calculate sum of  2  (A,B)   squares.*/
            do c=b   to hi;     abc= ab  + @.c  /*    "      "   "  3  (A,B,C)    "    */
            if abc<=high  then if !.abc==.  then iterate   /*Not a square? Then skip it*/
                          else do;   t=abc;   r=0;   q=1;       do while q<=t;   q=q*4
                                                                end   /*while q<=t*/
                                                           /*R:  will be the iSqrt(Z). */
                                 do while q>1;  q=q%4;  _=t-r-q;  r=r%2
                                 if _>=0  then do;  t=_;  r=r+q;  end
                                 end   /*while q>1*/
                               if r*r\=abc  then iterate
                               end
            s=!.abc;    d.s=                    /*define this D solution as being found*/
            end   /*c*/
         end      /*b*/
      end         /*a*/

say say 'Not possible positive integers for d ≤' hi " using equation: a² + b² + c² = d²" say $= /* [↓] find all the "not possibles". */

      do p=1  for hi;   if d.p==.  then $=$ p   /*Not possible? Then add it to the list*/
      end   /*p*/                               /* [↓]  display list of not-possibles. */

say substr($, 2) /*stick a fork in it, we're all done. */</lang>

output   when using the default input:
Not possible positive integers for   d ≤ 2200   using equation:  a² + b² + c²  =  d²

1 2 4 5 8 10 16 20 32 40 64 80 128 160 256 320 512 640 1024 1280 2048

optimized

This REXX version is an optimized version, it solves the formula:

  a2   +   b2     =     d2   -   c2

This REXX version is over thirty times faster then the previous version. <lang rexx>/*REXX pgm computes/shows (integers), D that aren't possible for: a² + b² + c² = d² */ parse arg hi . /*obtain optional argument from the CL.*/ if hi== | hi=="," then hi=2200 /*Not specified? Then use the default.*/ high=hi * 3 /*D can be three times the HI (max).*/ @.=. /*array of integers (≤ hi) squared.*/ dbs.= /* " " differences between squares.*/

     do s=1  for high;  ss=s*s;  r.ss=s; @.s=ss /*precompute squares and square roots. */
     end  /*s*/
     do    c=1   for high;       cc=@.c         /*precompute possible differences.     */
        do d=c+1  to high;       dif=@.d - cc   /*process  D  squared; calc differences*/
        if wordpos(cc, dbs.dif)==0  then dbs.dif=dbs.dif cc     /*Not in list?  Add it.*/
        end   /*d*/
     end      /*c*/

d.=. /*array of possible solutions (D) */

     do     a=1  for hi-2                       /*go hunting for solutions to equation.*/
        do  b=a   to hi-1;         ab=@.a + @.b /*calculate sum of  2  (A,B)   squares.*/
        if dbs.ab==  then iterate             /*Not a difference?   Then ignore it.  */
           do n=1  for words(dbs.ab)            /*handle all ints that satisfy equation*/
           x=word(dbs.ab, n)                    /*get a C integer from the DBS.AB list.*/
           abc=ab + x                           /*add the  C²  integer  to  A²  +  B²  */
           _=r.abc                              /*retrieve the square root  of  C²     */
           d._=                                 /*mark the  D  integer as being found. */
           end   /*n*/
        end      /*b*/
     end         /*a*/

say say 'Not possible positive integers for d ≤' hi " using equation: a² + b² + c² = d²" say $= /* [↓] find all the "not possibles". */

      do p=1  for hi;   if d.p==.  then $=$ p   /*Not possible? Then add it to the list*/
      end   /*p*/                               /* [↓]  display list of not-possibles. */

say substr($, 2) /*stick a fork in it, we're all done. */</lang>

output   is the same as the 1st REXX version.



zkl

Translation of: ALGOL 68

<lang zkl># find values of d where d^2 =/= a^2 + b^2 + c^2 for any integers a, b, c #

  1. where d in [1..2200], a, b, c =/= 0 #
  2. max number to check #

const max_number = 2200; const max_square = max_number * max_number;

  1. table of numbers that can be the sum of two squares #

sum_of_two_squares:=Data(max_square+1,Int).fill(0); # 4 meg byte array foreach a in ([1..max_number]){

  a2 := a * a;
  foreach b in ([a..max_number]){
     sum2 := ( b * b ) + a2;
     if(sum2 <= max_square) sum_of_two_squares[ sum2 ] = True;  # True-->1
  }

}

  1. now find d such that d^2 - c^2 is in sum of two squares #

solution:=Data(max_number+1,Int).fill(0); # another byte array foreach d in ([1..max_number]){

  d2 := d * d;
  foreach c in ([1..d-1]){
     diff2 := d2 - ( c * c );
     if(sum_of_two_squares[ diff2 ]){ solution[ d ] = True; break; }
  }

}

  1. print the numbers whose squares are not the sum of three squares #

foreach d in ([1..max_number]){

  if(not solution[ d ]) print(d, " ");

} println();</lang>

Output:
1 2 4 5 8 10 16 20 32 40 64 80 128 160 256 320 512 640 1024 1280 2048