intcode.py 1.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960
  1. from operator import add, mul, lt, eq
  2. def read_program(f):
  3. return list(map(int, f.readline().split(',')))
  4. def run(p):
  5. def decode_param(offset):
  6. return p[pc + offset], modes // (10 ** (offset - 1)) % 10
  7. def address(param, mode):
  8. addr = param + relbase * mode // 2
  9. if addr >= len(p):
  10. p.extend([0] * (addr - len(p) + 1))
  11. return addr
  12. def pload(offset):
  13. param, mode = decode_param(offset)
  14. return param if mode == 1 else p[address(param, mode)]
  15. def pstore(offset, value):
  16. param, mode = decode_param(offset)
  17. p[address(param, mode)] = value
  18. opmap = {1: add, 2: mul, 7: lt, 8: eq}
  19. p = list(p)
  20. pc = relbase = 0
  21. while p[pc] != 99:
  22. modes, opcode = divmod(p[pc], 100)
  23. if opcode in (1, 2, 7, 8):
  24. pstore(3, opmap[opcode](pload(1), pload(2)))
  25. pc += 4
  26. elif opcode == 3:
  27. pstore(1, (yield))
  28. pc += 2
  29. elif opcode == 4:
  30. yield pload(1)
  31. pc += 2
  32. elif opcode == 5:
  33. pc = pload(2) if pload(1) else pc + 3
  34. elif opcode == 6:
  35. pc = pload(2) if not pload(1) else pc + 3
  36. elif opcode == 9:
  37. relbase += pload(1)
  38. pc += 2
  39. def run_inputs(p, inputs):
  40. inputs = iter(inputs)
  41. computer = run(p)
  42. for outp in computer:
  43. while outp is None:
  44. outp = computer.send(next(inputs))
  45. yield outp
  46. def run_getter(p, get_input):
  47. def gen_inputs():
  48. while True:
  49. yield get_input()
  50. return run_inputs(p, gen_inputs())