#!/usr/bin/env python # coding: utf-8 # In[1]: 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', '')) # In[2]: 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 # In[3]: import import_ipynb import helper s = helper.read_file('2015_7.txt') # In[4]: 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'])