#!/usr/bin/env python import re MONKEYS = [] def parse_factor(old, factor): if factor == 'old': return old return int(factor) OPS = { '*': lambda old, factor: old * parse_factor(old, factor), '+': lambda old, factor: old + parse_factor(old, factor), } with open('input') as f: monkey = {'inspections': 0} for line in f: if line == "\n": MONKEYS.append(monkey) monkey = {'inspections': 0} elif match := re.match('^Monkey (\d+):$', line): monkey['id'] = int(match[1]) elif match := re.match('^ Starting items:', line): _, items = line.rstrip().split(":") monkey['items'] = list(map(int, items.split(", "))) elif match := re.match('^ Operation: new = old ([\*\+]) (\w+)', line): monkey['op_op'] = match[1] monkey['op_factor'] = match[2] elif match := re.match('^ Test: divisible by (\d+)$', line): monkey['test_factor'] = int(match[1]) elif match := re.match('^ If (true|false): throw to monkey (\d+)$', line): monkey['test_'+match[1]] = int(match[2]) else: raise Exception('unhandled line: '+line) MONKEYS.append(monkey) for idx, monkey in enumerate(MONKEYS): assert(idx == monkey['id']) for r in range(1, 21): # round for monkey in MONKEYS: # turn for item in monkey['items']: item = OPS[monkey['op_op']](item, monkey['op_factor']) item = item // 3 if item % monkey['test_factor'] == 0: MONKEYS[monkey['test_true']]['items'].append(item) else: MONKEYS[monkey['test_false']]['items'].append(item) monkey['inspections'] = monkey['inspections'] + 1 monkey['items'] = [] by_inspections = sorted(MONKEYS, key=lambda monkey: monkey['inspections']) print(by_inspections[-1]['inspections'] * by_inspections[-2]['inspections'])