150 lines
3.3 KiB
Go
150 lines
3.3 KiB
Go
package days
|
|
|
|
import (
|
|
"fmt"
|
|
"strconv"
|
|
"strings"
|
|
|
|
u "parnic.com/aoc2019/utilities"
|
|
)
|
|
|
|
type reaction struct {
|
|
inputs map[string]int
|
|
output u.Pair[string, int]
|
|
}
|
|
|
|
type Day14 struct {
|
|
reactions []reaction
|
|
leftovers map[string]int
|
|
}
|
|
|
|
func (d *Day14) Parse() {
|
|
d.leftovers = make(map[string]int)
|
|
|
|
lines := u.GetStringLines("14s2")
|
|
d.reactions = make([]reaction, len(lines))
|
|
for i, line := range lines {
|
|
sides := strings.Split(line, " => ")
|
|
inputs := strings.Split(sides[0], ", ")
|
|
output := sides[1]
|
|
|
|
outPair := strings.Split(output, " ")
|
|
outAmt, _ := strconv.Atoi(outPair[0])
|
|
d.reactions[i].output = u.Pair[string, int]{First: outPair[1], Second: outAmt}
|
|
d.reactions[i].inputs = make(map[string]int)
|
|
for _, input := range inputs {
|
|
pair := strings.Split(input, " ")
|
|
d.reactions[i].inputs[pair[1]], _ = strconv.Atoi(pair[0])
|
|
}
|
|
}
|
|
}
|
|
|
|
func (d Day14) getReactionProducing(chem string) *reaction {
|
|
for _, reaction := range d.reactions {
|
|
if reaction.output.First == chem {
|
|
return &reaction
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (d Day14) Num() int {
|
|
return 14
|
|
}
|
|
|
|
func (d Day14) getOreRequiredFor(chem string, amt int) (int, int) {
|
|
requiredOre := 0
|
|
for _, reaction := range d.reactions {
|
|
if reaction.output.First == chem {
|
|
// if oreAmt, exists := reaction.inputs["ORE"]; exists && len(reaction.inputs) == 1 {
|
|
// if d.leftovers[chem] >= amt {
|
|
// d.leftovers[chem] -= amt
|
|
// return 0, amt
|
|
// }
|
|
|
|
// produced := reaction.output.Second
|
|
// for produced < amt {
|
|
// requiredOre += oreAmt
|
|
// produced += reaction.output.Second
|
|
// }
|
|
// requiredOre += oreAmt
|
|
// if produced > amt {
|
|
// d.leftovers[chem] += produced - amt
|
|
// }
|
|
// return requiredOre, produced
|
|
// } else {
|
|
for inChem, inAmt := range reaction.inputs {
|
|
produced := 0
|
|
if d.leftovers[inChem] >= inAmt {
|
|
d.leftovers[inChem] -= inAmt
|
|
produced = inAmt
|
|
} else {
|
|
for produced < inAmt {
|
|
madeOre, madeChem := d.getOreRequiredFor(inChem, inAmt)
|
|
produced += madeChem
|
|
requiredOre += madeOre
|
|
}
|
|
if produced > inAmt {
|
|
d.leftovers[inChem] += produced - inAmt
|
|
}
|
|
}
|
|
}
|
|
// }
|
|
}
|
|
}
|
|
|
|
return requiredOre, 0
|
|
}
|
|
|
|
func (d *Day14) Part1() string {
|
|
fuelReaction := d.getReactionProducing("FUEL")
|
|
if fuelReaction == nil {
|
|
panic("")
|
|
}
|
|
|
|
neededMaterial := map[string]int{
|
|
"FUEL": 1,
|
|
}
|
|
var recurse func(neededMaterial map[string]int) map[string]int
|
|
recurse = func(neededMaterial map[string]int) map[string]int {
|
|
neededInputs := make(map[string]int)
|
|
for chem, amt := range neededMaterial {
|
|
reaction := d.getReactionProducing(chem)
|
|
if reaction == nil {
|
|
continue
|
|
}
|
|
produced := reaction.output.Second
|
|
reactionsNeeded := 1
|
|
for produced < amt {
|
|
produced += reaction.output.Second
|
|
reactionsNeeded++
|
|
}
|
|
for inChem, inAmt := range reaction.inputs {
|
|
neededInputs[inChem] += inAmt * reactionsNeeded
|
|
}
|
|
}
|
|
if len(neededInputs) > 0 {
|
|
recursed := recurse(neededInputs)
|
|
for k, v := range recursed {
|
|
neededInputs[k] += v
|
|
}
|
|
}
|
|
return neededInputs
|
|
}
|
|
recursed := recurse(neededMaterial)
|
|
fmt.Println(len(recursed))
|
|
|
|
ore := 0
|
|
for inChem, inAmt := range fuelReaction.inputs {
|
|
requiredOre, _ := d.getOreRequiredFor(inChem, inAmt)
|
|
ore += requiredOre
|
|
}
|
|
|
|
return fmt.Sprintf("%s%d%s", u.TextBold, ore, u.TextReset)
|
|
}
|
|
|
|
func (d *Day14) Part2() string {
|
|
return ""
|
|
}
|