from copy import deepcopy from collections import defaultdict from output import ints def solve(data): M = [] for md in data.split("\n\n"): m = {} starting_items, operation, divisor, if_true, if_false = md.splitlines()[1:] m["items"] = ints(starting_items) m["if_false"] = ints(if_false)[0] m["if_true"] = ints(if_true)[0] m["divisor"] = ints(divisor)[0] m["operation_values"] = operation.split()[-3:] M.append(m) p12 = [] # Part 2 resolver. # # Not sure what to call this, so I go for Greatest Common # Divisor. Had to look for hints at subreddit to find it out. # It basically fasten up the computation speed by keeping # the numbers low. # # Apparently, this is common Modular arithmetic: # https://en.wikipedia.org/wiki/Modular_arithmetic gcd = 1 for d in [m["divisor"] for m in M]: gcd *= d for rounds, wld in [(20, True), (10_000, False)]: B = defaultdict(int) MM = deepcopy(M) for _ in range(rounds): for i, m in enumerate(MM): while m["items"]: wl = m["items"].pop(0) B[i] += 1 x, y, z = m["operation_values"] x = int(wl) if x == "old" else int(x) z = int(wl) if z == "old" else int(z) match y: case "+": wl = x + z case "*": wl = x * z if wld: wl = wl // 3 else: wl = wl % gcd if wl % m["divisor"] == 0: MM[m["if_true"]]["items"].append(wl) else: MM[m["if_false"]]["items"].append(wl) a, b, *_ = sorted(B.values(), reverse=True) p12.append(a * b) p1, p2 = p12 return p1, p2 def _state(M): return tuple([(tuple(m["items"])) for m in M]) if __name__ == "__main__": with open("./input/11.txt", "r") as f: inp = f.read().strip() p1, p2 = solve(inp) print(p1) print(p2) assert p1 == 50616 assert p2 == 11309046332