mirror of
https://github.com/bertptrs/adventofcode.git
synced 2025-12-25 21:00:31 +01:00
Implement 2019 day 14
This commit is contained in:
71
2019/aoc2019/day14.py
Normal file
71
2019/aoc2019/day14.py
Normal 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
|
||||
Reference in New Issue
Block a user