from itertools import zip_longest
from functools import reduce
from operator import mul

def grouper(n, iterable, padvalue=None):
  return zip_longest(*[iter(iterable)]*n, fillvalue=padvalue)

lines = [line.strip() for line in open("11.input")]

def get_monkeys():
    monkeys = []

    for chunk in grouper(7, lines):
        items = chunk[1].split(":")
        items = items[1].strip().split(", ")
        exp = chunk[2].split("=")[1]
        monkeys.append({
            "items": list(map(int, items)),
            "op": exp,
            "test": int(chunk[3].split(" ")[-1]),
            "true": int(chunk[4].split(" ")[-1]),
            "false": int(chunk[5].split(" ")[-1]),
            "inspects": 0,
            })
    return monkeys


def run_part(part, rounds, monkeys):
    all_prod = reduce(mul, [m["test"] for m in monkeys])

    for _ in range(0, rounds):
        for monke in monkeys:
            for item in monke["items"]:
                old = item
                new = eval(monke["op"])
                monke["inspects"] += 1
                if part == 1:
                    new = new // 3
                else:
                    new %= all_prod
                if new % monke["test"] == 0:
                    target = monke["true"]
                else:
                    target = monke["false"]
                monkeys[target]["items"].append(new)

            monke["items"] = []


    inspects = [m["inspects"] for m in monkeys]
    inspects.sort()
    print(inspects[-1] * inspects[-2])

run_part(1, 20, get_monkeys())
run_part(2, 10000, get_monkeys())