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 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
@ -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:
@ -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
@ -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
@ -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])
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 not (new_chain_element in chain_list) and (
len(chain_list) <= chain_length
):
chain_list += [new_chain_element]
# Stop computing the chain when you find a repeating item
# or the length it greater then the desired one.
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
increase the counter
"""
chain_counter += len(chain_list) == chain_length
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