25_antenna.py 1.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768
  1. #!/usr/bin/env python3
  2. import sys
  3. from itertools import count, islice
  4. def read_program(f):
  5. maybe_int = lambda x: int(x) if x.isdigit() or x[0] == '-' else x
  6. for line in f:
  7. instr = tuple(map(maybe_int, line.split()))
  8. yield instr + (None,) * (3 - len(instr))
  9. def check_mul(p, pc):
  10. if pc <= len(p) - 5:
  11. opcodes, a, b = zip(*p[pc:pc + 5])
  12. if a[1] == a[2] and a[3] == a[4] and b[2] == -2 and b[4] == -5:
  13. if opcodes == ('inc', 'dec', 'jnz', 'dec', 'jnz'):
  14. return a[1], a[3]
  15. def run(p, init):
  16. regs = [init, 0, 0, 0]
  17. pc = 0
  18. def load(x):
  19. return x if isinstance(x, int) else regs[ord(x) - ord('a')]
  20. def store(reg, value):
  21. regs[ord(reg) - ord('a')] = value
  22. while pc < len(p):
  23. opcode, a, b = p[pc]
  24. if opcode == 'cpy':
  25. store(b, load(a))
  26. elif opcode == 'inc':
  27. params = check_mul(p, pc)
  28. if params:
  29. reg1, reg2 = params
  30. increment = load(reg1) * load(reg2)
  31. store(reg1, 0)
  32. store(reg2, 0)
  33. pc += 4
  34. else:
  35. increment = 1
  36. store(a, load(a) + increment)
  37. elif opcode == 'dec':
  38. store(a, load(a) - 1)
  39. elif opcode == 'jnz':
  40. if load(a):
  41. pc += load(b) - 1
  42. elif opcode == 'out':
  43. yield load(a)
  44. pc += 1
  45. return regs[0]
  46. def is_clock(signal):
  47. expect = 0
  48. for x in islice(signal, 8):
  49. if x != expect:
  50. return False
  51. expect = 1 - expect
  52. return True
  53. def find_clock(p):
  54. for a in count(0):
  55. if is_clock(run(p, a)):
  56. return a
  57. program = list(read_program(sys.stdin))
  58. print(find_clock(program))