adventofcode2022/day21/sol.py

104 lines
2.2 KiB
Python

import operator
lines = []
for line in open("input"):
lines.append(line.split())
unused = lines
scope = {}
while unused:
lines, unused = unused, []
for words in lines:
refs = [x for x in words[1:] if x.isalpha()]
if any(r not in scope for r in refs):
unused.append(words)
continue
dst = words[0].rstrip(':')
if len(words) == 2:
_, src = words
scope[dst] = int(src)
continue
_, x, op, y = words
scope[dst] = (op, scope[x], scope[y])
optab = {
'*': operator.mul,
'/': operator.floordiv,
'+': operator.add,
'-': operator.sub,
}
def eval(x):
if type(x) == int:
return x
op = x[0]
args = [eval(a) for a in x[1:]]
return optab[op](*args)
root = scope['root']
print(eval(root))
def solve(x):
_, left, right = x
humn = scope['humn']
path = set()
def find(x):
if x is humn:
path.add(x)
return True
if type(x) is tuple:
for a in x:
if find(a):
path.add(x)
return True
else:
return False
return False
x, y = left, right
if not find(x):
find(y)
x, y = y, x
#print(x)
assert x in path
y = eval(y)
while x is not humn:
assert len(x) == 3
op, a, b = x
if op == '/':
if a in path:
y = ('*', y, b)
else:
raise ValueError("ruh-roh")
elif op == '*':
if a in path:
y = ('/', y, b)
else:
y = ('/', y, a)
elif op == '+':
if a in path:
y = ('-', y, b)
else:
y = ('-', y, a)
elif op == '-':
if a in path:
# x - b = y => x = y + b
y = ('+', y, b)
else:
# a - x = y => x = a - y
y = ('-', a, y)
else:
raise ValueError("unknown op "+repr(op))
if a in path:
x = a
else:
x = b
return eval(y)
print(solve(root))