Day 19
This commit is contained in:
210
day19/common/factory.go
Normal file
210
day19/common/factory.go
Normal file
@@ -0,0 +1,210 @@
|
||||
package common
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
|
||||
type Material byte
|
||||
|
||||
const (
|
||||
Ore Material = iota
|
||||
Clay
|
||||
Obsidian
|
||||
Geode
|
||||
)
|
||||
|
||||
|
||||
type Robot byte
|
||||
|
||||
const (
|
||||
OreMiner Robot = iota
|
||||
ClayMiner
|
||||
ObsidianMiner
|
||||
GeodeMiner
|
||||
)
|
||||
|
||||
|
||||
type Factory struct {
|
||||
id int
|
||||
materials map[Material]int
|
||||
robots map[Robot]int
|
||||
costs map[Robot]map[Material]int
|
||||
minutesLeft int
|
||||
builtRobots []Robot
|
||||
maxProductionRequired map[Material]int
|
||||
}
|
||||
|
||||
func (factory *Factory) clone() *Factory {
|
||||
newFactory := Factory{factory.id, make(map[Material]int), map[Robot]int{}, factory.costs, factory.minutesLeft, []Robot{}, factory.maxProductionRequired}
|
||||
for m, v := range factory.materials {
|
||||
newFactory.materials[m] = v
|
||||
}
|
||||
for r, v := range factory.robots {
|
||||
newFactory.robots[r] = v
|
||||
}
|
||||
for i := range factory.builtRobots {
|
||||
newFactory.builtRobots = append(newFactory.builtRobots, factory.builtRobots[i])
|
||||
}
|
||||
return &newFactory
|
||||
}
|
||||
|
||||
func (factory *Factory) GenerateResources() {
|
||||
for r, v := range factory.robots {
|
||||
switch r {
|
||||
case OreMiner:
|
||||
factory.materials[Ore] += v
|
||||
case ClayMiner:
|
||||
factory.materials[Clay] += v
|
||||
case ObsidianMiner:
|
||||
factory.materials[Obsidian] += v
|
||||
case GeodeMiner:
|
||||
factory.materials[Geode] += v
|
||||
}
|
||||
}
|
||||
for i := range factory.builtRobots {
|
||||
factory.robots[factory.builtRobots[i]]++
|
||||
}
|
||||
factory.builtRobots = []Robot{}
|
||||
factory.minutesLeft--
|
||||
}
|
||||
|
||||
func (factory *Factory) StartOptimizedProduction() {
|
||||
factory.GenerateResources()
|
||||
|
||||
newFactories := []*Factory{factory.clone(), factory.clone(), factory.clone(), factory.clone()}
|
||||
for i := range newFactories {
|
||||
if i == 0 {
|
||||
for (newFactories[i].materials[Ore] < newFactories[i].costs[GeodeMiner][Ore] ||
|
||||
newFactories[i].materials[Obsidian] < newFactories[i].costs[GeodeMiner][Obsidian]) &&
|
||||
newFactories[i].minutesLeft > 0 {
|
||||
newFactories[i].GenerateResources()
|
||||
}
|
||||
if newFactories[i].minutesLeft > 0 {
|
||||
newFactories[i].builtRobots = []Robot{GeodeMiner}
|
||||
newFactories[i].materials[Ore] -= newFactories[i].costs[GeodeMiner][Ore]
|
||||
newFactories[i].materials[Obsidian] -= newFactories[i].costs[GeodeMiner][Obsidian]
|
||||
newFactories[i].StartOptimizedProduction()
|
||||
}
|
||||
} else if i == 1 && newFactories[i].robots[ObsidianMiner] < newFactories[i].maxProductionRequired[Obsidian] {
|
||||
for (newFactories[i].materials[Ore] < newFactories[i].costs[ObsidianMiner][Ore] ||
|
||||
newFactories[i].materials[Clay] < newFactories[i].costs[ObsidianMiner][Clay]) &&
|
||||
newFactories[i].minutesLeft > 0 {
|
||||
newFactories[i].GenerateResources()
|
||||
}
|
||||
if newFactories[i].minutesLeft > 0 {
|
||||
newFactories[i].builtRobots = []Robot{ObsidianMiner}
|
||||
newFactories[i].materials[Ore] -= newFactories[i].costs[ObsidianMiner][Ore]
|
||||
newFactories[i].materials[Clay] -= newFactories[i].costs[ObsidianMiner][Clay]
|
||||
newFactories[i].StartOptimizedProduction()
|
||||
}
|
||||
} else if i == 2 && newFactories[i].robots[ClayMiner] < newFactories[i].maxProductionRequired[Clay] {
|
||||
for newFactories[i].materials[Ore] < newFactories[i].costs[ClayMiner][Ore] &&
|
||||
newFactories[i].minutesLeft > 0 {
|
||||
newFactories[i].GenerateResources()
|
||||
}
|
||||
if newFactories[i].minutesLeft > 0 {
|
||||
newFactories[i].builtRobots = []Robot{ClayMiner}
|
||||
newFactories[i].materials[Ore] -= newFactories[i].costs[ClayMiner][Ore]
|
||||
newFactories[i].StartOptimizedProduction()
|
||||
}
|
||||
} else if i == 3 && newFactories[i].robots[OreMiner] < newFactories[i].maxProductionRequired[Ore] {
|
||||
for newFactories[i].materials[Ore] < newFactories[i].costs[OreMiner][Ore] &&
|
||||
newFactories[i].minutesLeft > 0 {
|
||||
newFactories[i].GenerateResources()
|
||||
}
|
||||
if newFactories[i].minutesLeft > 0 {
|
||||
newFactories[i].builtRobots = []Robot{OreMiner}
|
||||
newFactories[i].materials[Ore] -= newFactories[i].costs[OreMiner][Ore]
|
||||
newFactories[i].StartOptimizedProduction()
|
||||
}
|
||||
}
|
||||
|
||||
if newFactories[i].materials[Geode] > factory.materials[Geode] {
|
||||
factory.materials = newFactories[i].materials
|
||||
factory.robots = newFactories[i].robots
|
||||
factory.minutesLeft = newFactories[i].minutesLeft
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (factory *Factory) GetQualityLevel() int {
|
||||
return factory.id * factory.materials[Geode]
|
||||
}
|
||||
|
||||
func (factory *Factory) GetNumberOfGeodes() int {
|
||||
return factory.materials[Geode]
|
||||
}
|
||||
|
||||
|
||||
func Parse(scanner bufio.Scanner, limit int, minutesLeft int) []Factory {
|
||||
factories := []Factory{}
|
||||
|
||||
i := 0
|
||||
for scanner.Scan() {
|
||||
if limit >= 0 && i >= limit {
|
||||
break
|
||||
}
|
||||
|
||||
line := scanner.Text()
|
||||
splittedLine := strings.Split(line, ".")
|
||||
factory := Factory{}
|
||||
|
||||
splittedLine2 := strings.Split(splittedLine[0], " ")
|
||||
id, _ := strconv.Atoi(splittedLine2[1][:len(splittedLine2[1])-1])
|
||||
|
||||
factory.id = id
|
||||
factory.materials = make(map[Material]int)
|
||||
factory.materials[Ore] = 0
|
||||
factory.materials[Clay] = 0
|
||||
factory.materials[Obsidian] = 0
|
||||
factory.materials[Geode] = 0
|
||||
factory.robots = make(map[Robot]int)
|
||||
factory.robots[OreMiner] = 1
|
||||
factory.robots[ClayMiner] = 0
|
||||
factory.robots[ObsidianMiner] = 0
|
||||
factory.robots[GeodeMiner] = 0
|
||||
factory.minutesLeft = minutesLeft
|
||||
factory.maxProductionRequired = make(map[Material]int)
|
||||
|
||||
factory.costs = make(map[Robot]map[Material]int)
|
||||
oreCost, _ := strconv.Atoi(splittedLine2[6])
|
||||
factory.costs[OreMiner] = make(map[Material]int)
|
||||
factory.costs[OreMiner][Ore] = oreCost
|
||||
factory.maxProductionRequired[Ore] = oreCost
|
||||
splittedLine2 = strings.Split(splittedLine[1], " ")
|
||||
oreCost, _ = strconv.Atoi(splittedLine2[5])
|
||||
factory.costs[ClayMiner] = make(map[Material]int)
|
||||
factory.costs[ClayMiner][Ore] = oreCost
|
||||
if oreCost > factory.maxProductionRequired[Ore] {
|
||||
factory.maxProductionRequired[Ore] = oreCost
|
||||
}
|
||||
splittedLine2 = strings.Split(splittedLine[2], " ")
|
||||
oreCost, _ = strconv.Atoi(splittedLine2[5])
|
||||
clayCost, _ := strconv.Atoi(splittedLine2[8])
|
||||
factory.costs[ObsidianMiner] = make(map[Material]int)
|
||||
factory.costs[ObsidianMiner][Ore] = oreCost
|
||||
factory.costs[ObsidianMiner][Clay] = clayCost
|
||||
if oreCost > factory.maxProductionRequired[Ore] {
|
||||
factory.maxProductionRequired[Ore] = oreCost
|
||||
}
|
||||
factory.maxProductionRequired[Clay] = clayCost
|
||||
splittedLine2 = strings.Split(splittedLine[3], " ")
|
||||
oreCost, _ = strconv.Atoi(splittedLine2[5])
|
||||
obsidianCost, _ := strconv.Atoi(splittedLine2[8])
|
||||
factory.costs[GeodeMiner] = make(map[Material]int)
|
||||
factory.costs[GeodeMiner][Ore] = oreCost
|
||||
factory.costs[GeodeMiner][Obsidian] = obsidianCost
|
||||
if oreCost > factory.maxProductionRequired[Ore] {
|
||||
factory.maxProductionRequired[Ore] = oreCost
|
||||
}
|
||||
factory.maxProductionRequired[Obsidian] = obsidianCost
|
||||
|
||||
factories = append(factories, factory)
|
||||
i++
|
||||
}
|
||||
|
||||
return factories
|
||||
}
|
||||
Reference in New Issue
Block a user