75 lines
2.2 KiB
Python
75 lines
2.2 KiB
Python
|
|
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
|