adventofcode/2019/day14/main.go

154 lines
3.2 KiB
Go
Raw Normal View History

2019-12-15 14:57:44 +00:00
package main
import (
"fmt"
"strings"
helpers "git.bullercodeworks.com/brian/adventofcode/helpers"
)
func main() {
inp := helpers.StdinToStringSlice()
part1(inp)
part2(inp)
}
var allReactions map[string]*Reaction
func part1(inp []string) {
allReactions = make(map[string]*Reaction)
for _, v := range inp {
r := NewReaction(v)
allReactions[r.out] = r
}
factory := NewFactory(allReactions)
factory.setInfinite("ORE", true)
factory.generate("FUEL")
fmt.Println("# Part 1")
fmt.Println("Ore Used:", factory.generated["ORE"])
}
func part2(inp []string) {
allReactions = make(map[string]*Reaction)
for _, v := range inp {
r := NewReaction(v)
allReactions[r.out] = r
}
factory := NewFactory(allReactions)
oreStart := 1000000000000
factory.setStock("ORE", oreStart)
fmt.Println("\n# Part 2")
fmt.Println("Ore in stock", factory.stock["ORE"])
var out1 string
for factory.generate("FUEL") {
clearStr := strings.Repeat("", len(out1))
out1 = fmt.Sprintf("%s%3d%% (%d)", clearStr, ((factory.stock["ORE"] * 100) / oreStart), factory.generated["FUEL"])
fmt.Print(out1)
}
}
type Factory struct {
stock map[string]int
recipes map[string]*Reaction
generated map[string]int
used map[string]int
infinite map[string]bool
}
func NewFactory(recipes map[string]*Reaction) *Factory {
f := Factory{
stock: make(map[string]int),
recipes: recipes,
generated: make(map[string]int),
used: make(map[string]int),
infinite: make(map[string]bool),
}
return &f
}
func (f *Factory) setStock(chem string, amt int) {
f.stock[chem] = amt
}
func (f *Factory) setInfinite(chem string, is bool) {
f.infinite[chem] = is
}
func (f *Factory) count(chem string) int {
return f.stock[chem]
}
func (f *Factory) use(chem string, amt int) bool {
if f.count(chem) < amt {
return false
}
f.stock[chem] = f.stock[chem] - amt
f.used[chem] = f.used[chem] + amt
return true
}
func (f *Factory) generate(chem string) bool {
if f.infinite[chem] {
f.stock[chem] = f.stock[chem] + 1
f.generated[chem] = f.generated[chem] + 1
return true
}
react, ok := f.recipes[chem]
if !ok {
return false
}
for k, v := range react.in {
for f.count(k) < v {
f.generate(k)
}
f.use(k, v)
}
f.stock[chem] = f.stock[chem] + react.outQty
f.generated[chem] = f.generated[chem] + react.outQty
return true
}
type Reaction struct {
in map[string]int
out string
outQty int
ingredients []*Reaction
}
func NewReaction(inp string) *Reaction {
pts := strings.Split(inp, " => ")
if len(pts) != 2 {
panic("Invalid Reaction Input: " + inp)
}
ret := Reaction{
in: make(map[string]int),
}
inps := strings.Split(pts[0], ", ")
for k := range inps {
var qty int
var prod string
_, err := fmt.Sscanf(inps[k], "%d %s", &qty, &prod)
if err != nil {
panic("Invalid Reaction Input: " + inp)
}
ret.in[prod] = qty
}
_, err := fmt.Sscanf(pts[1], "%d %s", &ret.outQty, &ret.out)
if err != nil {
panic("Invalid Reaction Input: " + inp)
}
return &ret
}
func (r Reaction) String() string {
var ret string
for k, v := range r.in {
if len(ret) > 0 {
ret = ret + ","
}
ret = fmt.Sprintf("%s %d %s", ret, v, k)
}
return fmt.Sprintf("%s => %d %s", ret, r.outQty, r.out)
}