-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathday11.py
executable file
·116 lines (88 loc) · 3.23 KB
/
day11.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
111
112
113
114
115
116
from dataclasses import dataclass
from math import prod
from typing import List, Callable
from parse import findall, parse
from run_util import run_puzzle
@dataclass
class Monkey:
items: List[int]
inspect: Callable[[int], int]
operation: Callable[[int], int]
divisor: int
destination: Callable[[int], int]
inspected: int = 0
def ook(self):
self.inspected += len(self.items)
for item in self.items:
item = self.operation(item)
item = self.inspect(item)
yield self.destination(item), item
self.items = []
def go_bananas(monkeys: List[Monkey], rounds):
for _ in range(rounds):
for monkey in monkeys:
for target, item in monkey.ook():
monkeys[target].items.append(item)
inspection_counts: List[int] = sorted([monkey.inspected for monkey in monkeys])
return inspection_counts[-2] * inspection_counts[-1]
def parse_monkeys(data: str, relaxed: bool) -> List[Monkey]:
monkeys: List[Monkey] = []
for monkey in data.split('\n\n'):
_index, items, operation, test, true, false = [line.strip() for line in monkey.split('\n')]
items = [item[0] for item in findall("{:d}", items)]
inspect = lambda x: x // 3
op, value = parse("Operation: new = old {} {}", operation)
match (op, value):
case ('*', 'old'):
operation = lambda x: x * x
case ('*', value):
operation = (lambda value: lambda x: x * value)(int(value))
case ('+', value):
operation = (lambda value: lambda x: x + value)(int(value))
divisor, = parse("Test: divisible by {:d}", test)
true, = parse("If true: throw to monkey {:d}", true)
false, = parse("If false: throw to monkey {:d}", false)
destination = (lambda divisor, true, false: lambda x: true if x % divisor == 0 else false)(divisor, true, false)
monkeys.append(Monkey(items, inspect, operation, divisor, destination))
if relaxed:
product = prod([monkey.divisor for monkey in monkeys])
for idx in range(len(monkeys)):
monkeys[idx].inspect = (lambda product: lambda x: x % product)(product)
return monkeys
def part_a(data):
monkeys = parse_monkeys(data, relaxed=False)
return go_bananas(monkeys, 20)
def part_b(data):
monkeys = parse_monkeys(data, relaxed=True)
return go_bananas(monkeys, 10000)
def main():
examples = [
("""Monkey 0:
Starting items: 79, 98
Operation: new = old * 19
Test: divisible by 23
If true: throw to monkey 2
If false: throw to monkey 3
Monkey 1:
Starting items: 54, 65, 75, 74
Operation: new = old + 6
Test: divisible by 19
If true: throw to monkey 2
If false: throw to monkey 0
Monkey 2:
Starting items: 79, 60, 97
Operation: new = old * old
Test: divisible by 13
If true: throw to monkey 1
If false: throw to monkey 3
Monkey 3:
Starting items: 74
Operation: new = old + 3
Test: divisible by 17
If true: throw to monkey 0
If false: throw to monkey 1""", 10605, 2713310158)
]
day = int(__file__.split('/')[-1].split('.')[0][-2:])
run_puzzle(day, part_a, part_b, examples)
if __name__ == '__main__':
main()