Implement 2019 day 14

This commit is contained in:
2021-01-30 10:08:16 +01:00
parent c3671ec177
commit 43c063cef9
2 changed files with 151 additions and 0 deletions

71
2019/aoc2019/day14.py Normal file
View File

@@ -0,0 +1,71 @@
import math
from collections import defaultdict
from typing import TextIO, Tuple
from networkx import DiGraph, topological_sort
def read_pair(item: str) -> Tuple[str, int]:
amount, element = item.split(' ')
return element, int(amount)
def read_recipes(data: TextIO) -> DiGraph:
graph = DiGraph()
for line in data:
requisites, production = line.strip().split(' => ')
produced, produced_amount = read_pair(production)
graph.add_node(produced, weight=produced_amount)
for requisite in requisites.split(', '):
required, required_amount = read_pair(requisite)
graph.add_edge(produced, required, weight=required_amount)
return graph
def ore_required(graph: DiGraph, fuel_required: int) -> int:
requirements = defaultdict(int)
requirements['FUEL'] = fuel_required
for element in topological_sort(graph):
if element not in requirements:
continue
if element == 'ORE':
break
element_produced = graph.nodes[element]['weight']
productions_required = math.ceil(requirements[element] / element_produced)
for _, elem_required, amount_required in graph.edges(element, data='weight'):
requirements[elem_required] += amount_required * productions_required
return requirements['ORE']
def part1(data: TextIO) -> int:
return ore_required(read_recipes(data), 1)
def part2(data: TextIO) -> int:
ore_available = 1000000000000
graph = read_recipes(data)
min_possible = 1 # lower bound of ORE / ore_required(graph, 1) exists but is slower
max_possible = ore_available
while min_possible != max_possible:
check = min_possible + (max_possible - min_possible + 1) // 2
required = ore_required(graph, check)
if required <= ore_available:
min_possible = check
else:
max_possible = check - 1
return min_possible