-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathday19.py
110 lines (95 loc) · 3.31 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
97
98
99
100
101
102
103
104
105
106
107
108
109
110
from benchy import minibench
lines = open("day19.txt").read().split("\n")
def replace(t, i, v):
r = t.copy()
r[i] = v
return r
class BaseRule():
def __init__(self, name, lbl = None) -> None:
self.name = name
self.lbl = lbl
self.rule = None
self.next = None
def apply(self, ho, hoho) -> None:
# print("{} => {}".format(self.name, self.lbl))
return self.rule.apply(ho, hoho)
class BasicRule(BaseRule):
def __init__(self, name, lbl, i, n, v) -> None:
BaseRule.__init__(self, name, lbl)
self.v = v
self.n = n
self.i = i
class LessRule(BasicRule):
def apply(self, ho, hoho):
# print("{} {}({}-{}) < {} : {} / {}".format(self.name, self.v, ho[self.i], hoho[self.i], self.n, self.lbl, self.next.name))
if hoho[self.i] < self.n:
return self.rule.apply(ho, hoho)
if ho[self.i] < self.n:
return self.rule.apply(ho, replace(hoho, self.i, self.n - 1)) + self.next.apply(replace(ho, self.i, self.n), hoho)
return self.next.apply(ho, hoho)
class MoreRule(BasicRule):
def apply(self, ho, hoho):
# print("{} {}({}-{}) > {} : {} / {}".format(self.name, self.v, ho[self.i], hoho[self.i], self.n, self.lbl, self.next.lbl))
if ho[self.i] > self.n:
return self.rule.apply(ho, hoho)
if hoho[self.i] > self.n:
return self.rule.apply(replace(ho, self.i, self.n + 1), hoho) + self.next.apply(ho, replace(hoho, self.i, self.n))
return self.next.apply(ho, hoho)
class Accept(BaseRule):
def apply(self, ho, hoho) -> None:
return (hoho[0] - ho[0] + 1) * (hoho[1] - ho[1] + 1) * (hoho[2] - ho[2] + 1) * (hoho[3] - ho[3] + 1)
class Reject(BaseRule):
def apply(self, ho, hoho) -> None:
return 0
rules = {}
insn = []
def parse():
rules.clear()
insn.clear()
mapp = {"x": 0, "m": 1, "a": 2, "s": 3}
rules["A"] = Accept("A")
rules["R"] = Reject("R")
all_rules = []
for line in lines:
pos = line.find("{")
if pos > 0:
tok = line[:pos]
rrr = line[pos + 1 : -1].split(",")
prev = None
for r in rrr:
if ":" in r:
a, b = r.split(":")
v, o, n = a[0], a[1], int(a[2:])
i = mapp[v]
if o == "<":
rule = LessRule(tok, b, i, n, v)
else:
rule = MoreRule(tok, b, i, n, v)
else:
rule = BaseRule(tok, r)
all_rules.append(rule)
if prev:
prev.next = rule
else:
rules[tok] = rule
prev = rule
elif pos == 0:
hohoho = []
for t in line[1:-1].split(","):
_, n = t.split("=")
hohoho.append(int(n))
insn.append(hohoho)
for rule in all_rules:
rule.rule = rules[rule.lbl]
return len(insn)+len(rules)
def part1():
ret = 0
for hohoho in insn:
ret += sum(hohoho) * rules["in"].apply(hohoho, hohoho)
return ret
def part2():
return rules["in"].apply([1,1,1,1],[4000,4000,4000,4000])
parse()
print(part1())
print(part2())
minibench({"parse": parse, "part1": part1, "part2": part2})