From 11ab30bab656bc5536486df580313f679e32a482 Mon Sep 17 00:00:00 2001 From: Freddy Pringle Date: Fri, 9 Oct 2020 18:17:09 +0200 Subject: [PATCH 1/5] Added solution for Project Euler problem 75. Fixes: #2695 --- project_euler/problem_75/__init__.py | 0 project_euler/problem_75/sol1.py | 47 ++++++++++++++++++++++++++++ 2 files changed, 47 insertions(+) create mode 100644 project_euler/problem_75/__init__.py create mode 100644 project_euler/problem_75/sol1.py diff --git a/project_euler/problem_75/__init__.py b/project_euler/problem_75/__init__.py new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/project_euler/problem_75/sol1.py b/project_euler/problem_75/sol1.py new file mode 100644 index 000000000000..9f3d93021b0e --- /dev/null +++ b/project_euler/problem_75/sol1.py @@ -0,0 +1,47 @@ +""" +It turns out that 12 cm is the smallest length of wire that can be bent to form an +integer sided right angle triangle in exactly one way, but there are many more examples. + +12 cm: (3,4,5) +24 cm: (6,8,10) +30 cm: (5,12,13) +36 cm: (9,12,15) +40 cm: (8,15,17) +48 cm: (12,16,20) + +In contrast, some lengths of wire, like 20 cm, cannot be bent to form an integer sided +right angle triangle, and other lengths allow more than one solution to be found; for +example, using 120 cm it is possible to form exactly three different integer sided +right angle triangles. + +120 cm: (30,40,50), (20,48,52), (24,45,51) + +Given that L is the length of the wire, for how many values of L ≤ 1,500,000 can +exactly one integer sided right angle triangle be formed? +""" + +from collections import defaultdict +from math import gcd +from typing import DefaultDict + + +def solution(limit: int = 1500000) -> int: + """ + Return the number of values of L <= limit such that a wire of length L can be + formmed into an integer sided right angle triangle in exactly one way. + """ + freqs: DefaultDict = defaultdict(int) + m = 2 + while 2 * m * (m + 1) <= limit: + for n in range((m % 2) + 1, m, 2): + if gcd(m, n) > 1: + continue + perim = 2 * m * (m + n) + for p in range(perim, limit + 1, perim): + freqs[p] += 1 + m += 1 + return sum(1 for v in freqs.values() if v == 1) + + +if __name__ == "__main__": + print(solution()) From 0343b15f9c9e206c8acf9f5057db9d8b9a9beb6b Mon Sep 17 00:00:00 2001 From: Freddy Pringle Date: Sat, 10 Oct 2020 10:38:53 +0200 Subject: [PATCH 2/5] Added doctest for solution() in project_euler/problem_75/sol1.py --- project_euler/problem_75/sol1.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/project_euler/problem_75/sol1.py b/project_euler/problem_75/sol1.py index 9f3d93021b0e..b29b5306aa2e 100644 --- a/project_euler/problem_75/sol1.py +++ b/project_euler/problem_75/sol1.py @@ -29,6 +29,10 @@ def solution(limit: int = 1500000) -> int: """ Return the number of values of L <= limit such that a wire of length L can be formmed into an integer sided right angle triangle in exactly one way. + >>> solution(50) + 6 + >>> solution(1000) + 112 """ freqs: DefaultDict = defaultdict(int) m = 2 From bc9f7382eeceffa1d8238c3005c5117fd18a6ad3 Mon Sep 17 00:00:00 2001 From: Freddy Pringle Date: Thu, 15 Oct 2020 10:48:27 +0200 Subject: [PATCH 3/5] Update docstring and 0-padding of directory name. Reference: #3256 --- project_euler/{problem_75 => problem_075}/__init__.py | 0 project_euler/{problem_75 => problem_075}/sol1.py | 4 +++- 2 files changed, 3 insertions(+), 1 deletion(-) rename project_euler/{problem_75 => problem_075}/__init__.py (100%) rename project_euler/{problem_75 => problem_075}/sol1.py (94%) diff --git a/project_euler/problem_75/__init__.py b/project_euler/problem_075/__init__.py similarity index 100% rename from project_euler/problem_75/__init__.py rename to project_euler/problem_075/__init__.py diff --git a/project_euler/problem_75/sol1.py b/project_euler/problem_075/sol1.py similarity index 94% rename from project_euler/problem_75/sol1.py rename to project_euler/problem_075/sol1.py index b29b5306aa2e..f6e5bd07a3d0 100644 --- a/project_euler/problem_75/sol1.py +++ b/project_euler/problem_075/sol1.py @@ -1,4 +1,6 @@ """ +Project Euler Problem 75: https://projecteuler.net/problem=75 + It turns out that 12 cm is the smallest length of wire that can be bent to form an integer sided right angle triangle in exactly one way, but there are many more examples. @@ -48,4 +50,4 @@ def solution(limit: int = 1500000) -> int: if __name__ == "__main__": - print(solution()) + print(f"{solution() = }") From 908914e91c47969938e415ec9b316d9823f517ef Mon Sep 17 00:00:00 2001 From: Freddy Pringle Date: Fri, 16 Oct 2020 11:49:42 +0200 Subject: [PATCH 4/5] More descriptive variable names --- project_euler/problem_075/sol1.py | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/project_euler/problem_075/sol1.py b/project_euler/problem_075/sol1.py index f6e5bd07a3d0..2cdc041ecedc 100644 --- a/project_euler/problem_075/sol1.py +++ b/project_euler/problem_075/sol1.py @@ -35,18 +35,24 @@ def solution(limit: int = 1500000) -> int: 6 >>> solution(1000) 112 + >>> solution(50000) + 5502 + + Solution: we generate all pythagorean triples using Euclid's formula and + keep track of the frequencies of the perimeters. + Reference: https://en.wikipedia.org/wiki/Pythagorean_triple#Generating_a_triple """ - freqs: DefaultDict = defaultdict(int) - m = 2 - while 2 * m * (m + 1) <= limit: - for n in range((m % 2) + 1, m, 2): - if gcd(m, n) > 1: + frequencies: DefaultDict = defaultdict(int) + euclid_m = 2 + while 2 * euclid_m * (euclid_m + 1) <= limit: + for euclid_n in range((euclid_m % 2) + 1, euclid_m, 2): + if gcd(euclid_m, euclid_n) > 1: continue - perim = 2 * m * (m + n) - for p in range(perim, limit + 1, perim): - freqs[p] += 1 - m += 1 - return sum(1 for v in freqs.values() if v == 1) + primitive_perimeter = 2 * euclid_m * (euclid_m + euclid_n) + for perimeter in range(primitive_perimeter, limit + 1, primitive_perimeter): + frequencies[perimeter] += 1 + euclid_m += 1 + return sum(1 for frequency in frequencies.values() if frequency == 1) if __name__ == "__main__": From d64377f7d3f442dd5d61322e9b3cb581331b3a20 Mon Sep 17 00:00:00 2001 From: Freddy Pringle Date: Fri, 16 Oct 2020 11:53:12 +0200 Subject: [PATCH 5/5] Moved solution explanation to module-level docstring --- project_euler/problem_075/sol1.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/project_euler/problem_075/sol1.py b/project_euler/problem_075/sol1.py index 2cdc041ecedc..b57604d76a86 100644 --- a/project_euler/problem_075/sol1.py +++ b/project_euler/problem_075/sol1.py @@ -20,6 +20,11 @@ Given that L is the length of the wire, for how many values of L ≤ 1,500,000 can exactly one integer sided right angle triangle be formed? + +Solution: we generate all pythagorean triples using Euclid's formula and +keep track of the frequencies of the perimeters. + +Reference: https://en.wikipedia.org/wiki/Pythagorean_triple#Generating_a_triple """ from collections import defaultdict @@ -37,10 +42,6 @@ def solution(limit: int = 1500000) -> int: 112 >>> solution(50000) 5502 - - Solution: we generate all pythagorean triples using Euclid's formula and - keep track of the frequencies of the perimeters. - Reference: https://en.wikipedia.org/wiki/Pythagorean_triple#Generating_a_triple """ frequencies: DefaultDict = defaultdict(int) euclid_m = 2