#!/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)