aoc2022/day11.py
2022-12-11 07:40:32 +01:00

101 lines
3.1 KiB
Python

from collections import defaultdict
from math import lcm
from tools.aoc import AOCDay
from typing import Any
class Monkey:
def __init__(self, monkey_id: int):
self.monkey_id = monkey_id
self.items = []
self.operation = None
self.test = None
self.action_true = None
self.action_false = None
def turn(self, part2: bool = False):
for _ in range(len(self.items)):
item = self.items.pop(0)
op, right = self.operation
if op == "+":
item += int(right)
elif right == "old":
item *= item
else:
item *= int(right)
if not part2:
item //= 3
if item % self.test == 0:
yield item, self.action_true
else:
yield item, self.action_false
class Day(AOCDay):
inputs = [
[
(10605, "input11_test"),
(98280, "input11"),
],
[
(2713310158, "input11_test"),
(17673687232, "input11"),
]
]
def get_monkeys(self) -> list:
monkeys = {}
current_monkey = None
for line in self.getInput():
if not line:
continue
if line.startswith("Monkey"):
current_monkey = Monkey(int(line[:-1].split(" ")[1]))
monkeys[current_monkey.monkey_id] = current_monkey
elif line.startswith(" Starting items:"):
current_monkey.items = list(map(int, line.split(": ")[1].split(", ")))
elif line.startswith(" Operation"):
current_monkey.operation = line.split(": ")[1].split(" = ")[1].split(" ")[1:]
elif line.startswith(" Test:"):
current_monkey.test = int(line.split(" ")[-1])
elif line.startswith(" If true:"):
current_monkey.action_true = int(line.split(" ")[-1])
elif line.startswith(" If false:"):
current_monkey.action_false = int(line.split(" ")[-1])
else:
print("Don't know how to parse '", line, "'")
return [monkeys[x] for x in sorted(monkeys)]
def get_monkey_business(self, amount: int = 20, part2: bool = False) -> int:
monkeys = self.get_monkeys()
monkey_inspects = defaultdict(int)
modder = lcm(*[m.test for m in monkeys])
for _ in range(amount):
for monkey in monkeys:
for item, target in monkey.turn(part2):
monkey_inspects[monkey.monkey_id] += 1
if part2:
monkeys[target].items.append(item % modder)
else:
monkeys[target].items.append(item)
f = sorted(monkey_inspects.values())[-2:]
return f[0] * f[1]
def part1(self) -> Any:
return self.get_monkey_business(20, False)
def part2(self) -> Any:
return self.get_monkey_business(10_000, True)
if __name__ == '__main__':
day = Day(2022, 11)
day.run(verbose=True)