08_loop.py 1.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546
  1. #!/usr/bin/env python3
  2. import sys
  3. def parse(f):
  4. for line in f:
  5. opcode, arg = line.split()
  6. yield opcode, int(arg)
  7. def run(program, acc=0):
  8. ip = 0
  9. yield ip, acc
  10. while ip < len(program):
  11. opcode, arg = program[ip]
  12. if opcode == 'acc':
  13. acc += arg
  14. elif opcode == 'jmp':
  15. ip += arg - 1
  16. else:
  17. assert opcode == 'nop'
  18. ip += 1
  19. yield ip, acc
  20. def acc_after_one_iteration(program):
  21. seen = set()
  22. return next(acc for ip, acc in run(program) if ip in seen or seen.add(ip))
  23. def mutate(program):
  24. change = {'nop': 'jmp', 'jmp': 'nop'}
  25. for i, (opcode, arg) in enumerate(program):
  26. if opcode != 'acc':
  27. program[i] = change[opcode], arg
  28. yield program
  29. program[i] = opcode, arg
  30. def patch(program, maxn):
  31. for p in mutate(program):
  32. for n, (ip, acc) in zip(range(maxn), run(p)):
  33. pass
  34. if n < maxn - 1:
  35. return program
  36. program = list(parse(sys.stdin))
  37. print(acc_after_one_iteration(program))
  38. for ip, acc in run(patch(program, 1000)):
  39. pass
  40. print(acc)