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
(A version that uses brute force to find primitives)
 
m (Somewhere in there I got rid of the need for 12 as a BigInteger, reformat)
 
(15 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]]). After using those rules to eliminate candidates for a,b pairs, it checks that a and b are coprime. Since many a,b pair candidates have already been eliminated, this check actually speeds things up a little bit by letting the program skip some c loops. For a perimeter limit of 1000, it is about 35 times faster than [[Pythagorean triples#Java|the other brute force version]]. For a perimeter limit of 10000, it is about 517 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>TreeSet</code> for easy sorting and to remove duplicates (the GCD check should remove duplicates, but it's nice to make 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.
<lang java5>import java.math.BigInteger;
import java.util.Set;
import java.util.TreeSet;
import static java.math.BigInteger.ONE;
 
import static java.math.BigInteger.*;
public class PythTrip2{
 
public static final BigInteger TWO = BigInteger.valueOf(2);
public class PythTrip{
public static final BigInteger THREE = BigInteger.valueOf(3);
publicprivate static final BigInteger FourTWO = BigInteger.valueOf(42);,
private static B3 = BigInteger.valueOf(3), LIMITB4 = BigInteger.valueOf(1004);,
B7 = BigInteger.valueOf(7), B31 = BigInteger.valueOf(31),
B127 = BigInteger.valueOf(127), B191 = BigInteger.valueOf(191);
public static class Triple implements Comparable<Triple>{
//change this to whatever perimeter limit you want;the RAM's the limit
BigInteger a, b, c, peri;
private static BigInteger LIMIT = BigInteger.valueOf(100);
 
public Triple(BigInteger a, BigInteger b, BigInteger c) {
public static class Triple implements Comparable<Triple>{
this.a = a;
BigInteger a, this.b, =c, bperi;
boolean this.c = cprim;
 
peri = a.add(b).add(c);
public Triple(BigInteger a, BigInteger b, BigInteger c, boolean prim){
}
this.a = a;
publicthis.b Triple= scale(long k){b;
this.c = c;
return new Triple(a.multiply(BigInteger.valueOf(k)),
peri = ba.multiplyadd(BigIntegerb).valueOfadd(k)c),;
this.prim = prim;
c.multiply(BigInteger.valueOf(k)));
}
 
public Triple scale(long @Overridek){
publicreturn booleannew equalsTriple(Object obja.multiply(BigInteger.valueOf(k)), {b
if .multiply(objBigInteger.getClassvalueOf(k)), != thisc.getClassmultiply()) return false;BigInteger
Triple trip .valueOf(k)), prim && k == (Triple1)obj;
}
return a.equals(trip.a) && b.equals(trip.b) && c.equals(trip.c);
 
}
@Override
public boolean equals(Object @Overrideobj){
publicif(obj.getClass() int!= compareTothis.getClass(Triple o) {)
if(!a.equals(o.a)) return a.compareTo(o.a)false;
Triple trip = if(!b.equals(o.b)Triple) return b.compareTo(o.b)obj;
return a.equals(trip.a) && if(!cb.equals(otrip.c)b) return&& c.compareToequals(otrip.c);
return 0;}
 
}
@Override
public int compareTo(Triple @Overrideo){
public String toStringif(!a.equals(o.a)){
return a + ", " + b + ", " + c.compareTo(o.a);
}if(!b.equals(o.b))
return b.compareTo(o.b);
}
if(!c.equals(o.c))
private static Set<Triple> trips = new TreeSet<Triple> return c.compareTo(o.c);
return 0;
}
public static void addAllScales(Triple trip){
 
long k = 1;
public String toString(){
Triple tripCopy = new Triple(trip.a, trip.b, trip.c);
return a + ", " + b + ", " + c + (prim ? " primitive" : "");
while(tripCopy.peri.compareTo(LIMIT) < 0){
trips.add(tripCopy);}
}
tripCopy = trip.scale(k++);
 
}
private static Set<Triple> trips = new TreeSet<Triple>();
}
 
public static void addAllScales(Triple trip){
long k = 2;
Triple tripCopy = trip.scale(k++);
while(tripCopy.peri.compareTo(LIMIT) <= 0){
trips.add(tripCopy);
tripCopy = trip.scale(k++);
}
}
 
public static void main(String[] args){
long primCount = 0;
long start = System.currentTimeMillis();
 
//change this to whatever perimeter limit you want;the RAM's the limit
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)){
BigInteger//skip bbif =both or neither of a and b.multiply(b); are divisible by 3 and 4
//if(amod3 a^2 +== b^2 is not a perfect square then don't even test for c's.mod(B3).equals(ZERO)
if(aa || amod4 == b.addmod(bbB4).toStringequals(ZERO).matches(".*[2378]")) continue;
continue;
//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.gcd(b).equals(ONE))
continue;
BigInteger ab = a.add(b);
 
BigInteger aabb = aa.add(bb);
// c is always odd for primitives so if b is odd start at b+2
for(BigInteger c = b.add(b.and(ONE).equals(ONE)? TWO:ONE);
// otherwise c.compareTo(peri2) < 0; c = c.add(TWO)){b+1
for(BigInteger c = b.add(b.testBit(0) ? ZERO : ONE); c
.compareTo(peri2) < 0; c = c.add(TWO)){
 
// if a+b+c > periLimit
if(ab.add(c).compareTo(LIMIT) > 0) break;
 
int compare = aabb.compareTo(c.multiply(c));
// if a^2 + b+c^2 >!= periLimitc^2
if(ab.add(c).compareTo(LIMIT) > 0){
break;
}
//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)) primCount++;{
addAllScales(prim) primCount++;
addAllScales(prim);
}
}
}
}
}
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
Runtime: 22
Up to a perimeter of 100, there are 17 triples, of which 7 are primitive.</pre>
Anonymous user