211 lines
6.8 KiB
Go
211 lines
6.8 KiB
Go
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
|
|
}
|