123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293 |
- package main
-
- import (
- "github.com/csmith/aoc-2019/common"
- "math"
- "strings"
- )
-
- type chemical string
- type recipeBook map[chemical]*recipe
-
- type amount struct {
- chemical chemical
- quantity int
- }
-
- type recipe struct {
- produces *amount
- requires []*amount
- }
-
- func parseAmount(text string) *amount {
- parts := strings.Split(text, " ")
- return &amount{
- quantity: common.MustAtoi(parts[0]),
- chemical: chemical(parts[1]),
- }
- }
-
- func parseInput(file string) recipeBook {
- recipes := make(map[chemical]*recipe)
- for _, line := range common.ReadFileAsStrings(file) {
- parts := strings.Split(line, " => ")
- ingredients := strings.Split(parts[0], ", ")
- r := &recipe{
- produces: parseAmount(parts[1]),
- requires: make([]*amount, 0, len(ingredients)),
- }
- for _, in := range ingredients {
- r.requires = append(r.requires, parseAmount(in))
- }
- recipes[r.produces.chemical] = r
- }
- return recipes
- }
-
- func (rb recipeBook) produce(target chemical, quantity int, used map[chemical]int, spare map[chemical]int) {
- recipe := rb[target]
- needed := quantity
-
- if recipe == nil {
- used[target] += needed
- return
- }
-
- free := spare[target]
- if free >= needed {
- used[target] += needed
- spare[target] -= needed
- return
- } else {
- used[target] += free
- spare[target] = 0
- needed -= free
- }
-
- runs := int(math.Ceil(float64(needed) / float64(recipe.produces.quantity)))
- for _, i := range recipe.requires {
- rb.produce(i.chemical, i.quantity*runs, used, spare)
- }
-
- used[target] += needed
- spare[target] += (recipe.produces.quantity * runs) - needed
- }
-
- func main() {
- recipes := parseInput("14/input.txt")
- used := make(map[chemical]int, len(recipes))
- spare := make(map[chemical]int, len(recipes))
-
- recipes.produce("FUEL", 1, used, spare)
-
- orePerFuel := used["ORE"]
- println(used["ORE"])
-
- last := 0
- for used["ORE"] < 1000000000000 {
- last = used["FUEL"]
- recipes.produce("FUEL", common.Max(1, (1000000000000-used["ORE"])/orePerFuel), used, spare)
- }
-
- println(last)
- }
|