#Skip to menu

Day 7, Year 2015: Some Assembly Required

First read the problem description.
import networkx as nx
import matplotlib.pyplot as plt

INPUT = 'Input'

def value(wires, token):
    try:
        value = int(token)
    except ValueError:
        value = wires.get(token, 0)

    return value

mask = 0xffff

def compute(wires, tokens):
    if len(tokens) == 1:
        return value(wires, tokens[0])
    if tokens[0] == 'NOT':
        return mask - value(wires, tokens[1])
    if tokens[1] == 'AND':
        return value(wires, tokens[0]) & value(wires, tokens[2])
    if tokens[1] == 'OR':
        return value(wires, tokens[0]) | value(wires, tokens[2])
    if tokens[1] == 'LSHIFT':
        return (value(wires, tokens[0]) << value(wires, tokens[2])) & mask
    if tokens[1] == 'RSHIFT':
        return value(wires, tokens[0]) >> value(wires, tokens[2])
    assert False

def run(wires, s):
    if not s:
        return
    tokens = s.split()
    wires[tokens[-1]] = compute(wires, tokens[:-2])


def add_to_graph(dg, s):
    if not s:
        return
    tokens = s.split()
    input1 = None
    input2 = None
    output = tokens[-1]
    tokens = tokens[:-2]
    if len(tokens) == 1:
        if tokens[0].isdigit():
            input1 = INPUT
        else:
            input1 = tokens[0]
    elif tokens[0] == 'NOT':
        if tokens[1].isdigit():
            input1 = INPUT
        else:
            input1 = tokens[1]
    else:
        input1 = tokens[0]
        input2 = tokens[2]

    if input1 and not input1.isdigit():
        dg.add_edge(output, input1, code = s)
    if input2 and not input2.isdigit():
        dg.add_edge(output, input2, code = s)


def run_graph(wires, dg):
    nodes = reversed(list(nx.topological_sort(nx.line_graph(dg))))
    for (fn, tn) in nodes:
        run(wires, dg[fn][tn].get('code', ''))
wires = {}
instructions = """123 -> x
456 -> y
x AND y -> d
x OR y -> e
x LSHIFT 2 -> f
y RSHIFT 2 -> g
NOT x -> h
NOT y -> i"""
dg = nx.DiGraph()
for s in instructions.splitlines():
   add_to_graph(dg, s)
run_graph(wires, dg)
assert value(wires, 'd') == 72
assert value(wires, 'e') == 507
assert value(wires, 'f') == 492
assert value(wires, 'g') == 114
assert value(wires, 'h') == 65412
assert value(wires, 'i') == 65079
assert value(wires, 'x') == 123
assert value(wires, 'y') == 456
import import_ipynb
import helper
s = helper.read_file('2015_7.txt')
wires = {}
dg = nx.DiGraph()
for instr in s.splitlines():
    add_to_graph(dg, instr)

run_graph(wires, dg)
print(wires['a'])

wires = {'b': wires['a']}
dg.remove_node(INPUT)
run_graph(wires, dg)
print(wires['a'])
956
40149

Source code of the solution(s):