| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162 |
- #!/usr/bin/env python3
- import sys
- def read_program(f):
- maybe_int = lambda x: int(x) if x.isdigit() or x[0] == '-' else x
- for line in f:
- instr = tuple(map(maybe_int, line.split()))
- yield instr + (None,) * (3 - len(instr))
- def check_mul(p, pc):
- if pc <= len(p) - 5:
- opcodes, a, b = zip(*p[pc:pc + 5])
- if a[1] == a[2] and a[3] == a[4] and b[2] == -2 and b[4] == -5:
- if opcodes == ('inc', 'dec', 'jnz', 'dec', 'jnz'):
- return a[1], a[3]
- def run(p, init):
- regs = [init, 0, 0, 0]
- pc = 0
- toggle_opcode = {'inc': 'dec', 'dec': 'inc', 'tgl': 'inc',
- 'cpy': 'jnz', 'jnz': 'cpy'}
- def load(x):
- return x if isinstance(x, int) else regs[ord(x) - ord('a')]
- def store(reg, value):
- regs[ord(reg) - ord('a')] = value
- while pc < len(p):
- opcode, a, b = p[pc]
- try:
- if opcode == 'cpy':
- store(b, load(a))
- elif opcode == 'inc':
- params = check_mul(p, pc)
- if params:
- reg1, reg2 = params
- increment = load(reg1) * load(reg2)
- store(reg1, 0)
- store(reg2, 0)
- pc += 4
- else:
- increment = 1
- store(a, load(a) + increment)
- elif opcode == 'dec':
- store(a, load(a) - 1)
- elif opcode == 'jnz':
- if load(a):
- pc += load(b) - 1
- elif opcode == 'tgl':
- offset = load(a)
- other_opcode, other_a, other_b = p[pc + offset]
- p[pc + offset] = toggle_opcode[other_opcode], other_a, other_b
- except IndexError:
- pass
- pc += 1
- return regs[0]
- program = list(read_program(sys.stdin))
- print(run(program.copy(), 7))
- print(run(program, 12))
|