%%time
from collections import defaultdict
def solve(inp_filename):
with open(inp_filename) as file:
lines = [s.strip() for s in file.readlines() if len(s.strip()) > 0]
def execute(commands, state, inp):
i = 0
for line in commands:
parts = line.split()
if parts[0] == 'inp':
if i >= len(inp):
print(f"asking too much {i}, {inp}")
state[parts[1]] = inp[i]
i += 1
else:
x = parts[1]
if parts[2][0] in 'xyzw':
y = state[parts[2]]
else:
y = int(parts[2])
if parts[0] == 'add':
state[x] += y
elif parts[0] == 'mul':
state[x] *= y
elif parts[0] == 'div':
if y == 0:
print(f"y=0 for command {line}")
raise 1
state[x] = state[x] // y
elif parts[0] == 'mod':
if y == 0:
print(f"y=0 for command {line}")
raise 1
state[x] = state[x] % y
elif parts[0] == 'eql':
state[x] = 1 if (state[x] == y) else 0
return state
def group_commads_by_blocks(lines):
start = 0
blocks = []
for end in range(1, len(lines) + 1):
if end == len(lines) or lines[end].startswith('inp'):
blocks.append(lines[start : end])
start = end
return blocks
def execute_blocks(blocks, state, inp):
for i, block in enumerate(blocks):
state = execute(block, state, [inp[i]])
return state
blocks = group_commads_by_blocks(lines)
needz = defaultdict(lambda: float('inf'))
needz[0] = 0
power = 1
maxz_ranges = [1, 20, 500] + [13000, 320000, 13000, 320000, 13000, 320000, 13000] + [1000, 100, 100, 100]
for bi in range(len(blocks) - 1, -1, -1):
block = blocks[bi]
new_needz = defaultdict(lambda: float('inf'))
for w in range(1, 10):
for inputz in range(maxz_ranges[bi]):
state = execute(block, {'x':0, 'y':0, 'z':inputz, 'w':0}, [w])
if state['z'] in needz:
new_needz[inputz] = min(new_needz[inputz], w * power + needz[state['z']])
needz = new_needz
power *= 10
print(bi, len(needz), min(needz), max(needz))
return needz
# print(execute_blocks(blocks[3:], {'x':0, 'y':0, 'z':3, 'w':0}, list(map(int, '92999192998'))))
solve('input')