122 lines
3.1 KiB
Python
122 lines
3.1 KiB
Python
#!/usr/bin/env python3
|
|
|
|
import bisect
|
|
import sys
|
|
import time
|
|
import functools
|
|
|
|
input_file = sys.argv[1]
|
|
|
|
with open(input_file) as fd:
|
|
lines = [line.rstrip() for line in fd.readlines()]
|
|
|
|
start = time.time()
|
|
|
|
stones = [int(stone) for stone in lines[0].split()]
|
|
|
|
# for i in range(75):
|
|
# print(i, time.time() - start, len(stones))
|
|
# # for s, stone in enumerate(stones):
|
|
# # if stone == 0:
|
|
# # stones[s] = 1
|
|
# # continue
|
|
# # stone_str = str(stone)
|
|
# # if len(stone_str) % 2 == 0:
|
|
# # mid = int(len(stone_str) / 2)
|
|
# # stones[s] = int(stone_str[:mid])
|
|
# # stones.insert(s, int(stone_str[mid:]))
|
|
# # else:
|
|
# # stones[s] *= 2024
|
|
# new_stones = []
|
|
# for stone in stones:
|
|
# stone_str = str(stone)
|
|
# if stone == 0:
|
|
# new_stones.append(1)
|
|
# elif len(stone_str) % 2 == 0:
|
|
# mid = int(len(stone_str) / 2)
|
|
# new_stones.append(int(stone_str[:mid]))
|
|
# new_stones.append(int(stone_str[mid:]))
|
|
# else:
|
|
# new_stones.append(stone * 2024)
|
|
# stones = new_stones
|
|
|
|
target = int(sys.argv[2])
|
|
|
|
its = [0] * len(stones)
|
|
|
|
start_stones = stones.copy()
|
|
|
|
|
|
pow10 = list()
|
|
for i in range(25):
|
|
pow10.append(10**i)
|
|
|
|
|
|
def num_digits(a: int) -> int:
|
|
# for i, p in enumerate(pow10):
|
|
# if a < p:
|
|
# # assert len(str(a)) == i
|
|
# return i
|
|
# raise NotImplementedError
|
|
# return bisect.bisect(pow10, a)
|
|
# # nb = bisect.bisect(pow10, a)
|
|
num = 0
|
|
while a > 0:
|
|
num += 1
|
|
a //= 10
|
|
# assert nb == num
|
|
return num
|
|
|
|
|
|
# lstones = 0
|
|
# for e, sstone in enumerate(start_stones):
|
|
# print(f"47 {e}/{len(start_stones)} {time.time() - start}")
|
|
# stones = [sstone]
|
|
# while stones:
|
|
# stone = stones.pop(0)
|
|
# it = its.pop(0)
|
|
# lstones += 1
|
|
# if stone == 0:
|
|
# stone = 1
|
|
# it += 1
|
|
# nd = num_digits(stone)
|
|
# for i in range(it, target):
|
|
# print(stone)
|
|
# if nd % 2 == 0:
|
|
# mid = nd // 2
|
|
# left, right = divmod(stone, pow10[mid])
|
|
# # left, right = divmod(stone, 10**mid)
|
|
# stone = left
|
|
# stones.insert(0, right)
|
|
# its.insert(0, i + 1)
|
|
# nd = mid
|
|
# else:
|
|
# stone *= 2024
|
|
# nd = num_digits(stone)
|
|
# # print(f"64 {stone}")
|
|
|
|
# @functools.lru_cache(maxsize=1024)
|
|
@functools.cache
|
|
def proc(stone: int, target: int) -> int:
|
|
if target == 0:
|
|
return 1
|
|
target -= 1
|
|
if stone == 0:
|
|
return proc(1, target)
|
|
nd = num_digits(stone)
|
|
if nd % 2 == 0:
|
|
mid = nd // 2
|
|
left, right = divmod(stone, pow10[mid])
|
|
return proc(left, target) + proc(right, target)
|
|
else:
|
|
return proc(stone * 2024, target)
|
|
|
|
|
|
lstones = 0
|
|
for e, stone in enumerate(stones):
|
|
print(f"47 {e}/{len(stones)} {time.time() - start}")
|
|
lstones += proc(stone, target)
|
|
|
|
print(f"{target=}")
|
|
print(lstones)
|