-
Notifications
You must be signed in to change notification settings - Fork 16
/
Copy pathday19.py
executable file
·96 lines (73 loc) · 1.81 KB
/
day19.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
#!/usr/bin/env python3
from utils.all import *
def emu(flow, x, m, a, s):
cur = 'in'
while cur != 'A' and cur != 'R':
insns, last = flow[cur]
for exp, nxt in insns:
if eval(exp):
cur = nxt
break
else:
cur = last
if cur == 'A':
return x + m + a + s
return 0
# @log_calls_recursive()
def emu_comb(cur='in', vars={'x': (1,4000), 'm': (1,4000), 'a': (1,4000), 's': (1,4000)}):
if cur == 'R':
return 0
if cur == 'A':
x = [mmax - mmin + 1 for mmin, mmax in vars.values()]
# emu_comb.eprint(x)
return prod(x)
for (mmin, mmax) in vars.values():
assert mmin <= mmax
insns, last = flow[cur]
total = 0
for exp, nxt in insns:
var, op, value = exp[0], exp[1], exp[2:]
value = int(value)
if op == '<':
mmin, mmax = vars[var]
if mmin < value:
newvars = vars | {var: (mmin, value - 1)}
total += emu_comb(nxt, newvars)
# to advance satisfy the opposite (>=)
if mmax >= value:
vars[var] = (value, mmax)
else:
break
else:
mmin, mmax = vars[var]
if mmax > value:
newvars = vars | {var: (value + 1, mmax)}
total += emu_comb(nxt, newvars)
# to advance satisfy the opposite (<=)
if mmin <= value:
vars[var] = (mmin, value)
else:
break
total += emu_comb(last, deepcopy(vars))
return total
advent.setup(2023, 19)
fin = advent.get_input()
data = fin.read()
ans1 = ans2 = 0
progs, vals = data.split('\n\n')
progs = progs.splitlines()
vals = vals.splitlines()
flow = {}
for p in progs:
name = re.findall(r'(\w+)\{.+', p)[0]
insns = p[p.find('{') + 1:-1]
insns = insns.split(',')
insns = list(map(lambda x: tuple(x.split(':')), insns))
last = insns.pop()[0]
flow[name] = (insns, last)
for v in vals:
x, m, a, s = extract_ints(v)
ans1 += emu(flow, x, m, a, s)
advent.print_answer(1, ans1)
ans2 = emu_comb()
advent.print_answer(2, ans2)