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 lib_misc import gcd
def proper_divisors(n):
@ -28,16 +29,6 @@ def triples_brute_force(b_max):
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):
triples = []
assert(r % 2 == 0)
@ -94,7 +85,7 @@ def dicksons_method_efficient(r):
return perimeters
def euler_075():
def euler_075_dicksons():
"""
We are using Dickson's method to get all Pythagorean triples. The
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
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__":
print("e075.py: " + str(euler_075()))
assert(euler_075() == 161667)