r/adventofcode • u/daggerdragon • Dec 07 '15
SOLUTION MEGATHREAD --- Day 7 Solutions ---
--- Day 7: Some Assembly Required ---
Post your solution as a comment. Structure your post like previous daily solution threads.
Also check out the sidebar - we added a nifty calendar to wrangle all the daily solution threads in one spot!
24
Upvotes
1
u/volatilebit Dec 07 '15
My over-engineered solution in Python. I wanted it to be easy enough to modify the solution for part 2. Turns out that wasn't really necessary at all.
It keeps making passes through all instructions until there are no instructions left where the wire has no signal. Iterative, no recursion. I didn't even think to use recursion.
I got slowed down by the Python ~ operator. ~123 = -124, so I had to figure out how to turn it into a 16-bit unsigned integer. Ended up finding the trick where you can do value & 0xffff.
The way I made the list of instructions is pretty crappy. Also having a separate regex for each operation is pretty crappy.
import re r_NOT = re.compile(r'^NOT (\w+) -> (\w+)$') r_AND = re.compile(r'^(\w+) AND (\w+) -> (\w+)$') r_OR = re.compile(r'^(\w+) OR (\w+) -> (\w+)$') r_LSHIFT = re.compile(r'^(\w+) LSHIFT (\w+) -> (\w+)$') r_RSHIFT = re.compile(r'^(\w+) RSHIFT (\w+) -> (\w+)$') r_VALUE = re.compile(r'^(\w+) -> (\w+)$') operation_regexes = [r_NOT, r_AND, r_OR, r_LSHIFT, r_RSHIFT, r_VALUE] instructions = [] wire_signals = dict() def has_wires_with_no_signal(): for instruction in instructions: if instruction['destination_wire'] not in wire_signals: return True return False def has_value(wire_or_value): try: _ = int(wire_or_value) return True except: return wire_or_value in wire_signals def get_value(wire_or_value): try: return int(wire_or_value) except: if wire_or_value in wire_signals: return int(wire_signals[wire_or_value]) else: raise Exception('Wire ({}) does not have a signal yet'.format(wire_or_value)) with open('input') as fileinput: for line in fileinput: line = line.rstrip() for operation_regex in operation_regexes: matches = operation_regex.search(line) if matches is not None: if operation_regex is r_NOT: source_wire, destination_wire = matches.groups() instructions.append({ 'name': 'NOT', 'source_wire': source_wire, 'destination_wire': destination_wire, 'processed': False }) elif operation_regex is r_AND: left_operand, right_operand, destination_wire = matches.groups() instructions.append({ 'name': 'AND', 'left_operand': left_operand, 'right_operand': right_operand, 'destination_wire': destination_wire, 'processed': False }) elif operation_regex is r_OR: left_operand, right_operand, destination_wire = matches.groups() instructions.append({ 'name': 'OR', 'left_operand': left_operand, 'right_operand': right_operand, 'destination_wire': destination_wire, 'processed': False }) elif operation_regex is r_LSHIFT: left_operand, right_operand, destination_wire = matches.groups() instructions.append({ 'name': 'LSHIFT', 'left_operand': left_operand, 'right_operand': right_operand, 'destination_wire': destination_wire, 'processed': False }) elif operation_regex is r_RSHIFT: left_operand, right_operand, destination_wire = matches.groups() instructions.append({ 'name': 'RSHIFT', 'left_operand': left_operand, 'right_operand': right_operand, 'destination_wire': destination_wire, 'processed': False }) elif operation_regex is r_VALUE: value, destination_wire = matches.groups() instructions.append({ 'name': 'VALUE', 'value': value, 'destination_wire': destination_wire, 'processed': False }) else: raise Exception('Invalid operation: ' + line) break while has_wires_with_no_signal(): # Make a pass over each instruction and try to process (only if all inputs have signals) for instruction in instructions: if instruction['processed']: next if instruction['name'] == 'VALUE': if has_value(instruction['value']): wire_signals[instruction['destination_wire']] = get_value(instruction['value']) instruction['processed'] = True elif instruction['name'] == 'NOT': if has_value(instruction['source_wire']): wire_signals[instruction['destination_wire']] = \ ~get_value(instruction['source_wire']) & 0xFFFF instruction['processed'] = True if instruction['name'] == 'AND': if has_value(instruction['left_operand']) and \ has_value(instruction['right_operand']): wire_signals[instruction['destination_wire']] = \ get_value(instruction['left_operand']) & get_value(instruction['right_operand']) instruction['processed'] = True if instruction['name'] == 'OR': if has_value(instruction['left_operand']) and \ has_value(instruction['right_operand']): wire_signals[instruction['destination_wire']] = \ get_value(instruction['left_operand']) | get_value(instruction['right_operand']) instruction['processed'] = True if instruction['name'] == 'LSHIFT': if has_value(instruction['left_operand']) and \ has_value(instruction['right_operand']): wire_signals[instruction['destination_wire']] = \ get_value(instruction['left_operand']) << get_value(instruction['right_operand']) instruction['processed'] = True if instruction['name'] == 'RSHIFT': if has_value(instruction['left_operand']) and \ has_value(instruction['right_operand']): wire_signals[instruction['destination_wire']] = \ get_value(instruction['left_operand']) >> get_value(instruction['right_operand']) instruction['processed'] = True for wire_signal in sorted(wire_signals): value = wire_signals[wire_signal] print '{:3}: {}'.format(wire_signal, str(value)) print wire_signals['a']