|
@@ -0,0 +1,63 @@
|
|
1
|
+import re
|
|
2
|
+from collections import defaultdict
|
|
3
|
+
|
|
4
|
+VALUE = 0
|
|
5
|
+MOVE = 1
|
|
6
|
+STATE = 2
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+def parse():
|
|
10
|
+ begin_state = re.compile(r'Begin in state (.*?)\.')
|
|
11
|
+ checksum_steps = re.compile(r'Perform a diagnostic checksum after ([0-9]+) steps\.')
|
|
12
|
+ state_header = re.compile(r'In state (.*?):')
|
|
13
|
+ value_header = re.compile(r'If the current value is ([01]):')
|
|
14
|
+ value_action = re.compile(r'- Write the value ([01])\.')
|
|
15
|
+ move_action = re.compile(r'- Move one slot to the (right|left)\.')
|
|
16
|
+ state_action = re.compile(r'- Continue with state (.*?)\.')
|
|
17
|
+
|
|
18
|
+ initial_state = checksum = None
|
|
19
|
+ transitions = defaultdict(lambda: [[None]*3, [None]*3])
|
|
20
|
+ cur_state = None
|
|
21
|
+ cur_value = None
|
|
22
|
+
|
|
23
|
+ with open('data/25.txt') as file:
|
|
24
|
+ for line in file.readlines():
|
|
25
|
+ line = line.strip()
|
|
26
|
+ if len(line) == 0:
|
|
27
|
+ continue
|
|
28
|
+
|
|
29
|
+ if initial_state is None:
|
|
30
|
+ initial_state = begin_state.match(line).group(1)
|
|
31
|
+ elif checksum is None:
|
|
32
|
+ checksum = int(checksum_steps.match(line).group(1))
|
|
33
|
+ elif cur_state is None:
|
|
34
|
+ cur_state = state_header.match(line).group(1)
|
|
35
|
+ elif cur_value is None:
|
|
36
|
+ cur_value = int(value_header.match(line).group(1))
|
|
37
|
+ elif transitions[cur_state][cur_value][VALUE] is None:
|
|
38
|
+ transitions[cur_state][cur_value][VALUE] = int(value_action.match(line).group(1))
|
|
39
|
+ elif transitions[cur_state][cur_value][MOVE] is None:
|
|
40
|
+ transitions[cur_state][cur_value][MOVE] = move_action.match(line).group(1)
|
|
41
|
+ elif transitions[cur_state][cur_value][STATE] is None:
|
|
42
|
+ transitions[cur_state][cur_value][STATE] = state_action.match(line).group(1)
|
|
43
|
+ if cur_value == 1:
|
|
44
|
+ cur_state = None
|
|
45
|
+ cur_value = None
|
|
46
|
+
|
|
47
|
+ return initial_state, checksum, dict(transitions)
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+def execute(state, rounds, transitions):
|
|
51
|
+ tape = defaultdict(lambda: 0)
|
|
52
|
+ head = 0
|
|
53
|
+ for _ in range(rounds):
|
|
54
|
+ instr = transitions[state][tape[head]]
|
|
55
|
+ tape[head] = instr[VALUE]
|
|
56
|
+ head += 1 if instr[MOVE] == 'right' else -1
|
|
57
|
+ state = instr[STATE]
|
|
58
|
+
|
|
59
|
+ return sum(v for v in tape.values() if v == 1)
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+state, target, transitions = parse()
|
|
63
|
+print(execute(state, target, transitions))
|