You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

43 lines
1.3KB

  1. import operator
  2. import re
  3. from collections import namedtuple
  4. from math import prod
  5. def make_monkey(description):
  6. relevant = re.findall(r'\d+|old|\*|\+', description)
  7. parsed = [int(n) if n.isdigit() else n for n in relevant]
  8. _, *items, _, op, y, div, aa, bb = parsed
  9. op = {'*': operator.mul, '+': operator.add}[op]
  10. grow_item = lambda x: op(x, x if y == 'old' else y)
  11. find_target = lambda x: aa if x % div == 0 else bb
  12. return Monkey(items, grow_item, find_target)
  13. def play(monkeys, n_rounds, shrink):
  14. counts = [0 for _ in monkeys]
  15. for _ in range(n_rounds):
  16. for idx, monkey in enumerate(monkeys):
  17. while monkey.items:
  18. counts[idx] += 1
  19. item = monkey.items.pop()
  20. item = monkey.grow_item(item)
  21. item = shrink(item)
  22. idx = monkey.find_target(item)
  23. monkeys[idx].items.append(item)
  24. return prod(sorted(counts)[-2:])
  25. text = open(0).read()
  26. Monkey = namedtuple('Monkey', ['items', 'grow_item', 'find_target'])
  27. monkeys = [make_monkey(descr) for descr in text.strip().split('\n\n')]
  28. ans1 = play(monkeys, 20, lambda x: x // 3)
  29. print(ans1)
  30. lim = prod(map(int, re.findall(r'divisible by (\d+)', text)))
  31. monkeys = [make_monkey(descr) for descr in text.strip().split('\n\n')]
  32. ans2 = play(monkeys, 10_000, lambda x: x % lim)
  33. print(ans2)