2024-01-03 20:50:55 +00:00
|
|
|
import sys
|
|
|
|
|
2024-01-04 03:42:27 +00:00
|
|
|
|
2024-01-03 20:50:55 +00:00
|
|
|
def part1(workflows: dict[str, list[list[str]]], ratings: str) -> int:
|
|
|
|
result = 0
|
|
|
|
|
|
|
|
for rating in ratings.splitlines():
|
|
|
|
assert [r.split("=")[0] for r in rating[1:-1].split(",")] == list("xmas")
|
|
|
|
(x, m, a, s) = (int(r.split("=")[1]) for r in rating[1:-1].split(","))
|
2024-01-04 03:42:27 +00:00
|
|
|
|
2024-01-03 20:50:55 +00:00
|
|
|
workflow = "in"
|
|
|
|
while workflow not in "RA":
|
|
|
|
for rule in workflows[workflow]:
|
|
|
|
match rule:
|
|
|
|
case [target]:
|
|
|
|
workflow = target
|
|
|
|
break
|
|
|
|
case [condition, target]:
|
|
|
|
if eval(condition):
|
|
|
|
workflow = target
|
|
|
|
break
|
|
|
|
|
|
|
|
if workflow == "A":
|
|
|
|
result += sum((x, m, a, s))
|
|
|
|
|
|
|
|
return result
|
|
|
|
|
|
|
|
|
|
|
|
def part2(workflows: dict[str, list[list[str]]]) -> int:
|
|
|
|
result = 0
|
|
|
|
stack = [("in", (1, 4001), (1, 4001), (1, 4001), (1, 4001))]
|
|
|
|
while stack:
|
|
|
|
(workflow, x, m, a, s) = stack.pop()
|
|
|
|
|
|
|
|
if workflow == "A":
|
|
|
|
result += (x[1] - x[0]) * (m[1] - m[0]) * (a[1] - a[0]) * (s[1] - s[0])
|
|
|
|
continue
|
|
|
|
|
|
|
|
if workflow == "R":
|
|
|
|
continue
|
|
|
|
|
|
|
|
for rule in workflows[workflow]:
|
|
|
|
match rule:
|
|
|
|
case [target]:
|
|
|
|
stack.append((target, x, m, a, s))
|
|
|
|
case [condition, target] if ">" in condition:
|
|
|
|
(var, value_) = condition.split(">")
|
|
|
|
value = int(value_) + 1
|
|
|
|
match var:
|
|
|
|
case "x":
|
|
|
|
stack.append((target, (value, x[1]), m, a, s))
|
|
|
|
x = (x[0], value)
|
|
|
|
case "m":
|
|
|
|
stack.append((target, x, (value, m[1]), a, s))
|
|
|
|
m = (m[0], value)
|
|
|
|
case "a":
|
|
|
|
stack.append((target, x, m, (value, a[1]), s))
|
|
|
|
a = (a[0], value)
|
|
|
|
case "s":
|
|
|
|
stack.append((target, x, m, a, (value, s[1])))
|
|
|
|
s = (s[0], value)
|
|
|
|
case [condition, target] if "<" in condition:
|
|
|
|
(var, value_) = condition.split("<")
|
|
|
|
value = int(value_)
|
|
|
|
match var:
|
|
|
|
case "x":
|
|
|
|
stack.append((target, (x[0], value), m, a, s))
|
|
|
|
x = (value, x[1])
|
|
|
|
case "m":
|
|
|
|
stack.append((target, x, (m[0], value), a, s))
|
|
|
|
m = (value, m[1])
|
|
|
|
case "a":
|
|
|
|
stack.append((target, x, m, (a[0], value), s))
|
|
|
|
a = (value, a[1])
|
|
|
|
case "s":
|
|
|
|
stack.append((target, x, m, a, (s[0], value)))
|
|
|
|
s = (value, s[1])
|
|
|
|
return result
|
|
|
|
|
2024-01-04 03:42:27 +00:00
|
|
|
|
2024-01-03 20:50:55 +00:00
|
|
|
def main() -> None:
|
|
|
|
with open(sys.argv[1]) as f:
|
|
|
|
(workflows_, ratings) = f.read().split("\n\n")
|
2024-01-04 03:42:27 +00:00
|
|
|
|
2024-01-03 20:50:55 +00:00
|
|
|
workflows = {}
|
|
|
|
for workflow in workflows_.splitlines():
|
|
|
|
(name, rules_) = workflow.split("{", 1)
|
|
|
|
rules = [rule.split(":") for rule in rules_[:-1].split(",")]
|
|
|
|
workflows[name] = rules
|
|
|
|
|
|
|
|
p1 = part1(workflows, ratings)
|
|
|
|
p2 = part2(workflows)
|
|
|
|
print(p1, p2)
|
|
|
|
|
2024-01-04 03:42:27 +00:00
|
|
|
|
2024-01-03 20:50:55 +00:00
|
|
|
if __name__ == "__main__":
|
2024-01-04 03:42:27 +00:00
|
|
|
main()
|