Slightly more concise 2018 Day 16

This commit is contained in:
Luke Hubmayer-Werner 2018-12-16 16:58:30 +10:30
parent 4d583073a2
commit 225fe62540
1 changed files with 22 additions and 101 deletions

View File

@ -2,118 +2,39 @@ with open('day16-input1', 'r') as file:
data = [l.strip('\n') for l in file] data = [l.strip('\n') for l in file]
with open('day16-input2', 'r') as file: with open('day16-input2', 'r') as file:
data2 = [l.strip('\n') for l in file] data2 = [l.strip('\n') for l in file]
import numpy as np
import re import re
numbers_pt1 = [[int(s) for s in re.findall(r'-?\d+', d)] for d in data if d]
numbers_pt2 = [[int(s) for s in re.findall(r'-?\d+', d)] for d in data2 if d]
def oper_prototype(operator, immediate_a, immediate_b, regs, opcodes):
numbers = [[int(s) for s in re.findall(r'-?\d+', d)] for d in data if d]
numbers2 = [[int(s) for s in re.findall(r'-?\d+', d)] for d in data2 if d]
# arr = np.array(numbers, dtype=np.int64)
registers = np.zeros(4, dtype=np.int64)
def addr(regs, opcodes):
op, a, b, c = opcodes op, a, b, c = opcodes
r = list(regs) r = list(regs)
r[c] = regs[a] + regs[b] r[c] = operator((a if immediate_a else regs[a]), (b if immediate_b else regs[b]))
return r return r
def addi(regs, opcodes): addr = lambda regs, opcodes: oper_prototype(int.__add__, False, False, regs, opcodes)
op, a, b, c = opcodes addi = lambda regs, opcodes: oper_prototype(int.__add__, False, True, regs, opcodes)
r = list(regs) mulr = lambda regs, opcodes: oper_prototype(int.__mul__, False, False, regs, opcodes)
r[c] = regs[a] + b muli = lambda regs, opcodes: oper_prototype(int.__mul__, False, True, regs, opcodes)
return r andr = lambda regs, opcodes: oper_prototype(int.__and__, False, False, regs, opcodes)
andi = lambda regs, opcodes: oper_prototype(int.__and__, False, True, regs, opcodes)
def mulr(regs, opcodes): orr = lambda regs, opcodes: oper_prototype(int.__or__, False, False, regs, opcodes)
op, a, b, c = opcodes ori = lambda regs, opcodes: oper_prototype(int.__or__, False, True, regs, opcodes)
r = list(regs) setr = lambda regs, opcodes: oper_prototype(lambda a, b: a, True, True, regs, opcodes)
r[c] = regs[a] * regs[b] seti = lambda regs, opcodes: oper_prototype(lambda a, b: a, False, True, regs, opcodes)
return r gtir = lambda regs, opcodes: oper_prototype(int.__gt__, True, False, regs, opcodes)
gtri = lambda regs, opcodes: oper_prototype(int.__gt__, False, True, regs, opcodes)
def muli(regs, opcodes): gtrr = lambda regs, opcodes: oper_prototype(int.__gt__, False, False, regs, opcodes)
op, a, b, c = opcodes eqir = lambda regs, opcodes: oper_prototype(int.__eq__, True, False, regs, opcodes)
r = list(regs) eqri = lambda regs, opcodes: oper_prototype(int.__eq__, False, True, regs, opcodes)
r[c] = regs[a] * b eqrr = lambda regs, opcodes: oper_prototype(int.__eq__, False, False, regs, opcodes)
return r
def andr(regs, opcodes):
op, a, b, c = opcodes
r = list(regs)
r[c] = regs[a] & regs[b]
return r
def andi(regs, opcodes):
op, a, b, c = opcodes
r = list(regs)
r[c] = regs[a] & b
return r
def orr(regs, opcodes):
op, a, b, c = opcodes
r = list(regs)
r[c] = regs[a] | regs[b]
return r
def ori(regs, opcodes):
op, a, b, c = opcodes
r = list(regs)
r[c] = regs[a] | b
return r
def setr(regs, opcodes):
op, a, b, c = opcodes
r = list(regs)
r[c] = regs[a]
return r
def seti(regs, opcodes):
op, a, b, c = opcodes
r = list(regs)
r[c] = a
return r
def gtir(regs, opcodes):
op, a, b, c = opcodes
r = list(regs)
r[c] = int(bool(a > regs[b]))
return r
def gtri(regs, opcodes):
op, a, b, c = opcodes
r = list(regs)
r[c] = int(bool(regs[a] > b))
return r
def gtrr(regs, opcodes):
op, a, b, c = opcodes
r = list(regs)
r[c] = int(bool(regs[a] > regs[b]))
return r
def eqir(regs, opcodes):
op, a, b, c = opcodes
r = list(regs)
r[c] = int(bool(a == regs[b]))
return r
def eqri(regs, opcodes):
op, a, b, c = opcodes
r = list(regs)
r[c] = int(bool(regs[a] == b))
return r
def eqrr(regs, opcodes):
op, a, b, c = opcodes
r = list(regs)
r[c] = int(bool(regs[a] == regs[b]))
return r
instructions = [addr, addi, mulr, muli, andr, andi, orr, ori, setr, seti, gtir, gtri, gtrr, eqir, eqri, eqrr] instructions = [addr, addi, mulr, muli, andr, andi, orr, ori, setr, seti, gtir, gtri, gtrr, eqir, eqri, eqrr]
num_3_or_more = 0 num_3_or_more = 0
instruction_codes = {} instruction_codes = {}
instruction_impossibilities = {} instruction_impossibilities = {}
for before, opcodes, after in zip(numbers[::3], numbers[1::3], numbers[2::3]): for before, opcodes, after in zip(numbers_pt1[::3], numbers_pt1[1::3], numbers_pt1[2::3]):
possibilities = set() possibilities = set()
impossibilities = set() impossibilities = set()
for op in instructions: for op in instructions:
@ -151,7 +72,7 @@ while sum([len(i) for i in instruction_codes.values()]) > len(instructions):
opcode_convert = {code: list(s)[0] for code, s in instruction_codes.items()} opcode_convert = {code: list(s)[0] for code, s in instruction_codes.items()}
regs = [0, 0, 0, 0] regs = [0, 0, 0, 0]
for i, opcodes in enumerate(numbers2): for i, opcodes in enumerate(numbers_pt2):
try: try:
regs = opcode_convert[opcodes[0]](regs, opcodes) regs = opcode_convert[opcodes[0]](regs, opcodes)
except: except: