-
Notifications
You must be signed in to change notification settings - Fork 0
/
day19.solution.py
86 lines (78 loc) · 2.41 KB
/
day19.solution.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
import functools
import re
from sys import stderr
with open('day19.input.txt') as f:
in_workflow = True
workflow, parts = {}, []
for line in f:
if not line.strip():
in_workflow = False
continue
if in_workflow:
wf = line.strip().split('{')
workflow[wf[0]] = wf[1][:-1].split(',')
else:
parts.append(line.strip()[1:-1].split(','))
summ = 0
for ratings in parts:
scope = {}
for r in (rat.split('=') for rat in ratings):
scope[r[0]] = int(r[1])
wf = workflow['in']
while wf:
for arule in wf:
token = None
if re.search(r':', arule):
rule, nxt = arule.split(':')
if eval(rule, scope.copy()):
token = nxt
else:
token = arule
if token:
if token == 'A':
summ += sum(scope.values())
wf = None
elif token == 'R':
wf = None
else:
wf = workflow[token]
break
print(summ)
# part 2: DFS
summ = 0
def dfs(token, ratings):
global summ, workflow
if token == 'A':
summ += functools.reduce(lambda x, y: x * y, [rng[1] - rng[0] + 1 for rng in ratings.values()])
return
elif token == 'R':
return
for arule in workflow[token]:
if re.search(r':', arule):
rule, nxt = arule.split(':')
ll, rr = ratings[rule[0]]
if rule[1] == '<':
rmax = int(rule[2:])
if rr < rmax:
dfs(nxt, ratings)
elif ll < rmax <= rr:
rat = ratings.copy()
rat[rule[0]] = [ll, rmax - 1]
dfs(nxt, rat)
ratings[rule[0]] = [rmax, rr]
elif rule[1] == '>':
rmin = int(rule[2:])
if ll > rmin:
dfs(nxt, ratings)
elif ll <= rmin < rr:
rat = ratings.copy()
rat[rule[0]] = [rmin + 1, rr]
dfs(nxt, rat)
ratings[rule[0]] = [ll, rmin]
else:
print('error', file=stderr)
exit(1)
else:
dfs(arule, ratings)
dfs('in', dict((token, [1, 4000]) for token in ('x', 'm', 'a', 's')))
print(summ)