-
Notifications
You must be signed in to change notification settings - Fork 0
/
part2.py
66 lines (51 loc) Β· 1.87 KB
/
part2.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
import copy, math, functools as ft
[workflows_str, parts_str] = open("input.txt").read().split("\n\n")
class Rule:
def __init__(self, category, op, value, send_to):
self.category = category
self.op = op
self.value = value
self.send_to = send_to
@classmethod
def default_rule(cls, send_to):
return cls(None, None, None, send_to)
workflows = {}
for line in workflows_str.strip().split("\n"):
[name, content] = line[0:-1].split("{")
rules = []
rules_str = content.split(",")
for rule in rules_str[0:-1]:
[cond, send_to] = rule.split(":")
op = (lambda a, b: a > b) if cond[1] == ">" else (lambda a, b: a < b)
rules.append(Rule(cond[0], op, int(cond[2:]), send_to))
rules.append(Rule.default_rule(rules_str[-1]))
workflows[name] = rules
parts = []
for line in parts_str.strip().split("\n"):
part = {}
for ratings in line[1:-1].split(","):
[category, value] = ratings.split("=")
part[category] = int(value)
parts.append(part)
def recurse(workflows, send_to, rangs):
if send_to == 'R': return 0
elif send_to == 'A': return math.prod([len(rangs[category]) for category in rangs])
sum = 0
for rule in workflows[send_to]:
if rule.category == None:
sum += recurse(workflows, rule.send_to, rangs)
break
rang = rangs[rule.category]
filtered = list(filter(lambda x: rule.op(x, rule.value), rang))
if filtered != []:
rangs_copy = rangs.copy()
rangs_copy[rule.category] = filtered
sum += recurse(workflows, rule.send_to, rangs_copy)
rangs[rule.category] = list(x for x in rang if not rule.op(x, rule.value))
return sum
print(recurse(workflows, "in", {
"x": range(1, 4001),
"m": range(1, 4001),
"a": range(1, 4001),
"s": range(1, 4001),
}))