123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596 |
- #!/usr/bin/python3
-
- """Solution for day 25 of Advent of Code 2016.
-
- This is a copy of Day 23's solution, with an 'out' instruction added.
-
- Manual testing showed the output repeats regularly, so we just run the program until there are 20 bits output.
-
- TODO: Add a common class for handling the assembly code, as it's now repeated in 3 places.
- """
-
- import itertools
-
-
- def value(registers, x):
- try:
- return int(x)
- except ValueError:
- return registers[x]
-
-
- def cpy(registers, src, dst):
- registers[dst] = value(registers, src)
-
-
- def inc(registers, reg):
- registers[reg] += 1
-
-
- def dec(registers, reg):
- registers[reg] -= 1
-
-
- def jnz(registers, val, tar):
- registers['pc'] += 0 if value(registers, val) == 0 else value(registers, tar) - 1
-
-
- def tgl(registers, ins):
- mappings = {inc: dec, dec: inc, tgl: inc, jnz: cpy, cpy: jnz}
- target = registers['pc'] + value(registers, ins)
- registers['in'][target] = (mappings[registers['in'][target][0]], registers['in'][target][1])
-
-
- def out(registers, val):
- registers['out'].append(value(registers, val))
-
-
- def try_multiply(registers):
- try:
- pc = registers['pc']
- chunk = registers['in'][pc:pc+6]
- instr, args = map(list, zip(*chunk))
- if instr == [cpy, inc, dec, jnz, dec, jnz] \
- and args[0][1] == args[2][0] == args[3][0] \
- and args[4][0] == args[5][0] \
- and args[1][0] != args[0][1] != args[4][0] != args[0][0] \
- and args[3][1] == '-2' and args[5][1] == '-5':
- registers[args[1][0]] += value(registers, args[0][0]) * value(registers, args[4][0])
- registers[args[2][0]] = 0
- registers[args[4][0]] = 0
- registers['pc'] += 5
- return True
- except:
- pass
- return False
-
-
- def step(registers):
- if not try_multiply(registers):
- try:
- registers['in'][registers['pc']][0](registers, *registers['in'][registers['pc']][1])
- except:
- pass
-
-
- def run(values):
- registers = values
- registers['pc'] = 0
- registers['out'] = []
- registers['in'] = instr.copy()
-
- while registers['pc'] < len(instr) and len(registers['out']) < 20:
- step(registers)
- registers['pc'] += 1
-
- return registers['out']
-
-
- with open('data/25.txt', 'r') as file:
- instr = map(str.split, map(str.strip, file.readlines()))
- instr = [(globals()[i[0]], i[1:]) for i in instr]
-
- for a in itertools.count():
- if run({'a': a, 'b': 0, 'c': 0, 'd': 0}) == [0, 1] * 10:
- print('Part one: %s' % a)
- break
|