Browse Source

Day 23

master
Chris Smith 7 years ago
parent
commit
8e387277eb
2 changed files with 124 additions and 0 deletions
  1. 98
    0
      23.py
  2. 26
    0
      data/23.txt

+ 98
- 0
23.py View File

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

+ 26
- 0
data/23.txt View File

@@ -0,0 +1,26 @@
1
+cpy a b
2
+dec b
3
+cpy a d
4
+cpy 0 a
5
+cpy b c
6
+inc a
7
+dec c
8
+jnz c -2
9
+dec d
10
+jnz d -5
11
+dec b
12
+cpy b c
13
+cpy c d
14
+dec d
15
+inc c
16
+jnz d -2
17
+tgl c
18
+cpy -16 c
19
+jnz 1 c
20
+cpy 73 c
21
+jnz 91 d
22
+inc a
23
+inc d
24
+jnz d -2
25
+inc c
26
+jnz c -5

Loading…
Cancel
Save