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

* Fixes: #3869: Optimize Project Euler's Problem 74's  Solution 2

* updating DIRECTORY.md

Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com>
This commit is contained in:
tacitvenom 2020-11-20 04:14:08 +00:00 committed by GitHub
parent 2885a8cd99
commit 83b8b3c141
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -16,9 +16,13 @@
the chains of non repeating items. the chains of non repeating items.
The generation of the chain stops before a repeating item The generation of the chain stops before a repeating item
or if the size of the chain is greater then the desired one. 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: def factorial(a: int) -> int:
"""Returns the factorial of the input a """Returns the factorial of the input a
@ -36,18 +40,23 @@ def factorial(a: int) -> int:
if a < 0: if a < 0:
raise ValueError("Invalid negative input!", a) raise ValueError("Invalid negative input!", a)
if a in factorial_cache:
return factorial_cache[a]
# The case of 0! is handled separately # The case of 0! is handled separately
if a == 0: if a == 0:
return 1 factorial_cache[a] = 1
else: else:
# use a temporary support variable to store the computation # use a temporary support variable to store the computation
temporary_number = a
temporary_computation = 1 temporary_computation = 1
while a > 0: while temporary_number > 0:
temporary_computation *= a temporary_computation *= temporary_number
a -= 1 temporary_number -= 1
return temporary_computation factorial_cache[a] = temporary_computation
return factorial_cache[a]
def factorial_sum(a: int) -> int: def factorial_sum(a: int) -> int:
@ -57,7 +66,8 @@ def factorial_sum(a: int) -> int:
>>> factorial_sum(69) >>> factorial_sum(69)
363600 363600
""" """
if a in factorial_sum_cache:
return factorial_sum_cache[a]
# Prepare a variable to hold the computation # Prepare a variable to hold the computation
fact_sum = 0 fact_sum = 0
@ -67,17 +77,15 @@ def factorial_sum(a: int) -> int:
""" """
for i in str(a): for i in str(a):
fact_sum += factorial(int(i)) fact_sum += factorial(int(i))
factorial_sum_cache[a] = fact_sum
return fact_sum return fact_sum
def solution(chain_length: int = 60, number_limit: int = 1000000) -> int: def solution(chain_length: int = 60, number_limit: int = 1000000) -> int:
"""Returns the number of numbers that produce """Returns the number of numbers that produce
chains with exactly 60 non repeating elements. chains with exactly 60 non repeating elements.
>>> solution(60,1000000) >>> solution(10, 1000)
402 26
>>> solution(15,1000000)
17800
""" """
# the counter for the chains with the exact desired length # the counter for the chains with the exact desired length
@ -86,25 +94,27 @@ def solution(chain_length: int = 60, number_limit: int = 1000000) -> int:
for i in range(1, number_limit + 1): for i in range(1, number_limit + 1):
# The temporary list will contain the elements of the chain # 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 # The new element of the chain
new_chain_element = factorial_sum(chain_list[-1]) new_chain_element = factorial_sum(last_chain_element)
""" Stop computing the chain when you find a repeating item # Stop computing the chain when you find a repeating item
or the length it greater then the desired one. # 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]) while new_chain_element not in chain_set and len_chain_set <= chain_length:
chain_set.add(new_chain_element)
""" If the while exited because the chain list contains the exact amount of elements len_chain_set += 1
increase the counter last_chain_element = new_chain_element
""" new_chain_element = factorial_sum(last_chain_element)
chain_counter += len(chain_list) == chain_length
# 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 return chain_counter