Day 7 - Advent of Code 2015

Working solutions for the day 7 puzzles.

Part One

""" day_07_01.py """

# usage: python3 day_07_01.py < input


import sys


def parse(data):
    """ parse into python """
    ref = {'AND': '&', 'OR': '|', 'LSHIFT': '<<', 'RSHIFT': '>>'}
    code = []
    for row in data.splitlines():
        expr, symbol = row.split(' -> ')
        tokens = expr.split()
        count = len(tokens)
        if count == 1:
            line = f'{tokens[0]}'
        elif count == 2:
            line = f'{tokens[1]} ^ 65535'
        else:
            line = f'{tokens[0]} {ref[tokens[1]]} {tokens[2]}'

        for reserved in ['as', 'if', 'in', 'is']:
            symbol = symbol.replace(reserved, '_' + reserved)
            line = line.replace(reserved, '_' + reserved)

        code.append((symbol, line))
    return code


instructions = parse(sys.stdin.read())
local = {}
while instructions:
    variable, expression = instructions.pop(0)
    try:
        value = eval(expression, local)
    except NameError:
        instructions.append((variable, expression))
    else:
        local[variable] = value
print(local['a'])

Part Two

""" day_07_02.py """

# usage: python3 day_07_02.py < input


import sys


def parse(data):
    """ parse into python """
    ref = {'AND': '&', 'OR': '|', 'LSHIFT': '<<', 'RSHIFT': '>>'}
    code = []
    for row in data.splitlines():
        expr, symbol = row.split(' -> ')
        tokens = expr.split()
        count = len(tokens)
        if count == 1:
            line = f'{tokens[0]}'
        elif count == 2:
            line = f'{tokens[1]} ^ 65535'
        else:
            line = f'{tokens[0]} {ref[tokens[1]]} {tokens[2]}'

        for reserved in ['as', 'if', 'in', 'is']:
            symbol = symbol.replace(reserved, '_' + reserved)
            line = line.replace(reserved, '_' + reserved)

        code.append((symbol, line))
    return code


def process(instructions, override=None):
    """ evaluate instructions """
    commands = instructions.copy()
    if override is None:
        override = {}
    local = {}
    while commands:
        variable, expression = commands.pop(0)
        if variable in override:
            expression = override[variable]
        try:
            value = eval(expression, local)
        except NameError:
            commands.append((variable, expression))
        else:
            local[variable] = value
    return local


script = parse(sys.stdin.read())

ans = str(process(script)['a'])
print(process(script, {'b': ans})['a'])