Skip to content

Fixes: #3869: Optimize CI runtime of Project Euler's Problem 74's Solution 2 #3893

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Nov 20, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions DIRECTORY.md
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,7 @@
* [Heaps Algorithm](https://github.com/TheAlgorithms/Python/blob/master/divide_and_conquer/heaps_algorithm.py)
* [Heaps Algorithm Iterative](https://github.com/TheAlgorithms/Python/blob/master/divide_and_conquer/heaps_algorithm_iterative.py)
* [Inversions](https://github.com/TheAlgorithms/Python/blob/master/divide_and_conquer/inversions.py)
* [Kth Order Statistic](https://github.com/TheAlgorithms/Python/blob/master/divide_and_conquer/kth_order_statistic.py)
* [Max Subarray Sum](https://github.com/TheAlgorithms/Python/blob/master/divide_and_conquer/max_subarray_sum.py)
* [Mergesort](https://github.com/TheAlgorithms/Python/blob/master/divide_and_conquer/mergesort.py)
* [Power](https://github.com/TheAlgorithms/Python/blob/master/divide_and_conquer/power.py)
Expand Down Expand Up @@ -389,6 +390,7 @@
* [Chudnovsky Algorithm](https://github.com/TheAlgorithms/Python/blob/master/maths/chudnovsky_algorithm.py)
* [Collatz Sequence](https://github.com/TheAlgorithms/Python/blob/master/maths/collatz_sequence.py)
* [Combinations](https://github.com/TheAlgorithms/Python/blob/master/maths/combinations.py)
* [Decimal Isolate](https://github.com/TheAlgorithms/Python/blob/master/maths/decimal_isolate.py)
* [Entropy](https://github.com/TheAlgorithms/Python/blob/master/maths/entropy.py)
* [Eulers Totient](https://github.com/TheAlgorithms/Python/blob/master/maths/eulers_totient.py)
* [Explicit Euler](https://github.com/TheAlgorithms/Python/blob/master/maths/explicit_euler.py)
Expand Down Expand Up @@ -492,6 +494,7 @@
* [Autocomplete Using Trie](https://github.com/TheAlgorithms/Python/blob/master/other/autocomplete_using_trie.py)
* [Binary Exponentiation](https://github.com/TheAlgorithms/Python/blob/master/other/binary_exponentiation.py)
* [Binary Exponentiation 2](https://github.com/TheAlgorithms/Python/blob/master/other/binary_exponentiation_2.py)
* [Davis–Putnam–Logemann–Loveland](https://github.com/TheAlgorithms/Python/blob/master/other/davis–putnam–logemann–loveland.py)
* [Detecting English Programmatically](https://github.com/TheAlgorithms/Python/blob/master/other/detecting_english_programmatically.py)
* [Dijkstra Bankers Algorithm](https://github.com/TheAlgorithms/Python/blob/master/other/dijkstra_bankers_algorithm.py)
* [Doomsday](https://github.com/TheAlgorithms/Python/blob/master/other/doomsday.py)
Expand Down Expand Up @@ -659,6 +662,8 @@
* [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_048/sol1.py)
* Problem 049
* [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_049/sol1.py)
* Problem 050
* [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_050/sol1.py)
* Problem 051
* [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_051/sol1.py)
* Problem 052
Expand All @@ -680,6 +685,8 @@
* [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_062/sol1.py)
* Problem 063
* [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_063/sol1.py)
* Problem 064
* [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_064/sol1.py)
* Problem 065
* [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_065/sol1.py)
* Problem 067
Expand All @@ -693,6 +700,7 @@
* [Sol2](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_072/sol2.py)
* Problem 074
* [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_074/sol1.py)
* [Sol2](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_074/sol2.py)
* Problem 075
* [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_075/sol1.py)
* Problem 076
Expand All @@ -717,6 +725,8 @@
* [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_119/sol1.py)
* Problem 120
* [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_120/sol1.py)
* Problem 123
* [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_123/sol1.py)
* Problem 125
* [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_125/sol1.py)
* Problem 173
Expand All @@ -725,12 +735,16 @@
* [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_174/sol1.py)
* Problem 191
* [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_191/sol1.py)
* Problem 203
* [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_203/sol1.py)
* Problem 206
* [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_206/sol1.py)
* Problem 207
* [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_207/sol1.py)
* Problem 234
* [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_234/sol1.py)
* Problem 301
* [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_301/sol1.py)
* Problem 551
* [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_551/sol1.py)

Expand Down
68 changes: 39 additions & 29 deletions project_euler/problem_074/sol2.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,13 @@
the chains of non repeating items.
The generation of the chain stops before a repeating item
or if the size of the chain is greater then the desired one.
After generating each chain, the length is checked and the counter increases.
After generating each chain, the length is checked and the
counter increases.
"""

factorial_cache = {}
factorial_sum_cache = {}


def factorial(a: int) -> int:
"""Returns the factorial of the input a
Expand All @@ -36,18 +40,23 @@ def factorial(a: int) -> int:
if a < 0:
raise ValueError("Invalid negative input!", a)

if a in factorial_cache:
return factorial_cache[a]

# The case of 0! is handled separately
if a == 0:
return 1
factorial_cache[a] = 1
else:
# use a temporary support variable to store the computation
temporary_number = a
temporary_computation = 1

while a > 0:
temporary_computation *= a
a -= 1
while temporary_number > 0:
temporary_computation *= temporary_number
temporary_number -= 1

return temporary_computation
factorial_cache[a] = temporary_computation
return factorial_cache[a]


def factorial_sum(a: int) -> int:
Expand All @@ -57,7 +66,8 @@ def factorial_sum(a: int) -> int:
>>> factorial_sum(69)
363600
"""

if a in factorial_sum_cache:
return factorial_sum_cache[a]
# Prepare a variable to hold the computation
fact_sum = 0

Expand All @@ -67,17 +77,15 @@ def factorial_sum(a: int) -> int:
"""
for i in str(a):
fact_sum += factorial(int(i))

factorial_sum_cache[a] = fact_sum
return fact_sum


def solution(chain_length: int = 60, number_limit: int = 1000000) -> int:
"""Returns the number of numbers that produce
chains with exactly 60 non repeating elements.
>>> solution(60,1000000)
402
>>> solution(15,1000000)
17800
>>> solution(10, 1000)
26
"""

# the counter for the chains with the exact desired length
Expand All @@ -86,25 +94,27 @@ def solution(chain_length: int = 60, number_limit: int = 1000000) -> int:
for i in range(1, number_limit + 1):

# The temporary list will contain the elements of the chain
chain_list = [i]
chain_set = {i}
len_chain_set = 1
last_chain_element = i

# The new element of the chain
new_chain_element = factorial_sum(chain_list[-1])

""" Stop computing the chain when you find a repeating item
or the length it greater then the desired one.
"""
while not (new_chain_element in chain_list) and (
len(chain_list) <= chain_length
):
chain_list += [new_chain_element]

new_chain_element = factorial_sum(chain_list[-1])

""" If the while exited because the chain list contains the exact amount of elements
increase the counter
"""
chain_counter += len(chain_list) == chain_length
new_chain_element = factorial_sum(last_chain_element)

# Stop computing the chain when you find a repeating item
# or the length it greater then the desired one.

while new_chain_element not in chain_set and len_chain_set <= chain_length:
chain_set.add(new_chain_element)

len_chain_set += 1
last_chain_element = new_chain_element
new_chain_element = factorial_sum(last_chain_element)

# If the while exited because the chain list contains the exact amount
# of elements increase the counter
if len_chain_set == chain_length:
chain_counter += 1

return chain_counter

Expand Down