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)