|
|
@@ -0,0 +1,46 @@
|
|
|
+#!/usr/bin/env python3
|
|
|
+import sys
|
|
|
+
|
|
|
+def parse(f):
|
|
|
+ for line in f:
|
|
|
+ opcode, arg = line.split()
|
|
|
+ yield opcode, int(arg)
|
|
|
+
|
|
|
+def run(program, acc=0):
|
|
|
+ ip = 0
|
|
|
+ yield ip, acc
|
|
|
+ while ip < len(program):
|
|
|
+ opcode, arg = program[ip]
|
|
|
+ if opcode == 'acc':
|
|
|
+ acc += arg
|
|
|
+ elif opcode == 'jmp':
|
|
|
+ ip += arg - 1
|
|
|
+ else:
|
|
|
+ assert opcode == 'nop'
|
|
|
+ ip += 1
|
|
|
+ yield ip, acc
|
|
|
+
|
|
|
+def acc_after_one_iteration(program):
|
|
|
+ seen = set()
|
|
|
+ return next(acc for ip, acc in run(program) if ip in seen or seen.add(ip))
|
|
|
+
|
|
|
+def mutate(program):
|
|
|
+ change = {'nop': 'jmp', 'jmp': 'nop'}
|
|
|
+ for i, (opcode, arg) in enumerate(program):
|
|
|
+ if opcode != 'acc':
|
|
|
+ program[i] = change[opcode], arg
|
|
|
+ yield program
|
|
|
+ program[i] = opcode, arg
|
|
|
+
|
|
|
+def patch(program, maxn):
|
|
|
+ for p in mutate(program):
|
|
|
+ for n, (ip, acc) in zip(range(maxn), run(p)):
|
|
|
+ pass
|
|
|
+ if n < maxn - 1:
|
|
|
+ return program
|
|
|
+
|
|
|
+program = list(parse(sys.stdin))
|
|
|
+print(acc_after_one_iteration(program))
|
|
|
+for ip, acc in run(patch(program, 1000)):
|
|
|
+ pass
|
|
|
+print(acc)
|