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())