2019: d14: ex1: add solution

This commit is contained in:
Bruno BELANYI 2019-12-14 17:35:44 +01:00
parent 030f45af6c
commit 213575d822

89
2019/d14/ex1/ex1.py Executable file
View file

@ -0,0 +1,89 @@
#!/usr/bin/env python
import sys
from dataclasses import dataclass
from math import ceil
from typing import Dict, List
@dataclass
class Ingredient:
name: str
quantity: int
@dataclass
class ReactionEquation:
quantity: int
inputs: List[Ingredient]
Reactions = Dict[str, ReactionEquation]
def solve_for(n: int, reactions: Reactions) -> int:
ore_needed = 0
wanted = [("FUEL", n)]
excess: Dict[str, int] = {}
def provide_ingredient(name: str, wanted_quantity: int) -> None:
nonlocal ore_needed
nonlocal excess
nonlocal wanted
if name == "ORE":
ore_needed += wanted_quantity # There's no recipy for this one
return
if name in excess:
# Take from excess
if excess[name] > wanted_quantity:
excess[name] -= wanted_quantity
return # Nothing left to do
wanted_quantity -= excess[name]
del excess[name] # Took everything
if wanted_quantity == 0: # In case we provided just enough by excess
return
equation = reactions[name]
reaction_num = ceil(wanted_quantity / equation.quantity)
for ingredient in equation.inputs:
needed_quantity = ingredient.quantity * reaction_num
provide_ingredient(ingredient.name, needed_quantity)
produced_quantity = equation.quantity * reaction_num
excess_quantity = produced_quantity - wanted_quantity
if excess_quantity > 0:
if name in excess:
excess[name] += excess_quantity
else:
excess[name] = excess_quantity
while len(wanted) != 0:
provide_ingredient(*(wanted.pop()))
return ore_needed
def main() -> None:
reactions: Reactions = {}
def parse_react(l: str) -> None:
def parse_ingredient(i: str) -> Ingredient:
quantity, name = i.strip().split(" ")
return Ingredient(name, int(quantity))
input_list, output_str = l.split("=>")
inputs = [i for i in map(parse_ingredient, input_list.split(", "))]
output = parse_ingredient(output_str)
reactions[output.name] = ReactionEquation(output.quantity, inputs)
for line in sys.stdin.readlines():
parse_react(line)
print(solve_for(1, reactions))
if __name__ == "__main__":
main()