Day 14 complete
This commit is contained in:
144
days/14.go
144
days/14.go
@ -2,6 +2,7 @@ package days
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"math"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
@ -21,7 +22,7 @@ type Day14 struct {
|
|||||||
func (d *Day14) Parse() {
|
func (d *Day14) Parse() {
|
||||||
d.leftovers = make(map[string]int)
|
d.leftovers = make(map[string]int)
|
||||||
|
|
||||||
lines := u.GetStringLines("14s2")
|
lines := u.GetStringLines("14p")
|
||||||
d.reactions = make([]reaction, len(lines))
|
d.reactions = make([]reaction, len(lines))
|
||||||
for i, line := range lines {
|
for i, line := range lines {
|
||||||
sides := strings.Split(line, " => ")
|
sides := strings.Split(line, " => ")
|
||||||
@ -53,97 +54,74 @@ func (d Day14) Num() int {
|
|||||||
return 14
|
return 14
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d Day14) getOreRequiredFor(chem string, amt int) (int, int) {
|
func (d *Day14) oreRequiredStock(qty int64) int64 {
|
||||||
requiredOre := 0
|
oreRequired := int64(0)
|
||||||
for _, reaction := range d.reactions {
|
needs := map[string]int64{
|
||||||
if reaction.output.First == chem {
|
"FUEL": qty,
|
||||||
// if oreAmt, exists := reaction.inputs["ORE"]; exists && len(reaction.inputs) == 1 {
|
}
|
||||||
// if d.leftovers[chem] >= amt {
|
excess := make(map[string]int64)
|
||||||
// d.leftovers[chem] -= amt
|
|
||||||
// return 0, amt
|
|
||||||
// }
|
|
||||||
|
|
||||||
// produced := reaction.output.Second
|
getFromExcess := func(qty int64, chemical string) int64 {
|
||||||
// for produced < amt {
|
inStock := excess[chemical]
|
||||||
// requiredOre += oreAmt
|
qty -= inStock
|
||||||
// produced += reaction.output.Second
|
excess[chemical] = int64(math.Min(math.Abs(float64(qty)), 0))
|
||||||
// }
|
return inStock - excess[chemical]
|
||||||
// requiredOre += oreAmt
|
}
|
||||||
// if produced > amt {
|
|
||||||
// d.leftovers[chem] += produced - amt
|
for len(needs) > 0 {
|
||||||
// }
|
keys := u.MapKeys(needs)
|
||||||
// return requiredOre, produced
|
chemical := keys[len(keys)-1]
|
||||||
// } else {
|
qtyRequired := needs[chemical]
|
||||||
for inChem, inAmt := range reaction.inputs {
|
delete(needs, chemical)
|
||||||
produced := 0
|
|
||||||
if d.leftovers[inChem] >= inAmt {
|
fromExcess := getFromExcess(qtyRequired, chemical)
|
||||||
d.leftovers[inChem] -= inAmt
|
qtyRequired -= fromExcess
|
||||||
produced = inAmt
|
|
||||||
} else {
|
reaction := d.getReactionProducing(chemical)
|
||||||
for produced < inAmt {
|
qtyProduced := int64(reaction.output.Second)
|
||||||
madeOre, madeChem := d.getOreRequiredFor(inChem, inAmt)
|
ingredients := reaction.inputs
|
||||||
produced += madeChem
|
|
||||||
requiredOre += madeOre
|
n := int64(math.Ceil(float64(qtyRequired) / float64(qtyProduced)))
|
||||||
}
|
|
||||||
if produced > inAmt {
|
excess[chemical] = (qtyProduced * n) - qtyRequired
|
||||||
d.leftovers[inChem] += produced - inAmt
|
for ingredient, qtyIngredient := range ingredients {
|
||||||
}
|
if ingredient == "ORE" {
|
||||||
}
|
oreRequired += int64(int64(qtyIngredient) * n)
|
||||||
|
} else {
|
||||||
|
needs[ingredient] += int64(qtyIngredient) * n
|
||||||
}
|
}
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return requiredOre, 0
|
return oreRequired
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Day14) Part1() string {
|
func (d *Day14) Part1() string {
|
||||||
fuelReaction := d.getReactionProducing("FUEL")
|
neededOre := d.oreRequiredStock(1)
|
||||||
if fuelReaction == nil {
|
return fmt.Sprintf("%s%d%s", u.TextBold, neededOre, u.TextReset)
|
||||||
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 {
|
func (d *Day14) Part2() string {
|
||||||
return ""
|
oreAvailable := int64(1000000000000)
|
||||||
|
estimate := oreAvailable / d.oreRequiredStock(1)
|
||||||
|
|
||||||
|
high := estimate * 2
|
||||||
|
low := estimate
|
||||||
|
|
||||||
|
lastSuccess := low
|
||||||
|
lastFailure := high
|
||||||
|
fuelProduced := low
|
||||||
|
|
||||||
|
for math.Abs(float64(lastFailure)-float64(lastSuccess)) > 1 {
|
||||||
|
oreConsumed := d.oreRequiredStock(fuelProduced)
|
||||||
|
if oreConsumed < oreAvailable {
|
||||||
|
lastSuccess = fuelProduced
|
||||||
|
fuelProduced += (lastFailure - lastSuccess) / 2
|
||||||
|
} else {
|
||||||
|
lastFailure = fuelProduced
|
||||||
|
fuelProduced -= (lastFailure - lastSuccess) / 2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return fmt.Sprintf("%s%d%s", u.TextBold, lastSuccess, u.TextReset)
|
||||||
}
|
}
|
||||||
|
17
utilities/map.go
Normal file
17
utilities/map.go
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
package utilities
|
||||||
|
|
||||||
|
func MapKeys[T comparable, U any](m map[T]U) []T {
|
||||||
|
r := make([]T, 0, len(m))
|
||||||
|
for k := range m {
|
||||||
|
r = append(r, k)
|
||||||
|
}
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
|
||||||
|
func MapValues[T comparable, U any](m map[T]U) []U {
|
||||||
|
r := make([]U, 0, len(m))
|
||||||
|
for _, v := range m {
|
||||||
|
r = append(r, v)
|
||||||
|
}
|
||||||
|
return r
|
||||||
|
}
|
Reference in New Issue
Block a user