Improve problem 75 in Python.

main
Felix Martin 2019-08-18 13:27:29 -04:00
parent a451cd0db6
commit 45692feacb
1 changed files with 53 additions and 11 deletions

View File

@ -1,4 +1,5 @@
from math import sqrt from math import sqrt
from lib_misc import gcd
def proper_divisors(n): def proper_divisors(n):
@ -28,16 +29,6 @@ def triples_brute_force(b_max):
return triples return triples
def triples_euclids_formula(m, n):
""" Does not return all triples! """
assert(m > n)
assert(n > 0)
a = m * m - n * n
b = 2 * m * n
c = m * m + n * n
return (a, b, c)
def dicksons_method(r): def dicksons_method(r):
triples = [] triples = []
assert(r % 2 == 0) assert(r % 2 == 0)
@ -94,7 +85,7 @@ def dicksons_method_efficient(r):
return perimeters return perimeters
def euler_075(): def euler_075_dicksons():
""" """
We are using Dickson's method to get all Pythagorean triples. The We are using Dickson's method to get all Pythagorean triples. The
challenge is that this method requires finding the divisors for a challenge is that this method requires finding the divisors for a
@ -130,6 +121,57 @@ def euler_075():
return one_integer_sided_right_triangle_count return one_integer_sided_right_triangle_count
def triples_euclids_formula(m, n):
"""
Generates only primitive triples.
https://en.wikipedia.org/wiki/Pythagorean_triple#Generating_a_triple
"""
assert(m > n)
assert(n > 0)
assert(gcd(m, n) == 1)
assert(m % 2 == 0 or n % 2 == 0)
a = m * m - n * n
b = 2 * m * n
c = m * m + n * n
if a < b:
return (a, b, c)
else:
return (b, a, c)
def euler_075():
"""
The range for m was chosen empirically (aka by trial and error).
I tried terminating when L > L_max the first time, but there might
be combinations for m = m + 1 that yield lower L. I guess the right
criteria to return would be if L > L_max and n == 1.
This is good enough for now. I still like my other solution, but it
is so much slower because finding the divisors is so expensive.
"""
L = 0
L_max = 1500000
m = 1
perimeter_counts = {}
for m in range(1, 1000):
for n in range(1, m):
try:
L = sum(triples_euclids_formula(m, n))
L_k = L
while L_k <= L_max:
try:
perimeter_counts[L_k] += 1
except KeyError:
perimeter_counts[L_k] = 1
L_k += L
except AssertionError:
pass
one_integer_sided_right_triangle_count = 0
for perimeter, count in perimeter_counts.items():
if count == 1:
one_integer_sided_right_triangle_count += 1
return one_integer_sided_right_triangle_count
if __name__ == "__main__": if __name__ == "__main__":
print("e075.py: " + str(euler_075())) print("e075.py: " + str(euler_075()))
assert(euler_075() == 161667) assert(euler_075() == 161667)