A Pythagorean triple is defined as three positive integers 



(
a
,
b
,
c
)


{\displaystyle (a,b,c)}

 where 



a
<
b
<
c


{\displaystyle a<b<c}

, and 




a

2


+

b

2


=

c

2


.


{\displaystyle a^{2}+b^{2}=c^{2}.}



They are called primitive triples if 



a
,
b
,
c


{\displaystyle a,b,c}

 are co-prime, that is, if their pairwise greatest common divisors 





g
c
d


(
a
,
b
)
=


g
c
d


(
a
,
c
)
=


g
c
d


(
b
,
c
)
=
1


{\displaystyle {\rm {gcd}}(a,b)={\rm {gcd}}(a,c)={\rm {gcd}}(b,c)=1}

.

Because of their relationship through the Pythagorean theorem, a, b, and c are co-prime if a and b are co-prime (





g
c
d


(
a
,
b
)
=
1


{\displaystyle {\rm {gcd}}(a,b)=1}

).  

Each triple forms the length of the sides of a right triangle, whose perimeter is 



P
=
a
+
b
+
c


{\displaystyle P=a+b+c}

.



Task

The task is to determine how many Pythagorean triples there are with a perimeter no larger than 100 and the number of these that are primitive.



Extra credit
 
Deal with large values.   Can your program handle a maximum perimeter of 1,000,000?   What about 10,000,000?   100,000,000?

Note: the extra credit is not for you to demonstrate how fast your language is compared to others;   you need a proper algorithm to solve them in a timely manner.



Related tasks

   Euler's sum of powers conjecture 
   List comprehensions
   Pythagorean quadruples 


 
link numbers
link printf
 
procedure main(A)  # P-triples
 
   plimit := (0 < integer(\A[1])) | 100 # get perimiter limit
 
   nonprimitiveS := set()  # record unique non-primitives triples
   primitiveS := set()     # record unique primitive triples
 
   u :=  0
   while (g := (u +:= 1)^2) + 3 * u + 2 < plimit / 2 do {
      every v := seq(1) do {
         a := g + (i := 2*u*v)
         b := (h := 2*v^2) + i
         c := g + h + i
         if (p := a + b + c) > plimit then break 
 
         insert( (gcd(u,v)=1 & u%2=1, primitiveS) | nonprimitiveS, memo(a,b,c)) 
         every k := seq(2) do {      # k is for larger non-primitives          
            if k*p > plimit then break      
            insert(nonprimitiveS,memo(a*k,b*k,c*k) )
            }
         }
      }
 
printf("Under perimiter=%d: Pythagorean Triples=%d including primitives=%d\n",
       plimit,*nonprimitiveS+*primitiveS,*primitiveS) 
 
every put(gcol := []  , &collections)
printf("Time=%d, Collections: total=%d string=%d block=%d",&time,gcol[1],gcol[3],gcol[4])
end
 
 
procedure memo(x[]) #: return a csv string of arguments in sorted order
every (s := "") ||:= !sort(x) do s ||:= ","
return s[1:-1]
end