67 lines
1.8 KiB
Python
67 lines
1.8 KiB
Python
import re
|
|
from lib import get_data, str_to_ints
|
|
from math import ceil
|
|
|
|
data = get_data(__file__)
|
|
|
|
p1 = 0
|
|
p2 = 1
|
|
|
|
for line in data.splitlines():
|
|
id = str_to_ints(line)[0]
|
|
bps = []
|
|
maxmin = [0, 0, 0]
|
|
for part in line.split(". "):
|
|
bp = []
|
|
for amount, mineral in re.findall(r"(\d+) (\w+)", part):
|
|
amount = int(amount)
|
|
mi = ["ore", "clay", "obsidian", "geode"].index(mineral)
|
|
bp.append((amount, mi))
|
|
maxmin[mi] = max(maxmin[mi], amount)
|
|
bps.append(bp)
|
|
|
|
def dfs(time, mins, bots, cache):
|
|
if time == 0:
|
|
return mins[3]
|
|
|
|
key = (time, *mins, *bots)
|
|
if key in cache:
|
|
return cache[key]
|
|
|
|
maxv = mins[3] + time * bots[3]
|
|
for bi, recipe in enumerate(bps):
|
|
if bi != 3 and bots[bi] >= maxmin[bi]:
|
|
continue
|
|
|
|
wait = 0
|
|
for ra, ri in recipe:
|
|
if bots[ri] == 0:
|
|
break
|
|
wait = max(ceil((ra - mins[ri]) / bots[ri]), wait)
|
|
else:
|
|
remtime = time - wait - 1
|
|
if remtime <= 0:
|
|
continue
|
|
|
|
bots_ = list(bots)
|
|
mins_ = [m + b * (wait + 1) for m, b in zip(mins, bots)]
|
|
for ra, ri in recipe:
|
|
mins_[ri] -= ra
|
|
bots_[bi] += 1
|
|
|
|
for i in range(3):
|
|
mins_[i] = min(mins_[i], maxmin[i] * remtime)
|
|
v = dfs(remtime, tuple(mins_), tuple(bots_), cache)
|
|
maxv = max(v, maxv)
|
|
|
|
key = (time, *mins, *bots)
|
|
cache[key] = maxv
|
|
return maxv
|
|
|
|
p1 += id * dfs(24, (0, 0, 0, 0), (1, 0, 0, 0), {})
|
|
if id < 4:
|
|
p2 *= dfs(32, (0, 0, 0, 0), (1, 0, 0, 0), {})
|
|
|
|
print(p1)
|
|
print(p2)
|