day 07
some assembly required
approach
each line is parsed into (operand, operand, gate, output), where an operand is either a number or a wire name. a dependency graph is built between instructions (an instruction points to the ones that read its output) and sorted topologically with a queue of in-degrees, so every wire is computed before it is read.
after that the circuit is evaluated in a single pass into a dict, masking every result to 16 bits. part 1 reads wire a. part 2 runs the same pass again with b already set to that value; instructions whose output is already in the dict are skipped, which is what makes the override stick.
the trick
sort the gates topologically so one straight pass can evaluate the whole circuit.
python
def toposort(instructions):
g, incoming = build_deps_graph(instructions)
q = deque(i for i in range(len(instructions)) if incoming[i] == 0)
res = []
while q:
n = q.popleft()
res.append(n)
for nn in g[n]:
if incoming[nn] == 1:
q.append(nn)
del incoming[nn]
else:
incoming[nn] -= 1
return res