49 lines
1.3 KiB
Python
49 lines
1.3 KiB
Python
|
from lib_misc import sum_proper_divisors
|
||
|
|
||
|
|
||
|
def euler_095():
|
||
|
NO_CHAIN = set()
|
||
|
PROPER_DIVISOR_CACHE = {}
|
||
|
|
||
|
def sum_proper_divisors_cached(n):
|
||
|
if n in PROPER_DIVISOR_CACHE:
|
||
|
return PROPER_DIVISOR_CACHE[n]
|
||
|
r = sum_proper_divisors(n)
|
||
|
PROPER_DIVISOR_CACHE[n] = r
|
||
|
return r
|
||
|
|
||
|
def chain(n):
|
||
|
chain = []
|
||
|
next_number = n
|
||
|
|
||
|
while next_number not in chain:
|
||
|
if next_number >= 10**6 or next_number == 0 or next_number in NO_CHAIN:
|
||
|
for c in chain:
|
||
|
NO_CHAIN.add(c)
|
||
|
return None
|
||
|
chain.append(next_number)
|
||
|
next_number = sum_proper_divisors_cached(next_number)
|
||
|
chain.append(next_number)
|
||
|
return chain
|
||
|
|
||
|
chains = [[]]
|
||
|
for i in range(1, 10**6 + 1):
|
||
|
c = chain(i)
|
||
|
if c and c[0] == c[-1]:
|
||
|
if len(c) == len(chains[0]):
|
||
|
# There might be multiple different chains with the same length
|
||
|
# so keep all of them to get the smalles element.
|
||
|
chains.append(c)
|
||
|
elif len(c) > len(chains[0]):
|
||
|
chains = [c]
|
||
|
|
||
|
elems = [e for c in chains for e in c]
|
||
|
return min(elems)
|
||
|
|
||
|
|
||
|
if __name__ == "__main__":
|
||
|
solution = euler_095()
|
||
|
print("e095.py: " + str(solution))
|
||
|
assert(solution == 14316)
|
||
|
|