Pythagorean triples/Java/Brute force primitives: Difference between revisions

m
Somewhere in there I got rid of the need for 12 as a BigInteger, reformat
m (Save another operation (this way might do the same thing under the hood))
m (Somewhere in there I got rid of the need for 12 as a BigInteger, reformat)
 
(6 intermediate revisions by the same user not shown)
Line 1:
{{works with|Java|1.5+}}
This version brute forces primitive triple candidates and then scales them to find the rest (under the perimeter limit of course). Since it only finds the primitives mathematically it can optimize its candidates based on some of the properties [[wp:Pythagorean_triple#Elementary_properties_of_primitive_Pythagorean_triples|here]] -- namely that a and b have opposite evenness, only one of a and b is divisible by 3, only one of a and b is divisible by 4, c is always odd, and that a<sup>2</sup> + b<sup>2</sup> must be a perfect square (which [[wp:Square_number#Properties|don't ever end in 2, 3, 7, or 8]]). NotablyAfter using those rules to eliminate candidates for a,b pairs, it doesn'tchecks usethat a GCDand functionb toare checkcoprime. forSince primitivesmany (<code>BigInteger.gcd()</code>a,b usespair thecandidates binaryhave GCDalready algorithmbeen eliminated, [[wp:Computational_complexity_of_mathematical_operations#Number_theory|whichthis ischeck O(n<sup>2</sup>)]])actually speeds things up a little bit by letting the program skip some c loops. For a perimeter limit of 1000, it is about 5 times faster than [[Pythagorean triples#Java|the other brute force version]]. For a perimeter limit of 10000, it is about 1517 times faster. It also does not markmarks the primitives.
 
It defines a <code>Triple</code> class which is comparable so it can be placed in a <code>SetTreeSet</code> for easy sorting and to remove duplicates (e.g.the thisGCD algorithmcheck findsshould [15,remove 20duplicates, 25] as a primitive candidate afterbut it's hadnice alreadyto been added by scaling [3, 4,make 5]sure). It also can scale itself by an integer factor.
 
Note: this implementation also keeps all triples in memory. Be mindful of large perimeter limits.
Line 8:
import java.util.Set;
import java.util.TreeSet;
 
import static java.math.BigInteger.*;
 
public class PythTrip2PythTrip{
publicprivate static final BigInteger TWO = BigInteger.valueOf(2),
B3 = BigInteger.valueOf(3), B7B4 = BigInteger.valueOf(74), //B7...B191 are used for skipping non-square "a^2 + b^2"s
B7 = BigInteger.valueOf(7), B12B31 = BigInteger.valueOf(1231),
B127 = BigInteger.valueOf(127), B31B191 = BigInteger.valueOf(31191),;
//change this to whatever perimeter limit you want;the RAM's the limit
B127 = BigInteger.valueOf(127),
private static BigInteger B191LIMIT = BigInteger.valueOf(191100);
 
//change this to whatever perimeter limit you want;the RAM's the limit
privatepublic static BigIntegerclass LIMITTriple =implements BigInteger.valueOf(100);Comparable<Triple>{
BigInteger a, b, c, peri;
boolean prim;
public static class Triple implements Comparable<Triple>{
 
BigInteger a, b, c, peri;
public Triple(BigInteger a, BigInteger b, BigInteger c, boolean prim){
publicthis.a Triple(BigInteger= a, BigInteger b, BigInteger c) {;
this.ab = ab;
this.bc = bc;
peri = thisa.add(b).add(c = c);
perithis.prim = a.add(b).add(c)prim;
}
 
public Triple scale(long k){
return new Triple(a.multiply(BigInteger.valueOf(k)), b
b.multiply(BigInteger.valueOf(k)), c.multiply(BigInteger
c.multiply(BigInteger.valueOf(k)), prim && k == 1);
}
 
@Override
public boolean equals(Object obj) {
if(obj.getClass() != this.getClass()) return false;
return Triple trip = (Triple)objfalse;
Triple return a.equals(trip.a) &&= b.equals(trip.bTriple) && c.equals(trip.c)obj;
return a.equals(trip.a) && b.equals(trip.b) && c.equals(trip.c);
}
 
@Override
public int compareTo(Triple o) {
//sort by a, then b, then c
if(!a.equals(o.a)) return a.compareTo(o.a);
if(!b.equals(o.b)) return ba.compareTo(o.ba);
if(!cb.equals(o.cb)) return c.compareTo(o.c);
return 0b.compareTo(o.b);
}if(!c.equals(o.c))
return c.compareTo(o.c);
@Overridereturn 0;
public String toString(){}
 
return a + ", " + b + ", " + c;
public String }toString(){
return a + ", " + b + ", " + c + (prim ? " primitive" : "");
}
}
}
private static Set<Triple> trips = new TreeSet<Triple>();
 
private static Set<Triple> trips = new TreeSet<Triple>();
public static void addAllScales(Triple trip){
 
long k = 1;
public static void addAllScales(Triple tripCopy = new Triple(trip.a, trip.b, trip.c);{
long k = 12;
while(tripCopy.peri.compareTo(LIMIT) < 0){
Triple tripCopy = tripstrip.addscale(tripCopyk++);
while(tripCopy.peri.compareTo(LIMIT) <= trip.scale(k++0);{
}trips.add(tripCopy);
tripCopy = trip.scale(k++);
}
}
public static void main(String[] args){
}
 
public static void addAllScalesmain(TripleString[] tripargs){
long primCount = 0;
long start = System.currentTimeMillis();
 
BigInteger peri2 = LIMIT.divide(BigIntegerTWO), peri3 = LIMIT.valueOfdivide(2B3)),;
peri3 = LIMIT.divide(BigInteger.valueOf(3));
 
for(BigInteger a = ONEB3; a.compareTo(peri3) < 0; a = a.add(ONE)){
BigInteger aa = a.multiply(a);
boolean amod3 = a.mod(B3).equals(ZERO);
boolean amod4 = a.mod(B4).equals(ZERO);
 
//b is the opposite evenness of a so increment by 2
for(BigInteger b = a.add(ONE); b.compareTo(peri2) < 0; b = b
b.compareTo(peri2) < 0; b = b.add(TWO)){
//skip if a^2both +or b^2neither is notof a perfectand squareb thenare don'tdivisible evenby test3 forand c's4
if(amod3 == b.mod(B3).equals(ZERO)
break;|| amod4 == b.mod(B4).equals(ZERO))
//sort by a, then b, then ccontinue;
//if a^2+b^2 isn't a perfect square, don't even test for c's
BigInteger aabb = aa.add(b.multiply(b));
if((aabb.and(B7).intValue() != 1) &&
&& (aabb.and(B31).intValue() != 4) &&
&& (aabb.and(B127).intValue() != 16) &&
&& (aabb.and(B191).intValue() != 0)) continue;
if(a.multiply(b).mod(B12).compareTo(ZERO) != 0) continue;
if(!a.gcd(b).equals(ONE))
continue;
BigInteger ab = a.add(b);
 
for(BigInteger// c =is always odd for primitives so if b.add(b.testBit(0) ?is TWO:ONE);odd start at b+2
// otherwise c.compareTo(peri2) < 0; c = c.add(TWO)){b+1
for(BigInteger c = b.add(b.testBit(0) //if? a+b+cZERO >: periLimitONE); c
if(ab.add(c) .compareTo(LIMITperi2) >< 0; c = c.add(TWO)){
 
break;
}// if a+b+c > periLimit
while if(tripCopyab.periadd(c).compareTo(LIMIT) <> 0){ break;
 
int compare = aabb.compareTo(c.multiply(c));
// if a^2 + b^2 != c^2
if(compare < 0){
break;
}else if (compare == 0){
Triple prim = new Triple(a, b, c, true);
if(trips.add(prim)){ //if it's new
primCount++; //count it
addAllScales(prim); //add its scales
}
}
Line 111 ⟶ 123:
}
}
for(Triple trip : trips){
System.out.println(trip);
}
System.out.println("Runtime: " + (System.currentTimeMillis() - start));
System.out.println("Up to a perimeter of " + LIMIT + ", there are "
+ trips.size() + " triples, of which " + primCount + " are primitive.");
+ " are primitive.");
}
}</lang>
Output:
<pre>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
Anonymous user