aoc2019/day14.py
Stefan Harmuth fac9376175 day14
2021-12-03 08:37:07 +01:00

59 lines
1.8 KiB
Python

from aoc import AOCDay
from math import ceil
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