2019-08-02 05:04:43 +02:00
|
|
|
from functools import lru_cache
|
|
|
|
|
|
|
|
|
|
|
|
@lru_cache(maxsize=10)
|
|
|
|
def fac(n):
|
|
|
|
r = 1
|
|
|
|
if n <= 1:
|
|
|
|
return 1
|
|
|
|
for i in range(2, n + 1):
|
|
|
|
r *= i
|
|
|
|
return r
|
|
|
|
|
|
|
|
|
|
|
|
@lru_cache(maxsize=1000000)
|
|
|
|
def get_factorial_sum(n):
|
|
|
|
s = 0
|
|
|
|
for d in get_digits(n):
|
|
|
|
s += fac(d)
|
|
|
|
return s
|
|
|
|
|
|
|
|
|
|
|
|
current_numbers_set = set()
|
|
|
|
|
|
|
|
|
|
|
|
@lru_cache(maxsize=10000000)
|
|
|
|
def get_chain_length(n):
|
|
|
|
""" Could be further optimized by caching all permutations
|
|
|
|
of the given number. All permutations of a number
|
|
|
|
have the same factorial sum because they consist of the
|
|
|
|
same digits. """
|
|
|
|
global current_numbers_set
|
|
|
|
next_value = get_factorial_sum(n)
|
|
|
|
if next_value in current_numbers_set:
|
|
|
|
return 1
|
|
|
|
else:
|
|
|
|
current_numbers_set.add(next_value)
|
|
|
|
return 1 + get_chain_length(next_value)
|
|
|
|
|
|
|
|
|
|
|
|
def get_digits(n):
|
|
|
|
return map(int, str(n))
|
|
|
|
|
2019-07-21 20:13:28 +02:00
|
|
|
|
|
|
|
def euler_074():
|
2019-08-02 05:04:43 +02:00
|
|
|
c = 0
|
|
|
|
for n in range(10**6):
|
|
|
|
global current_numbers_set
|
|
|
|
current_numbers_set = set([n])
|
|
|
|
chain_len = get_chain_length(n)
|
|
|
|
if chain_len == 60:
|
|
|
|
# print("n: {} length: {}".format(n, chain_len))
|
|
|
|
c += 1
|
|
|
|
return c
|
2019-07-21 20:13:28 +02:00
|
|
|
|
|
|
|
|
|
|
|
if __name__ == "__main__":
|
|
|
|
print("e074.py: " + str(euler_074()))
|
2019-08-02 05:04:43 +02:00
|
|
|
assert(euler_074() == 402)
|