Pythagorean triples: Difference between revisions

From Rosetta Code
Content added Content deleted
(→‎{{header|C}}: semi-optimized code)
m (→‎{{header|Java}}: Added optimizations inspired by C, hey cool my IDE at home converted tabs to spaces for me)
Line 63: Line 63:
=={{header|Java}}==
=={{header|Java}}==
[[Category:Arbitrary precision]]Theoretically, this can go "forever", but it takes a while, so only the minimum is shown. Luckily, <code>BigInteger</code> has a GCD method built in.
[[Category:Arbitrary precision]]Theoretically, this can go "forever", but it takes a while, so only the minimum is shown. Luckily, <code>BigInteger</code> has a GCD method built in.
<lang java>import java.math.BigInteger;
<lang java>
import java.math.BigInteger;
import static java.math.BigInteger.ONE;


public class PythTrip{
public class PythTrip{
public static void main(String[] args){
long tripCount = 0, primCount = 0;


public static void main(String[] args){
//change this to whatever perimeter limit you want;the RAM's the limit
long tripCount = 0, primCount = 0;
BigInteger periLimit = new BigInteger("100");


//change this to whatever perimeter limit you want;the RAM's the limit
for(BigInteger a = BigInteger.ONE;
BigInteger periLimit = new BigInteger("10000"),
a.compareTo(periLimit) < 0; a = a.add(BigInteger.ONE)){
peri2 = periLimit.divide(new BigInteger("2")),
peri3 = periLimit.divide(new BigInteger("3"));


for(BigInteger b = new BigInteger(a.toString());
for(BigInteger a = ONE; a.compareTo(peri3) < 0; a = a.add(ONE)){
BigInteger aa = a.multiply(a);
b.compareTo(periLimit) < 0; b = b.add(BigInteger.ONE)){
for(BigInteger b = new BigInteger(a.toString()).add(ONE);
b.compareTo(peri2) < 0; b = b.add(ONE)){
BigInteger bb = b.multiply(b);
BigInteger ab = a.add(b);
BigInteger aabb = aa.add(bb);
for(BigInteger c = new BigInteger(b.toString()).add(ONE);
c.compareTo(peri2) < 0; c = c.add(ONE)){


int compare = aabb.compareTo(c.multiply(c));
for(BigInteger c = new BigInteger(b.toString());
//if a+b+c > periLimit
c.compareTo(periLimit) < 0; c = c.add(BigInteger.ONE)){
if(ab.add(c).compareTo(periLimit) > 0){
break;
}
//if a^2 + b^2 != c^2
if(compare < 0){
break;
}else if (compare == 0){
tripCount++;
System.out.print(a + ", " + b + ", " + c);


//does binary GCD under the hood
//if a+b+c > periLimit
if(a.add(b).add(c).compareTo(periLimit) > 0)break;
if(a.gcd(b).compareTo(ONE) == 0){
System.out.print(" primitive");
//if a^2 + b^2 != c^2
primCount++;
if(a.pow(2).add(b.pow(2)).compareTo(c.pow(2)) != 0)
}
continue;
System.out.println();
}
tripCount++;
}
System.out.print(a +", "+b+", "+c);
}
}
//does binary GCD under the hood
System.out.println("Up to a perimeter of " + periLimit + ", there are "
if(a.gcd(b).compareTo(BigInteger.ONE) == 0){
+ tripCount + " triples, of which " + primCount + " are primitive.");
System.out.print(" primitive");
}
primCount++;
}
System.out.println();
}
}
}
System.out.println("Up to a perimeter of "+periLimit+", there are "+
tripCount+" triples, of which "+primCount+" are primitive.");
}
}</lang>
}</lang>
Output:
Output:

Revision as of 00:53, 29 June 2011

Pythagorean triples 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.

A Pythagorean triple is defined as three positive integers where , and They are called primitive triples if are coprime, that is, if their pairwise greatest common divisors . Because of their relationship through the Pythagorean theorem, a, b, and c are coprime if a and b are coprime (). Each triple forms the length of the sides of a right triangle, whose perimeter is .

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 max 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.

Cf

C

Sample implemention; naive method, patentedly won't scale to larger numbers, despite the attempt to optimize it. Calculating up to 10000 is already a test of patience. <lang C>#include <stdio.h>

  1. include <stdlib.h>

typedef unsigned long long xint; typedef unsigned long ulong;

inline ulong gcd(ulong m, ulong n) { ulong t; while (n) { t = n; n = m % n; m = t; } return m; }

int main() { ulong a, b, c, pytha = 0, prim = 0, max_p = 100; xint aa, bb, cc;

for (a = 1; a <= max_p / 3; a++) { aa = (xint)a * a; printf("a = %lu\r", a); /* show that we are working */ fflush(stdout);

/* max_p/2: valid limit, because one side of triangle * must be less than the sum of the other two */ for (b = a + 1; b < max_p/2; b++) { bb = (xint)b * b; for (c = b + 1; c < max_p/2; c++) { cc = (xint)c * c; if (aa + bb < cc) break; if (a + b + c > max_p) break;

if (aa + bb == cc) { pytha++; if (gcd(a, b) == 1) prim++; } } } }

printf("Up to %lu, there are %lu triples, of which %lu are primitive\n", max_p, pytha, prim);

return 0; }</lang>output:<lang>Up to 100, there are 17 triples, of which 7 are primitive</lang>

Java

Theoretically, this can go "forever", but it takes a while, so only the minimum is shown. Luckily, BigInteger has a GCD method built in.

<lang java> import java.math.BigInteger; import static java.math.BigInteger.ONE;

public class PythTrip{

   public static void main(String[] args){
       long tripCount = 0, primCount = 0;
       //change this to whatever perimeter limit you want;the RAM's the limit
       BigInteger periLimit = new BigInteger("10000"),
               peri2 = periLimit.divide(new BigInteger("2")),
               peri3 = periLimit.divide(new BigInteger("3"));
       for(BigInteger a = ONE; a.compareTo(peri3) < 0; a = a.add(ONE)){
           BigInteger aa = a.multiply(a);
           
           for(BigInteger b = new BigInteger(a.toString()).add(ONE);
                   b.compareTo(peri2) < 0; b = b.add(ONE)){
               BigInteger bb = b.multiply(b);
               BigInteger ab = a.add(b);
               BigInteger aabb = aa.add(bb);
               
               for(BigInteger c = new BigInteger(b.toString()).add(ONE);
                       c.compareTo(peri2) < 0; c = c.add(ONE)){
                   int compare = aabb.compareTo(c.multiply(c));
                   //if a+b+c > periLimit
                   if(ab.add(c).compareTo(periLimit) > 0){
                       break;
                   }
                   //if a^2 + b^2 != c^2
                   if(compare < 0){
                       break;
                   }else if (compare == 0){
                       tripCount++;
                       System.out.print(a + ", " + b + ", " + c);
                       //does binary GCD under the hood
                       if(a.gcd(b).compareTo(ONE) == 0){
                           System.out.print(" primitive");
                           primCount++;
                       }
                       System.out.println();
                   }
               }
           }
       }
       System.out.println("Up to a perimeter of " + periLimit + ", there are "
               + tripCount + " triples, of which " + primCount + " are primitive.");
   }

}</lang> Output:

3, 4, 5 primitive
5, 12, 13 primitive
6, 8, 10
7, 24, 25 primitive
8, 15, 17 primitive
9, 12, 15
9, 40, 41 primitive
10, 24, 26
12, 16, 20
12, 35, 37 primitive
15, 20, 25
15, 36, 39
16, 30, 34
18, 24, 30
20, 21, 29 primitive
21, 28, 35
24, 32, 40
Up to a perimeter of 100, there are 17 triples, of which 7 are primitive.

Python

I could not wait for the answer to triples with a perimeter of 10000, although it should calculate it. <lang python>>>> from fractions import gcd >>> def pt(maxperimeter=100): trips = [] for a in range(1, maxperimeter): aa = a*a for b in range(a, maxperimeter-a): bb = b*b for c in range(b, maxperimeter-b-a): cc = c*c if a+b+c > maxperimeter or cc > aa + bb: break if aa + bb == cc: trips.append((a,b,c, gcd(a, b) == 1)) return trips

>>> def printit(maxperimeter=100): trips = pt(maxperimeter) print("Up to a perimeter of %i there are %i triples, of which %i are primitive"  % (maxperimeter, len(trips), len([prim for a,b,c,prim in trips if prim])))


>>> for i in range(4): printit(10**i)

Up to a perimeter of 1 there are 0 triples, of which 0 are primitive Up to a perimeter of 10 there are 0 triples, of which 0 are primitive Up to a perimeter of 100 there are 17 triples, of which 7 are primitive Up to a perimeter of 1000 there are 324 triples, of which 70 are primitive</lang>