In [23]:
import csv
def parse_registers(input_path):
registers = []
with open(input_path, 'rt') as f_input:
csv_reader = csv.reader(f_input, delimiter=' ')
for line in csv_reader:
registers.append((line[0], tuple(line[1:])))
return registers
In [24]:
def r_set(x, y):
exec('{0} = {1}'.format(x, y), globals())
def r_add(x, y):
exec('{0} += {1}'.format(x, y), globals())
def r_mul(x, y):
if x not in globals(): globals()[x] = 0
exec('{0} *= {1}'.format(x, y), globals())
def r_mod(x, y):
exec('{0} = {0} % {1}'.format(x, y), globals())
def r_snd(x):
exec('last_played = {0}'.format(x), globals())
def r_rcv(x):
exec('if {0} != 0: recovered = last_played'.format(x), globals())
In [25]:
import re
def exec_register(reg):
comm = reg[0]
argx = reg[1][0]
if len(reg[1]) == 1:
globals()['r_' + comm](argx)
if len(reg[1]) > 1:
argy = reg[1][1]
globals()['r_' + comm](argx, argy)
def retrieve(string):
if re.search('\d+', string):
return int(string)
else:
return globals()[string]
def read_registers(registers):
head = 0
while recovered is None:
reg = registers[head]
if reg[0] != 'jgz':
exec_register(reg)
head += 1
else:
req = retrieve(reg[1][0])
offset = retrieve(reg[1][1])
if req > 0:
head += offset
else:
head += 1
return last_played
In [26]:
registers = parse_registers('input.test1.txt')
recovered = None
last_played = None
read_registers(registers)
Out[26]:
In [27]:
registers = parse_registers('input.txt')
recovered = None
last_played = None
read_registers(registers)
Out[27]:
In [162]:
from collections import defaultdict
def init():
globals()['prog'] = (defaultdict(int), defaultdict(int))
globals()['prog'][1]['p'] = 1
globals()['queue'] = ([], [])
globals()['halt'] = [False, False]
globals()['sent_count'] = 0
In [225]:
def retrieve(string, prog):
if re.search('\d+', string):
return int(string)
else:
return prog[string]
def r_set(x, y, i):
y = retrieve(y, prog[i])
prog[i][x] = y
def r_add(x, y, i):
y = retrieve(y, prog[i])
prog[i][x] += y
def r_mul(x, y, i):
y = retrieve(y, prog[i])
prog[i][x] *= y
def r_mod(x, y, i):
y = retrieve(y, prog[i])
prog[i][x] = prog[i][x] % y
def r_snd(x, i):
x = retrieve(x, prog[i])
queue[(i + 1) % 2].append(x)
if halt[(i + 1) % 2] == True:
halt[(i + 1) % 2] = False
if i == 1:
globals()['sent_count'] += 1
def r_rcv(x, i):
try:
prog[i][x] = queue[i].pop(0)
except IndexError:
globals()['halt'][i] = True
In [226]:
import re
def exec_register(reg, i):
comm = reg[0]
argx = reg[1][0]
if len(reg[1]) == 1:
globals()['r_' + comm](argx, i)
if len(reg[1]) > 1:
argy = reg[1][1]
globals()['r_' + comm](argx, argy, i)
In [234]:
def run_duet(registers):
head = [0, 0]
while (not halt[0]) or (not halt[1]):
i = halt.index(False)
reg = registers[head[i]]
if reg[0] != 'jgz':
exec_register(reg, i)
if not halt[i]:
head[i] += 1
else:
req = retrieve(reg[1][0], prog[i])
offset = retrieve(reg[1][1], prog[i])
if req > 0:
head[i] += offset
else:
head[i] += 1
In [235]:
init()
registers = parse_registers('input.test1.txt')
run_duet(registers)
assert(sent_count == 1)
In [236]:
init()
registers = parse_registers('input.test2.txt')
run_duet(registers)
assert(sent_count == 3)
In [237]:
init()
registers = parse_registers('input.txt')
run_duet(registers)
print(sent_count)