Skip to content

Commit 3cb1d3e

Browse files
ManpreetXSinghsedatguzelsemme
authored andcommitted
Performance: 80% faster Project Euler 145 (TheAlgorithms#10445)
* Performance: 80% faster Project Euler145 * Added timeit benchmark * >>> slow_solution() doctest
1 parent 4a3935e commit 3cb1d3e

File tree

1 file changed

+63
-7
lines changed

1 file changed

+63
-7
lines changed

Diff for: project_euler/problem_145/sol1.py

+63-7
Original file line numberDiff line numberDiff line change
@@ -17,17 +17,17 @@
1717
ODD_DIGITS = [1, 3, 5, 7, 9]
1818

1919

20-
def reversible_numbers(
20+
def slow_reversible_numbers(
2121
remaining_length: int, remainder: int, digits: list[int], length: int
2222
) -> int:
2323
"""
2424
Count the number of reversible numbers of given length.
2525
Iterate over possible digits considering parity of current sum remainder.
26-
>>> reversible_numbers(1, 0, [0], 1)
26+
>>> slow_reversible_numbers(1, 0, [0], 1)
2727
0
28-
>>> reversible_numbers(2, 0, [0] * 2, 2)
28+
>>> slow_reversible_numbers(2, 0, [0] * 2, 2)
2929
20
30-
>>> reversible_numbers(3, 0, [0] * 3, 3)
30+
>>> slow_reversible_numbers(3, 0, [0] * 3, 3)
3131
100
3232
"""
3333
if remaining_length == 0:
@@ -51,7 +51,7 @@ def reversible_numbers(
5151
result = 0
5252
for digit in range(10):
5353
digits[length // 2] = digit
54-
result += reversible_numbers(
54+
result += slow_reversible_numbers(
5555
0, (remainder + 2 * digit) // 10, digits, length
5656
)
5757
return result
@@ -67,7 +67,7 @@ def reversible_numbers(
6767

6868
for digit2 in other_parity_digits:
6969
digits[(length - remaining_length) // 2] = digit2
70-
result += reversible_numbers(
70+
result += slow_reversible_numbers(
7171
remaining_length - 2,
7272
(remainder + digit1 + digit2) // 10,
7373
digits,
@@ -76,6 +76,42 @@ def reversible_numbers(
7676
return result
7777

7878

79+
def slow_solution(max_power: int = 9) -> int:
80+
"""
81+
To evaluate the solution, use solution()
82+
>>> slow_solution(3)
83+
120
84+
>>> slow_solution(6)
85+
18720
86+
>>> slow_solution(7)
87+
68720
88+
"""
89+
result = 0
90+
for length in range(1, max_power + 1):
91+
result += slow_reversible_numbers(length, 0, [0] * length, length)
92+
return result
93+
94+
95+
def reversible_numbers(
96+
remaining_length: int, remainder: int, digits: list[int], length: int
97+
) -> int:
98+
"""
99+
Count the number of reversible numbers of given length.
100+
Iterate over possible digits considering parity of current sum remainder.
101+
>>> reversible_numbers(1, 0, [0], 1)
102+
0
103+
>>> reversible_numbers(2, 0, [0] * 2, 2)
104+
20
105+
>>> reversible_numbers(3, 0, [0] * 3, 3)
106+
100
107+
"""
108+
# There exist no reversible 1, 5, 9, 13 (ie. 4k+1) digit numbers
109+
if (length - 1) % 4 == 0:
110+
return 0
111+
112+
return slow_reversible_numbers(length, 0, [0] * length, length)
113+
114+
79115
def solution(max_power: int = 9) -> int:
80116
"""
81117
To evaluate the solution, use solution()
@@ -92,5 +128,25 @@ def solution(max_power: int = 9) -> int:
92128
return result
93129

94130

131+
def benchmark() -> None:
132+
"""
133+
Benchmarks
134+
"""
135+
# Running performance benchmarks...
136+
# slow_solution : 292.9300301000003
137+
# solution : 54.90970860000016
138+
139+
from timeit import timeit
140+
141+
print("Running performance benchmarks...")
142+
143+
print(f"slow_solution : {timeit('slow_solution()', globals=globals(), number=10)}")
144+
print(f"solution : {timeit('solution()', globals=globals(), number=10)}")
145+
146+
95147
if __name__ == "__main__":
96-
print(f"{solution() = }")
148+
print(f"Solution : {solution()}")
149+
benchmark()
150+
151+
# for i in range(1, 15):
152+
# print(f"{i}. {reversible_numbers(i, 0, [0]*i, i)}")

0 commit comments

Comments
 (0)