Reputation: 2393
I've implemented the naive algorithm to compute all pythagorean triples for a given hypotenuse length in Java and Python. For some reason, the Python implementation takes ~20 times longer. Why is this the case?
$ time python PythagoreanTriples.py
[2800, 9600, 3520, 9360, 5376, 8432, 6000, 8000, 8000, 6000, 8432, 5376, 9360, 3520, 9600, 2800]
python PythagoreanTriples.py 13.92s user 0.71s system 87% cpu 16.698 total
$ time java PythagoreanTriples
[2800, 9600, 3520, 9360, 5376, 8432, 6000, 8000, 8000, 6000, 8432, 5376, 9360, 3520, 9600, 2800]
java PythagoreanTriples 0.32s user 0.12s system 72% cpu 0.618 total
The algorithm is to add a
and b
values to an output list in ascending order of a
values and descending order of b
values. Here are the Python and Java programs.
Python:
def pythagorean_triples(c):
"""
:param c: the length of the hypotenuse
:return: a list containing all possible configurations of the other two
sides that are of positive integer length. Output each
configuration as a separate element in a list in the format a b
where a is in ascending order and b is in descending order in
respect to the other configurations.
"""
output = []
c_squared = c * c
for a in xrange(1, c):
a_squared = a * a
for b in xrange(1, c):
b_squared = b * b
if a_squared + b_squared == c_squared:
output.append(a)
output.append(b)
return output
Java:
public static Iterable<Integer> findTriples(int hypotenuse) {
ArrayList<Integer> output = new ArrayList<Integer>();
int c_2 = hypotenuse * hypotenuse;
for(int a = 1; a < hypotenuse; a++) {
int a_2 = a * a;
for(int b = 1; b < hypotenuse; b++) {
int b_2 = b * b;
if(a_2 + b_2 == c_2) {
output.add(a);
output.add(b);
}
}
}
return output;
}
Upvotes: 2
Views: 129
Reputation: 42748
Python is not made for number crunching, but using a faster algorithm solves the problem in a few milli seconds:
def pythagorean_triples(c):
"""
:param c: the length of the hypotenuse
:return: a list containing all possible configurations of the other two
sides that are of positive integer length. Output each
configuration as a separate element in a list in the format a b
where a is in ascending order and b is in descending order in
respect to the other configurations.
"""
output = []
c_squared = c * c
for a in xrange(1, c):
a_squared = a * a
b = int(round((c_squared - a_squared) ** 0.5))
b_squared = b * b
if a_squared + b_squared == c_squared:
output.append(a)
output.append(b)
return output
Upvotes: 0
Reputation: 4316
it seems most of the time is spent doing the multiplication:
because replacing
output = []
c_squared = c * c
for a in xrange(1, c):
a_squared = a * a
for b in xrange(1, c):
b_squared = b * b
if a_squared + b_squared == c_squared:
output.append(a)
output.append(b)
return output
by
all_b_squared = [b*b for b in xrange(1,c)]
output = []
c_squared = c * c
for a in xrange(1, c):
a_squared = a * a
for b_squared in all_b_squared:
if a_squared + b_squared == c_squared:
output.append(a)
output.append(math.b)
return output
on my computer show a substantial gain in performance
also note that (on my computer)
a**2
instead of a*a
is significantly slowerI recommend you vprof
and pprofile
(pip install vprof
) to profile line by line your method
it can be explained because int
in python are a full object and not only a 32bit variable in your ram which will not overflow, at the opposite of the java integer.
Upvotes: 1