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
|
from copy import deepcopy
from dataclasses import dataclass
from functools import partial, reduce
from operator import mul as mul_op
from typing import Callable
def identity(o):
return o
def value(v, _):
return v
def add(a, b, o):
return a(o) + b(o)
def mul(a, b, o):
return a(o) * b(o)
@dataclass
class Monkey:
items: list[int]
op: Callable[[int], int]
test_div: int
target: tuple[int, int]
inspections: int = 0
def from_str(s):
items, op, test_div, true_tgt, false_tgt = [l.split(': ')[1] for l in s.split('\n')[1:]]
items = [int(i) for i in items.split(', ')]
op = op.split(' ')[2:]
lhs = identity if op[0] == 'old' else partial(value, int(op[0]))
rhs = identity if op[2] == 'old' else partial(value, int(op[2]))
op = partial(add, lhs, rhs) if op[1] == '+' else partial(mul, lhs, rhs)
test_div = int(test_div.split(' ')[-1])
true_tgt = int(true_tgt.split(' ')[-1])
false_tgt = int(false_tgt.split(' ')[-1])
return Monkey(items, op, test_div, (true_tgt, false_tgt))
with open('11.in') as f:
monkeys = [Monkey.from_str(m) for m in f.read().rstrip().split('\n\n')]
def solve(monkeys, rounds, do_div):
monkeys = deepcopy(monkeys)
modulo = reduce(mul_op, (m.test_div for m in monkeys), 1)
for _ in range(rounds):
for m in monkeys:
while m.items:
m.inspections += 1
i = m.items.pop(0)
i = m.op(i)
if do_div: i //= 3
target = m.target[min(i % m.test_div, 1)]
monkeys[target].items.append(i % modulo)
return reduce(mul_op, sorted(m.inspections for m in monkeys)[-2:], 1)
print(solve(monkeys, 20, True))
print(solve(monkeys, 10000, False))
|