This commit is contained in:
dave 2018-12-17 21:01:37 -08:00
parent f514774857
commit 14ee180067
3 changed files with 4508 additions and 0 deletions

191
16/a.py Executable file
View File

@ -0,0 +1,191 @@
#!/usr/bin/env python3
"""
four registers (numbered 0 through 3) that
can be manipulated by instructions containing one of 16 opcodes.
The registers start with the value 0.
Every instruction consists of four values:
an opcode,
two inputs (named A and B), and
an output (named C), in that order.
The opcode specifies the behavior of the instruction and how the inputs are interpreted.
The output, C, is always treated as a register.
ch opcode has a number from 0 through 15
"""
def addr(regs, a, b, c):
# addr (add register) stores into register C the result of adding register A and register B.
regs.set(c, regs.get(a) + regs.get(b))
def addi(regs, a, b, c):
# addi (add immediate) stores into register C the result of adding register A and value B.
regs.set(c, regs.get(a) + b)
def mulr(regs, a, b, c):
# mulr (multiply register) stores into register C the result of multiplying register A and register B.
regs.set(c, regs.get(a) * regs.get(b))
def muli(regs, a, b, c):
# muli (multiply immediate) stores into register C the result of multiplying register A and value B.
regs.set(c, regs.get(a) * b)
def banr(regs, a, b, c):
# banr (bitwise AND register) stores into register C the result of the bitwise AND of register A and register B.
regs.set(c, regs.get(a) & regs.get(b))
def bani(regs, a, b, c):
# bani (bitwise AND immediate) stores into register C the result of the bitwise AND of register A and value B.
regs.set(c, regs.get(a) & b)
def borr(regs, a, b, c):
# borr (bitwise OR register) stores into register C the result of the bitwise OR of register A and register B.
regs.set(c, regs.get(a) | regs.get(b))
def bori(regs, a, b, c):
# bori (bitwise OR immediate) stores into register C the result of the bitwise OR of register A and value B.
regs.set(c, regs.get(a) | b)
def setr(regs, a, b, c):
# setr (set register) copies the contents of register A into register C. (Input B is ignored.)
regs.set(c, regs.get(a))
def seti(regs, a, b, c):
# seti (set immediate) stores value A into register C. (Input B is ignored.)
regs.set(c, a)
def gtir(regs, a, b, c):
# gtir (greater-than immediate/register) sets register C to 1 if value A is greater than register B. Otherwise, register C is set to 0.
regs.set(c, 1 if a > regs.get(b) else 0)
def gtri(regs, a, b, c):
# gtri (greater-than register/immediate) sets register C to 1 if register A is greater than value B. Otherwise, register C is set to 0.
regs.set(c, 1 if regs.get(a) > b else 0)
def gtrr(regs, a, b, c):
# gtrr (greater-than register/register) sets register C to 1 if register A is greater than register B. Otherwise, register C is set to 0.
regs.set(c, 1 if regs.get(a) > regs.get(b) else 0)
def eqir(regs, a, b, c):
# eqir (equal immediate/register) sets register C to 1 if value A is equal to register B. Otherwise, register C is set to 0.
regs.set(c, 1 if a == regs.get(b) else 0)
def eqri(regs, a, b, c):
# eqri (equal register/immediate) sets register C to 1 if register A is equal to value B. Otherwise, register C is set to 0.
regs.set(c, 1 if regs.get(a) == b else 0)
def eqrr(regs, a, b, c):
# eqrr (equal register/register) sets register C to 1 if register A is equal to register B. Otherwise, register C is set to 0.
regs.set(c, 1 if regs.get(a) == regs.get(b) else 0)
ops = (addr,
addi,
mulr,
muli,
banr,
bani,
borr,
bori,
setr,
seti,
gtir,
gtri,
gtrr,
eqir,
eqri,
eqrr)
class Registers(object):
def __init__(self, initial=None):
self.regs = list(initial) if initial else [0, 0, 0, 0]
def get(self, num):
return self.regs[num]
def set(self, num, value):
self.regs[num] = value
class SampleInstr(object):
def __init__(self, before, instr, after):
self.before = before
self.instr = instr
self.after = after
def load_samples(fname):
"""
Load the samples into a list
"""
samples = []
program = []
with open(fname) as f:
while True:
line = f.readline()
if not line.startswith("Before"):
break
samples.append(SampleInstr(
[int(i) for i in line.strip().split(": [")[1][0:-1].split(", ")],
[int(i) for i in f.readline().strip().split()],
[int(i) for i in f.readline().strip().split(": [")[1][0:-1].split(", ")]))
f.readline()
f.readline()
for line in f.readlines():
program.append([int(i) for i in line.strip().split()])
return samples, program
def run_sample(sample, op):
# Run the sample through one opcode and returns True if our output matches the sample output
r = Registers(sample.before)
op(r, *sample.instr[1:])
return sample.after == r.regs
def sample_repeats(sample):
# run the sample through the opcodes until a duplicate result is found
matching = 0
for op in ops:
if run_sample(sample, op):
matching += 1
if matching >= 3:
return True
return False
def main():
samples, _ = load_samples("input.txt")
repeating = 0
for sample in samples:
if sample_repeats(sample):
repeating += 1
print(repeating)
if __name__ == '__main__':
main()

51
16/b.py Executable file
View File

@ -0,0 +1,51 @@
#!/usr/bin/env python3
from a import load_samples, ops, Registers
def find_opcodes(samples):
# process of elimination to find opcode IDs
options = {i: set(ops) for i in range(0, 16)}
found_codes = set()
while len(found_codes) < 15:
for sample in samples:
op_id = sample.instr[0]
if op_id in found_codes:
continue
for op in list(options[op_id]):
cpu = Registers(sample.before)
op(cpu, *sample.instr[1:])
if cpu.regs != sample.after:
options[op_id].remove(op)
if len(options[op_id]) == 1:
found_op = list(options[op_id])[0]
found_codes.update([op_id])
for o_opid, opset in options.items():
if o_opid != op_id:
try:
opset.remove(found_op)
except KeyError:
pass
return {k: list(v)[0] for k, v in options.items()}
def main():
samples, program = load_samples("input.txt")
optable = find_opcodes(samples)
cpu = Registers()
for instruction in program:
optable[instruction[0]](cpu, *instruction[1:])
print("Registers:", cpu.regs)
print("Answer:", cpu.regs[0])
if __name__ == '__main__':
main()

4266
16/input.txt Normal file

File diff suppressed because it is too large Load Diff