70 lines
1.7 KiB
Python
70 lines
1.7 KiB
Python
|
from typing import List, Optional
|
||
|
from math import sqrt
|
||
|
from functools import lru_cache
|
||
|
|
||
|
|
||
|
def to_int(digits: List[int]) -> int:
|
||
|
return int("".join(map(str, digits)))
|
||
|
|
||
|
|
||
|
def int_len(n: int) -> int:
|
||
|
return len(str(n))
|
||
|
|
||
|
|
||
|
@lru_cache
|
||
|
def digits_make_sum(digits, remainder: int) -> Optional[List]:
|
||
|
if len(digits) == 0:
|
||
|
if remainder == 0:
|
||
|
return []
|
||
|
return None
|
||
|
|
||
|
remainder_digits_count = int_len(remainder)
|
||
|
if remainder_digits_count > len(digits):
|
||
|
return None
|
||
|
|
||
|
if to_int(digits) < remainder:
|
||
|
return None
|
||
|
|
||
|
for group_size in range(1, remainder_digits_count + 1):
|
||
|
digits_list = list(digits)
|
||
|
rest_value = remainder - to_int(digits_list[:group_size])
|
||
|
rest_digits = tuple(digits_list[group_size:])
|
||
|
r = digits_make_sum(rest_digits, rest_value)
|
||
|
if type(r) is list:
|
||
|
return [digits_list[:group_size]] + r
|
||
|
return None
|
||
|
|
||
|
|
||
|
def digits_sum_to(digits, number: int):
|
||
|
r = digits_make_sum(digits, number)
|
||
|
if type(r) is list:
|
||
|
# print(digits, r, number)
|
||
|
return True
|
||
|
return False
|
||
|
|
||
|
|
||
|
def t(limit: int) -> int:
|
||
|
r = 0
|
||
|
for base in range(4, int(sqrt(limit)) + 1):
|
||
|
n = base * base
|
||
|
n_digits = tuple(map(int, list(str(n))))
|
||
|
if digits_sum_to(n_digits, base):
|
||
|
r += n
|
||
|
return r
|
||
|
|
||
|
|
||
|
def euler_719():
|
||
|
assert(t(10**4) == 41333)
|
||
|
assert(digits_sum_to((1, 0, 0), 10) == True)
|
||
|
assert(digits_sum_to((1, 8), 9) == True)
|
||
|
assert(digits_sum_to((2, 5), 5) == False)
|
||
|
assert(digits_sum_to((8, 2, 8, 1), 91) == True)
|
||
|
assert(t(10**6) == 10804656)
|
||
|
return t(10**12)
|
||
|
|
||
|
|
||
|
if __name__ == "__main__":
|
||
|
solution = euler_719()
|
||
|
print("e719.py: " + str(solution))
|
||
|
assert(solution == 128088830547982)
|