Add solution for day 14 part 1
parent
9bc4cfb8ec
commit
da0078e201
|
@ -0,0 +1,60 @@
|
|||
11 BNMWF, 1 MRVFT, 10 PBNSF => 7 XSFVQ
|
||||
149 ORE => 4 SMSB
|
||||
1 XHQDX, 1 SVSTJ, 2 LDHX => 7 JMWQG
|
||||
12 MJCLX => 9 PBNSF
|
||||
132 ORE => 7 XPTXL
|
||||
15 TZMWG, 1 LDHX, 1 PDVR => 7 LBQB
|
||||
1 HJTD, 8 VFXHC => 2 SVSTJ
|
||||
5 LBHQ, 6 MTQCB => 4 MHBZ
|
||||
1 PRXT, 1 FWZN => 2 PBMPL
|
||||
1 XPTXL => 1 HMRGM
|
||||
10 XHPHR => 6 NSVJL
|
||||
3 QZQLZ, 3 MTQCB => 4 TZMWG
|
||||
5 LBHQ, 2 VPSDV => 3 ZFCD
|
||||
13 WPFP => 6 ZXMGK
|
||||
10 MHJMX, 75 LDHX, 52 JMWQG, 4 QWRB, 1 SVNVJ, 17 BNMWF, 18 GHVN => 1 FUEL
|
||||
4 PFQRG, 14 XVNL => 5 PDCV
|
||||
11 JMWQG, 10 ZBNCP => 6 NTJZH
|
||||
14 PBMPL, 12 PRXT, 9 MJQS => 9 XVNL
|
||||
9 GDNG, 13 LBQB => 9 QWRB
|
||||
1 CXNM => 6 PFQRG
|
||||
9 NTJZH, 7 BNMWF, 11 JCHP, 1 MHBZ, 1 SVSTJ, 9 XRDN => 5 SVNVJ
|
||||
1 XHPHR, 1 GSMP => 4 THRVR
|
||||
26 FWZN => 4 WPFP
|
||||
35 VJTFJ, 2 XSFVQ, 6 HJVN, 1 NSVJL, 1 JCHP, 3 MJCLX, 1 QZNCK => 6 GHVN
|
||||
1 WPFP, 3 XHPHR => 2 HJVN
|
||||
5 SMSB => 7 HNCDS
|
||||
111 ORE => 4 GSMP
|
||||
6 LBHQ => 8 GDNG
|
||||
2 GDNG, 5 MHBZ => 1 RNMKC
|
||||
15 THRVR, 4 NWNSH, 1 NSVJL => 7 FDVH
|
||||
2 HMRGM => 9 FWZN
|
||||
6 MJQS, 5 JRZXM => 5 NWNSH
|
||||
14 ZXMGK, 1 JTXWX => 6 DLWT
|
||||
1 MJQS, 3 FWZN, 2 PRXT => 1 JTXWX
|
||||
1 GSMP, 4 CXNM => 3 JRZXM
|
||||
151 ORE => 9 ZNPRL
|
||||
2 NTJZH, 1 DLWT, 3 ZBNCP => 9 MRVFT
|
||||
14 SWZCB, 1 VPSDV => 7 XRDN
|
||||
14 LBHQ, 16 FDVH, 9 PFQRG => 4 PRXT
|
||||
22 CXNM => 9 HJTD
|
||||
1 VFXHC, 1 MTQCB => 6 QZQLZ
|
||||
6 SWZCB, 2 PDCV, 17 RNMKC => 9 LTHFW
|
||||
4 ZNPRL => 6 CXNM
|
||||
2 CXNM => 3 LBHQ
|
||||
8 MHBZ, 2 QZQLZ, 2 LBQB => 3 VJTFJ
|
||||
3 ZFCD => 1 XHQDX
|
||||
1 VJTFJ, 7 MHBZ => 8 ZBNCP
|
||||
5 CXNM => 2 VPSDV
|
||||
7 MJQS => 9 VFXHC
|
||||
2 LTHFW, 11 HJVN, 4 XRDN, 8 MRVFT, 3 NSVJL, 3 SVSTJ, 5 XSFVQ, 13 RNMKC => 8 MHJMX
|
||||
2 HMRGM => 3 XHPHR
|
||||
1 GDNG, 19 PDVR => 3 SWZCB
|
||||
18 HMRGM, 10 HNCDS => 2 MJQS
|
||||
6 HNCDS, 2 HMRGM, 1 LBHQ => 3 MTQCB
|
||||
16 VJTFJ, 1 WPFP, 6 JMWQG => 6 BNMWF
|
||||
3 TZMWG, 1 FWZN => 7 PDVR
|
||||
10 ZXMGK => 4 QZNCK
|
||||
32 LBQB, 1 ZBNCP => 1 JCHP
|
||||
27 PDVR, 7 QZQLZ, 7 PBMPL => 3 MJCLX
|
||||
5 MHBZ, 12 ZFCD => 4 LDHX
|
|
@ -0,0 +1,120 @@
|
|||
import sys
|
||||
import math
|
||||
from dataclasses import dataclass
|
||||
from typing import Dict, List, Tuple
|
||||
|
||||
|
||||
# Element is a node in a graph used to represent the dependencies amongst reactions (not the quantities themselves)
|
||||
class Element:
|
||||
FUEL_ELEMENT = 'FUEL'
|
||||
ORE_ELEMENT = 'ORE'
|
||||
|
||||
def __init__(self, name: str):
|
||||
self.name = name
|
||||
self.possible_inputs = set()
|
||||
self.possible_outputs = set()
|
||||
|
||||
def __repr__(self) -> str:
|
||||
return f'<Element: {self.name}>'
|
||||
|
||||
|
||||
@dataclass
|
||||
class Reaction:
|
||||
# We can have many inputs
|
||||
inputs: Dict[Element, int]
|
||||
# We only have one output
|
||||
output: Tuple[Element, int]
|
||||
|
||||
@classmethod
|
||||
def from_input_str(cls, s: str):
|
||||
REACTION_DELIM = ' => '
|
||||
INPUT_DELIM = ', '
|
||||
ELEMENT_DELIM = ' '
|
||||
raw_inputs, raw_output = s.split(REACTION_DELIM)
|
||||
split_output = raw_output.split(ELEMENT_DELIM)
|
||||
output = (Element(split_output[1]), int(split_output[0]))
|
||||
|
||||
inputs = {}
|
||||
for raw_input in raw_inputs.split(INPUT_DELIM):
|
||||
split_input = raw_input.split(ELEMENT_DELIM)
|
||||
inputs[Element(split_input[1])] = int(split_input[0])
|
||||
|
||||
return cls(inputs, output)
|
||||
|
||||
def __repr__(self) -> str:
|
||||
inputs = ', '.join(f'{count} {element.name}' for element, count in self.inputs.items())
|
||||
return inputs + f' => {self.output[1]} {self.output[0].name}'
|
||||
|
||||
|
||||
# Parses all of the output, returns a list of all of the reactions and the FUEL element
|
||||
def parse_reaction_list(input_lines: str) -> Tuple[List[Reaction], Element]:
|
||||
elements = {Element.ORE_ELEMENT: Element(Element.ORE_ELEMENT)}
|
||||
reactions = [Reaction.from_input_str(line) for line in input_lines]
|
||||
for reaction in reactions:
|
||||
output_element = reaction.output[0]
|
||||
elements[output_element.name] = output_element
|
||||
|
||||
# Once we add all reactions, add neighbors for the elements
|
||||
for reaction in reactions:
|
||||
output_element = elements[reaction.output[0].name]
|
||||
reaction_inputs = reaction.inputs.copy()
|
||||
for reaction_input_element, quantity in reaction_inputs.items():
|
||||
input_element = elements[reaction_input_element.name]
|
||||
# Noramlize the elemnts in the reaction list to all point to the same instance of that element.
|
||||
del reaction.inputs[reaction_input_element]
|
||||
reaction.inputs[input_element] = quantity
|
||||
output_element.possible_inputs.add(input_element)
|
||||
input_element.possible_outputs.add(output_element)
|
||||
|
||||
return reactions, elements[Element.FUEL_ELEMENT]
|
||||
|
||||
|
||||
def part1(reactions: List[Reaction], fuel_element: Element) -> int:
|
||||
surplus_elements = {}
|
||||
# Counts how many times a reaction with index i is run
|
||||
reaction_counts = {}
|
||||
# Maps a reaction's output to its reaction
|
||||
reaction_map = {reaction.output[0].name: (i, reaction) for i, reaction in enumerate(reactions)}
|
||||
|
||||
def generate_reaction_counts(element: Element, num_required: int):
|
||||
if element.name == Element.ORE_ELEMENT:
|
||||
return
|
||||
|
||||
num_surplus = surplus_elements.get(element.name, 0)
|
||||
i, reaction = reaction_map[element.name]
|
||||
num_missing = num_required - num_surplus
|
||||
# If we already have enough elements, we're done.
|
||||
if num_missing <= 0:
|
||||
# Store how many our new suplus is
|
||||
surplus_elements[element.name] = num_surplus - num_required
|
||||
return
|
||||
|
||||
reactions_required = int(math.ceil(num_missing / reaction.output[1]))
|
||||
surplus_elements[element.name] = (num_surplus - num_required) + reactions_required * reaction.output[1]
|
||||
reaction_count = reaction_counts.get(i, 0)
|
||||
reaction_counts[i] = reaction_count + reactions_required
|
||||
|
||||
for input_element, count in reaction.inputs.items():
|
||||
generate_reaction_counts(input_element, count * reactions_required)
|
||||
|
||||
# Run our recursive algorithm to calculate how many reactions are required
|
||||
generate_reaction_counts(fuel_element, 1)
|
||||
num_ore_required = 0
|
||||
for i, count in reaction_counts.items():
|
||||
for input_element, reaction_input_count in reactions[i].inputs.items():
|
||||
if input_element.name == Element.ORE_ELEMENT:
|
||||
num_ore_required += count * reaction_input_count
|
||||
|
||||
return num_ore_required
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
if len(sys.argv) != 2:
|
||||
print("Usage: ./main.py in_file")
|
||||
sys.exit(1)
|
||||
|
||||
with open(sys.argv[1]) as f:
|
||||
lines = f.read().rstrip('\n').split('\n')
|
||||
reactions, fuel_element = parse_reaction_list(lines)
|
||||
|
||||
print(part1(reactions, fuel_element))
|
|
@ -0,0 +1,6 @@
|
|||
10 ORE => 10 A
|
||||
1 ORE => 1 B
|
||||
7 A, 1 B => 1 C
|
||||
7 A, 1 C => 1 D
|
||||
7 A, 1 D => 1 E
|
||||
7 A, 1 E => 1 FUEL
|
|
@ -0,0 +1,9 @@
|
|||
157 ORE => 5 NZVS
|
||||
165 ORE => 6 DCFZ
|
||||
44 XJWVT, 5 KHKGT, 1 QDVJ, 29 NZVS, 9 GPVTF, 48 HKGWZ => 1 FUEL
|
||||
12 HKGWZ, 1 GPVTF, 8 PSHF => 9 QDVJ
|
||||
179 ORE => 7 PSHF
|
||||
177 ORE => 5 HKGWZ
|
||||
7 DCFZ, 7 PSHF => 2 XJWVT
|
||||
165 ORE => 2 GPVTF
|
||||
3 DCFZ, 7 NZVS, 5 HKGWZ, 10 PSHF => 8 KHKGT
|
|
@ -0,0 +1,12 @@
|
|||
2 VPVL, 7 FWMGM, 2 CXFTF, 11 MNCFX => 1 STKFG
|
||||
17 NVRVD, 3 JNWZP => 8 VPVL
|
||||
53 STKFG, 6 MNCFX, 46 VJHF, 81 HVMC, 68 CXFTF, 25 GNMV => 1 FUEL
|
||||
22 VJHF, 37 MNCFX => 5 FWMGM
|
||||
139 ORE => 4 NVRVD
|
||||
144 ORE => 7 JNWZP
|
||||
5 MNCFX, 7 RFSQX, 2 FWMGM, 2 VPVL, 19 CXFTF => 3 HVMC
|
||||
5 VJHF, 7 MNCFX, 9 VPVL, 37 CXFTF => 6 GNMV
|
||||
145 ORE => 6 MNCFX
|
||||
1 NVRVD => 8 CXFTF
|
||||
1 VJHF, 6 MNCFX => 4 RFSQX
|
||||
176 ORE => 6 VJHF
|
|
@ -0,0 +1,17 @@
|
|||
171 ORE => 8 CNZTR
|
||||
7 ZLQW, 3 BMBT, 9 XCVML, 26 XMNCP, 1 WPTQ, 2 MZWV, 1 RJRHP => 4 PLWSL
|
||||
114 ORE => 4 BHXH
|
||||
14 VRPVC => 6 BMBT
|
||||
6 BHXH, 18 KTJDG, 12 WPTQ, 7 PLWSL, 31 FHTLT, 37 ZDVW => 1 FUEL
|
||||
6 WPTQ, 2 BMBT, 8 ZLQW, 18 KTJDG, 1 XMNCP, 6 MZWV, 1 RJRHP => 6 FHTLT
|
||||
15 XDBXC, 2 LTCX, 1 VRPVC => 6 ZLQW
|
||||
13 WPTQ, 10 LTCX, 3 RJRHP, 14 XMNCP, 2 MZWV, 1 ZLQW => 1 ZDVW
|
||||
5 BMBT => 4 WPTQ
|
||||
189 ORE => 9 KTJDG
|
||||
1 MZWV, 17 XDBXC, 3 XCVML => 2 XMNCP
|
||||
12 VRPVC, 27 CNZTR => 2 XDBXC
|
||||
15 KTJDG, 12 BHXH => 5 XCVML
|
||||
3 BHXH, 2 VRPVC => 7 MZWV
|
||||
121 ORE => 7 VRPVC
|
||||
7 XCVML => 6 RJRHP
|
||||
5 BHXH, 4 VRPVC => 5 LTCX
|
Loading…
Reference in New Issue