59 lines
1.8 KiB
Python
59 lines
1.8 KiB
Python
from math import ceil
|
|
from tools.aoc import AOCDay
|
|
from typing import Any
|
|
|
|
|
|
class Day(AOCDay):
|
|
test_solutions_p1 = [165, 13312, 180697, 2210736]
|
|
test_solutions_p2 = [82892753, 5586022, 460664]
|
|
conversions = {}
|
|
rest = {}
|
|
|
|
def buildConversionDict(self):
|
|
self.rest = {}
|
|
conv_input = self.getInputAsArraySplit(" => ")
|
|
|
|
for need_str, give_str in conv_input:
|
|
tar_amt, tar = give_str.split()
|
|
self.conversions[tar] = {'amount': int(tar_amt), 'need': {}}
|
|
|
|
for r in need_str.split(", "):
|
|
a, n = r.split()
|
|
self.conversions[tar]['need'][n] = int(a)
|
|
|
|
def getOreNeed(self, what: str, amount: int) -> int:
|
|
amount -= self.rest.get(what, 0)
|
|
if amount < 0:
|
|
self.rest[what] = abs(amount)
|
|
return 0
|
|
|
|
if what == 'ORE':
|
|
return amount
|
|
|
|
ore_need = 0
|
|
count = ceil(amount / self.conversions[what]['amount'])
|
|
for need, need_amt in self.conversions[what]['need'].items():
|
|
ore_need += self.getOreNeed(need, need_amt * count)
|
|
|
|
self.rest[what] = self.conversions[what]['amount'] * count - amount
|
|
|
|
return ore_need
|
|
|
|
def part1(self) -> Any:
|
|
self.buildConversionDict()
|
|
return self.getOreNeed('FUEL', 1)
|
|
|
|
def part2(self) -> Any:
|
|
self.buildConversionDict()
|
|
got_ore = 1_000_000_000_000
|
|
min_fuel = got_ore // self.getOreNeed('FUEL', 1)
|
|
factor = 100_000
|
|
while factor >= 1:
|
|
ore_need = self.getOreNeed('FUEL', min_fuel + factor)
|
|
if ore_need > got_ore:
|
|
factor //= 10
|
|
else:
|
|
min_fuel += factor
|
|
|
|
return min_fuel if self.getOreNeed('FUEL', min_fuel) < got_ore else min_fuel - 1
|