-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathDay24.py
205 lines (158 loc) · 4 KB
/
Day24.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
from sys import argv, stdin
from dataclasses import dataclass
import re
from typing import List, Tuple
"""
This is a special purpose solution. It may or may not work with your input.
This solution parses the input looking for two types of patterns:
- Forced actions: These actions will be run, regardless the condition.
```
if i0 - 14 != z.top():
z.push(i0 + 14)
```
Corresponds to this ALU code:
```
inp w
mul x 0
add x z
mod x 26
div z 1
add x 14
eql x w
eql x 0
mul y 0
add y 25
mul y x
add y 1
mul z y
mul y 0
add y w
add y 14
mul y x
add z y
```
- Conditional actions: These actions depend on the stack's top value.
```
if i5 + 12 == z.top():
z.pop()
else:
z.pop()
z.push(i5 + 5)
```
Corresponds to this ALU code:
```
inp w
mul x 0
add x z
mod x 26
div z 26
add x -12
eql x w
eql x 0
mul y 0
add y 25
mul y x
add y 1
mul z y
mul y 0
add y w
add y 5
mul y x
add z y
```
The divisor on the fifth line of each ALU code fragment determines which type of
condition it is.
Then, each possible execution path is considered taking into account the stack
(z's value) and the given condition. It branches when it is not a forced condition.
There should be only one execution path that has its stack empty at the end, from
which the maximum possible value is calculated using the conditions that were chosen
for this specific execution path.
"""
def split(lines, items):
return [
[
*[int(m[0]) if (m := re.match(r"-?\d+", w)) else w for w in l.split(" ")],
*([None] * items),
][:items]
for l in lines
]
lines = split(map(str.strip, stdin.readlines()), 3)
@dataclass
class InputSum:
name: str
right: int
def __repr__(self):
symbol = "+" if self.right >= 0 else "-"
return f"{self.name} {symbol} {abs(self.right)}"
@dataclass
class StackAction:
cond: InputSum
to_push: InputSum
is_forced: bool
@property
def code(self):
if self.is_forced:
return f"""\
if {self.cond} != z.top():
z.push({self.to_push})
"""
else:
return f"""\
if {self.cond} == z.top():
z.pop()
else:
z.pop()
z.push({self.to_push})
"""
@dataclass
class CheckEq:
left: InputSum
right: InputSum
value: bool
def __repr__(self):
symbol = "==" if self.value else "!="
return f"{self.left} {symbol} {self.right}"
actions = []
for i in range(14):
cur = lines[i * 18 : (i + 1) * 18]
cond = InputSum(f"i{i}", -cur[5][-1])
push = InputSum(f"i{i}", cur[-3][-1])
actions.append(StackAction(cond, push, cur[4][-1] == 1))
stacks: List[Tuple[List[CheckEq], List[InputSum]]] = [([], [])]
for c in actions:
new_stacks = []
for pcond, ps in stacks:
if c.is_forced:
cond = pcond.copy()
s = ps.copy()
s.append(c.to_push)
new_stacks.append((cond, s))
else:
cond1 = pcond.copy()
cond2 = pcond.copy()
s1 = ps.copy()
s2 = ps.copy()
cond1.append(CheckEq(c.cond, s1[-1], True))
s1.pop()
cond2.append(CheckEq(c.cond, s2[-1], False))
s2.pop()
s2.append(c.to_push)
new_stacks.append((cond1, s1))
new_stacks.append((cond2, s2))
stacks = new_stacks
value_mappings = [0] * 14
maximize = argv[1] == "1"
for cs, s in stacks:
if len(s) == 0:
for c in cs:
l, r = c.left.name, c.right.name
lv, rv = c.left.right, c.right.right
if lv > rv:
l, r = r, l
lv, rv = rv, lv
rv -= lv
r_final = 9 - rv if maximize else 1
l_final = r_final + rv
value_mappings[int(r[1:])] = r_final
value_mappings[int(l[1:])] = l_final
print("".join(map(str, value_mappings)))