Advent of Code 2016 solutions https://adventofcode.com/2016/
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

23.py 2.7KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  1. #!/usr/bin/python3
  2. """Solution for day 23 of Advent of Code 2016.
  3. This is loosely based on day 12's solution. As instructions can now be modified (by the TGL opcode), they're kept
  4. in a 'register' as well.
  5. For part two to work in a reasonable amount of time, try_multiply implements a look-ahead optimisation for
  6. basic multiplication. Instructions of the form
  7. cpy b c
  8. inc a
  9. dec c
  10. jnz c -2
  11. dec d
  12. jnz d -5
  13. Are actually incrementing a by b*d, and setting both c and d to 0. The optimisation supports any registers, as long
  14. as they're distinct. It also only applies if the whole block of six instructions is reached naturally (i.e., execution
  15. doesn't jump into the middle of it).
  16. """
  17. def value(registers, x):
  18. try:
  19. return int(x)
  20. except ValueError:
  21. return registers[x]
  22. def cpy(registers, src, dst):
  23. registers[dst] = value(registers, src)
  24. def inc(registers, reg):
  25. registers[reg] += 1
  26. def dec(registers, reg):
  27. registers[reg] -= 1
  28. def jnz(registers, val, tar):
  29. registers['pc'] += 0 if value(registers, val) == 0 else value(registers, tar) - 1
  30. def tgl(registers, ins):
  31. mappings = {inc: dec, dec: inc, tgl: inc, jnz: cpy, cpy: jnz}
  32. target = registers['pc'] + value(registers, ins)
  33. registers['in'][target] = (mappings[registers['in'][target][0]], registers['in'][target][1])
  34. def try_multiply(registers):
  35. try:
  36. pc = registers['pc']
  37. chunk = registers['in'][pc:pc+6]
  38. instr, args = map(list, zip(*chunk))
  39. if instr == [cpy, inc, dec, jnz, dec, jnz] \
  40. and args[0][1] == args[2][0] == args[3][0] \
  41. and args[4][0] == args[5][0] \
  42. and args[1][0] != args[0][1] != args[4][0] != args[0][0] \
  43. and args[3][1] == '-2' and args[5][1] == '-5':
  44. registers[args[1][0]] += value(registers, args[0][0]) * value(registers, args[4][0])
  45. registers[args[2][0]] = 0
  46. registers[args[4][0]] = 0
  47. registers['pc'] += 5
  48. return True
  49. except:
  50. pass
  51. return False
  52. def step(registers):
  53. if not try_multiply(registers):
  54. try:
  55. registers['in'][registers['pc']][0](registers, *registers['in'][registers['pc']][1])
  56. except:
  57. pass
  58. def run(values):
  59. registers = values
  60. registers['pc'] = 0
  61. registers['in'] = instr.copy()
  62. while registers['pc'] < len(instr):
  63. step(registers)
  64. registers['pc'] += 1
  65. return registers['a']
  66. with open('data/23.txt', 'r') as file:
  67. instr = map(str.split, map(str.strip, file.readlines()))
  68. instr = [(globals()[i[0]], i[1:]) for i in instr]
  69. print("Stage 1: %s" % run({'a': 7, 'b': 0, 'c': 0, 'd': 0}))
  70. print("Stage 2: %s" % run({'a': 12, 'b': 0, 'c': 0, 'd': 0}))