advent-of-code/2022-python/output/day_11.py

75 lines
2.2 KiB
Python
Raw Normal View History

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