This commit is contained in:
Sven Heidemann 2022-12-11 10:43:57 +01:00
parent 40c08275cc
commit 12d1c427cf

122
src/day11.py Normal file
View File

@ -0,0 +1,122 @@
import textwrap
from dataclasses import dataclass
from functools import reduce
from math import lcm
from typing import Optional
from cpl_core.console import Console
from cpl_core.utils import String
from cpl_query.enumerable import Enumerable
from cpl_query.extension import List
from cpl_core.pipes import *
from aoc.aoc import get_input
# global vars
day = 11
aoc_input = get_input(2022, day)
aoc_input1 = """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
"""
class Monkey:
def __init__(self, m: List[str]):
self.items = List(int)
self.operation = ''
self.test = ''
self.test_true_action = None
self.test_false_action = None
self.inspects = 0
for x in m:
x = str(x).replace(' ', '')
if ':' not in x:
continue
atr, value = x.split(':')
match atr:
case 'Startingitems':
for v in value.split(','):
self.items.append(int(v))
case 'Operation':
self.operation = value
case 'Test':
self.test = value
self.divisor = int(self.test.split('divisibleby')[1])
case 'Iftrue':
self.test_true_action = value
case 'Iffalse':
self.test_false_action = value
self.initial_items = self.items.copy()
def __repr__(self):
return f'<Monkey {self.inspects} {self.items}>'
def do_work(self, monkeys: List['Monkey'], modulus, part2=False):
remove = []
for old in self.items:
self.inspects += 1
if part2:
new = int(eval(self.operation.split('=')[1]))
else:
new = int(eval(self.operation.split('=')[1]) / 3)
new %= modulus
divisible = new % int(self.test.split('divisibleby')[1]) == 0
throw_to = monkeys.element_at(int((self.test_true_action if divisible else self.test_false_action).split('throwtomonkey')[1]))
throw_to.items.append(new)
remove.append(old)
for r in remove:
self.items.remove(r)
def main(part2=False):
monkeys = List(str, aoc_input.splitlines()) \
.select(lambda x: x if not str(x).startswith('Monkey') else None).where(lambda x: x is not None) \
.split(lambda x: '') \
.select(lambda monkey: Monkey(monkey))
mod = lcm(*monkeys.select(lambda x: x.divisor))
for i in range(0, 10000 if part2 else 20):
for m in monkeys:
m.do_work(monkeys, mod, part2)
Console.write_line(reduce((lambda x, y: x * y), monkeys.order_by_descending(lambda x: x.inspects).take(2).select(lambda x: x.inspects)))
if __name__ == '__main__':
Console.write_line(f'Advent of code day {day}')
main()
main(True)
Console.write_line()