From 7ed45eb39a19fc3ddddd849afc42ae51fb07dc13 Mon Sep 17 00:00:00 2001 From: Karl Spickermann Date: Mon, 19 Dec 2022 23:39:38 +0100 Subject: [PATCH] Zwischenstand --- day19/day19.go | 191 ++++++++++++++++++++++++++++++++++++++++++++++++ day19/input | 30 ++++++++ day19/testinput | 2 + 3 files changed, 223 insertions(+) create mode 100644 day19/day19.go create mode 100644 day19/input create mode 100644 day19/testinput diff --git a/day19/day19.go b/day19/day19.go new file mode 100644 index 0000000..f5174cf --- /dev/null +++ b/day19/day19.go @@ -0,0 +1,191 @@ +package main + +import ( + "AOC2022/helper" + "fmt" + "strconv" + "strings" +) + +type State struct { + currentRessources [4]int + currentProduction [4]int + runtime int +} + +type Blueprint struct { + oreRoboterCost int + clayRoboterCost int + obsidianRobototerCost [2]int + geodeRoboterCost [2]int +} + +func main() { + //args := os.Args[1:] + lines := helper.ReadTextFile("day19/input") + highestGeode := make([]int, len(lines)) + for i, line := range lines { + blueprint := getBluePrint(line) + startStates := []State{State{[4]int{0, 0, 0, 0}, [4]int{1, 0, 0, 0}, 0}} + fastestTime := getFastestTimeToElementN(blueprint, []State{State{[4]int{0, 0, 0, 0}, [4]int{1, 0, 0, 0}, 0}}, 2) + startStates = getAllPossibleCombinationsWithFastestTime(blueprint, []State{State{[4]int{0, 0, 0, 0}, [4]int{1, 0, 0, 0}, 0}}, 2, fastestTime) + tmpStates := getAllPossibleCombinationsWithFastestTime(blueprint, []State{State{[4]int{0, 0, 0, 0}, [4]int{1, 0, 0, 0}, 0}}, 2, fastestTime) + fastestTime = getFastestTimeToElementN(blueprint, tmpStates, 3) + startStates = getAllPossibleCombinationsWithFastestTime(blueprint, startStates, 3, fastestTime) + highestGeode[i] = getHighestGeode(blueprint, startStates) + } + sum := 0 + for i, score := range highestGeode { + sum += (i + 1) * score + } + fmt.Println(sum) + +} + +func getHighestGeode(blueprint Blueprint, startStates []State) int { + activeStates := startStates + endStates := []State{} + for len(activeStates) > 0 { + stepHighestGeode(&activeStates, &endStates, &blueprint) + } + highestgeode := 0 + for _, state := range endStates { + if state.currentRessources[3] > highestgeode && state.runtime < 25 { + highestgeode = state.currentRessources[3] + } + } + return highestgeode +} + +func getFastestTimeToElementN(blueprint Blueprint, startStates []State, untilElementN int) int { + activeStates := startStates + fastestTimeToObsidianState := State{[4]int{0, 0, 0, 0}, [4]int{1, 0, 0, 0}, 26} + for len(activeStates) > 0 { + step(&activeStates, &fastestTimeToObsidianState, untilElementN, &blueprint) + } + return fastestTimeToObsidianState.runtime +} + +func getAllPossibleCombinationsWithFastestTime(blueprint Blueprint, startStates []State, untilElementN int, fastestTime int) []State { + activeStates := startStates + fastestTimeToObsidianState := map[[8]int]State{} + for len(activeStates) > 0 { + stepFindAllFastestTime(&activeStates, &fastestTimeToObsidianState, untilElementN, fastestTime, &blueprint) + } + returnStates := []State{} + for _, val := range fastestTimeToObsidianState { + returnStates = append(returnStates, val) + } + return returnStates +} + +func step(activeStates *[]State, fastestTImeToObsidian *State, untilElementN int, blueprint *Blueprint) { + activeStates, newTmpStates := generatePossibleTmpStates(activeStates, blueprint) + for _, tmpState := range newTmpStates { + if tmpState.currentProduction[untilElementN] > 0 && (*fastestTImeToObsidian).runtime > tmpState.runtime { + *fastestTImeToObsidian = tmpState + } + if tmpState.currentProduction[untilElementN] == 0 && tmpState.runtime < (*fastestTImeToObsidian).runtime { + *activeStates = append(*activeStates, tmpState) + } + } +} + +func stepHighestGeode(activeStates *[]State, endStates *[]State, blueprint *Blueprint) { + activeStates, newTmpStates := generatePossibleTmpStates(activeStates, blueprint) + for _, tmpState := range newTmpStates { + if tmpState.runtime < 24 { + *activeStates = append(*activeStates, tmpState) + } else { + *endStates = append(*endStates, tmpState) + } + } +} + +func stepFindAllFastestTime(activeStates *[]State, fastestTImeStates *map[[8]int]State, untilElementN int, fastestTime int, blueprint *Blueprint) { + activeStates, newTmpStates := generatePossibleTmpStates(activeStates, blueprint) + for _, tmpState := range newTmpStates { + if tmpState.currentProduction[untilElementN] > 0 && fastestTime >= tmpState.runtime { + identifier := [8]int{} + copy(identifier[:], append(tmpState.currentRessources[:], tmpState.currentProduction[:]...)[:8]) + (*fastestTImeStates)[identifier] = tmpState + } + if tmpState.currentProduction[untilElementN] == 0 && tmpState.runtime < fastestTime { + *activeStates = append(*activeStates, tmpState) + } + } +} + +func generatePossibleTmpStates(activeStates *[]State, blueprint *Blueprint) (*[]State, []State) { + activeState := (*activeStates)[len(*activeStates)-1] + *activeStates = (*activeStates)[:len(*activeStates)-1] + possibleProductions := activeState.getPossibleProductions(blueprint) + newTmpStates := []State{} + for i := -1; i < len(possibleProductions); i++ { + if i == -1 || possibleProductions[i] == 1 { + tmpState := activeState + tmpState.produceRessources() + tmpState.produceRoboter(blueprint, i) + tmpState.runtime++ + newTmpStates = append(newTmpStates, tmpState) + } + } + return activeStates, newTmpStates +} + +func (state *State) produceRoboter(blueprint *Blueprint, roboter int) { + switch roboter { + case 0: + state.currentProduction[0]++ + state.currentRessources[0] -= blueprint.oreRoboterCost + case 1: + state.currentProduction[1]++ + state.currentRessources[0] -= blueprint.clayRoboterCost + case 2: + state.currentProduction[2]++ + state.currentRessources[0] -= blueprint.obsidianRobototerCost[0] + state.currentRessources[1] -= blueprint.obsidianRobototerCost[1] + case 3: + state.currentProduction[3]++ + state.currentRessources[0] -= blueprint.geodeRoboterCost[0] + state.currentRessources[2] -= blueprint.geodeRoboterCost[1] + default: + + } +} + +func (state *State) produceRessources() { + for i := 0; i < 4; i++ { + state.currentRessources[i] += state.currentProduction[i] + } +} + +func (state State) getPossibleProductions(blueprint *Blueprint) [4]int { + possibleProductions := [4]int{0, 0, 0, 0} + if state.currentRessources[0] >= blueprint.oreRoboterCost { + possibleProductions[0] = 1 + } + if state.currentRessources[0] >= blueprint.clayRoboterCost { + possibleProductions[1] = 1 + } + if state.currentRessources[0] >= blueprint.obsidianRobototerCost[0] && state.currentRessources[1] >= blueprint.obsidianRobototerCost[1] { + possibleProductions[2] = 1 + } + if state.currentRessources[0] >= blueprint.geodeRoboterCost[0] && state.currentRessources[2] >= blueprint.geodeRoboterCost[1] { + possibleProductions[3] = 1 + } + return possibleProductions +} + +func getBluePrint(line string) Blueprint { + productionCostStrings := strings.Split(strings.Split(line, ":")[1], ". ") + oreCostString := strings.ReplaceAll(productionCostStrings[0], " ore", "")[18:] + oreCost, _ := strconv.Atoi(oreCostString) + clayCostString := strings.ReplaceAll(productionCostStrings[1], " ore", "")[22:] + claycost, _ := strconv.Atoi(clayCostString) + obsidiancostString := strings.ReplaceAll(productionCostStrings[2], "ore and ", "")[26:] + obsidianCost := helper.StringSliceToIntSlice(strings.Split(obsidiancostString[:len(obsidiancostString)-5], " ")) + geodeCostString := strings.ReplaceAll(productionCostStrings[3], "ore and ", "")[23:] + geodeCost := helper.StringSliceToIntSlice(strings.Split(geodeCostString[:len(geodeCostString)-10], " ")) + return Blueprint{oreCost, claycost, [2]int{obsidianCost[0], obsidianCost[1]}, [2]int{geodeCost[0], geodeCost[1]}} +} diff --git a/day19/input b/day19/input new file mode 100644 index 0000000..26d113e --- /dev/null +++ b/day19/input @@ -0,0 +1,30 @@ +Blueprint 1: Each ore robot costs 4 ore. Each clay robot costs 4 ore. Each obsidian robot costs 4 ore and 14 clay. Each geode robot costs 2 ore and 16 obsidian. +Blueprint 2: Each ore robot costs 2 ore. Each clay robot costs 2 ore. Each obsidian robot costs 2 ore and 15 clay. Each geode robot costs 2 ore and 7 obsidian. +Blueprint 3: Each ore robot costs 4 ore. Each clay robot costs 3 ore. Each obsidian robot costs 2 ore and 14 clay. Each geode robot costs 2 ore and 7 obsidian. +Blueprint 4: Each ore robot costs 4 ore. Each clay robot costs 3 ore. Each obsidian robot costs 2 ore and 17 clay. Each geode robot costs 3 ore and 16 obsidian. +Blueprint 5: Each ore robot costs 2 ore. Each clay robot costs 2 ore. Each obsidian robot costs 2 ore and 17 clay. Each geode robot costs 2 ore and 10 obsidian. +Blueprint 6: Each ore robot costs 3 ore. Each clay robot costs 3 ore. Each obsidian robot costs 3 ore and 17 clay. Each geode robot costs 4 ore and 8 obsidian. +Blueprint 7: Each ore robot costs 4 ore. Each clay robot costs 4 ore. Each obsidian robot costs 4 ore and 9 clay. Each geode robot costs 2 ore and 20 obsidian. +Blueprint 8: Each ore robot costs 3 ore. Each clay robot costs 4 ore. Each obsidian robot costs 3 ore and 20 clay. Each geode robot costs 3 ore and 14 obsidian. +Blueprint 9: Each ore robot costs 3 ore. Each clay robot costs 3 ore. Each obsidian robot costs 2 ore and 20 clay. Each geode robot costs 3 ore and 18 obsidian. +Blueprint 10: Each ore robot costs 4 ore. Each clay robot costs 4 ore. Each obsidian robot costs 2 ore and 16 clay. Each geode robot costs 4 ore and 16 obsidian. +Blueprint 11: Each ore robot costs 4 ore. Each clay robot costs 4 ore. Each obsidian robot costs 4 ore and 5 clay. Each geode robot costs 3 ore and 15 obsidian. +Blueprint 12: Each ore robot costs 2 ore. Each clay robot costs 3 ore. Each obsidian robot costs 2 ore and 14 clay. Each geode robot costs 3 ore and 8 obsidian. +Blueprint 13: Each ore robot costs 2 ore. Each clay robot costs 4 ore. Each obsidian robot costs 2 ore and 20 clay. Each geode robot costs 2 ore and 17 obsidian. +Blueprint 14: Each ore robot costs 4 ore. Each clay robot costs 3 ore. Each obsidian robot costs 2 ore and 19 clay. Each geode robot costs 3 ore and 10 obsidian. +Blueprint 15: Each ore robot costs 4 ore. Each clay robot costs 4 ore. Each obsidian robot costs 4 ore and 17 clay. Each geode robot costs 4 ore and 20 obsidian. +Blueprint 16: Each ore robot costs 2 ore. Each clay robot costs 3 ore. Each obsidian robot costs 2 ore and 14 clay. Each geode robot costs 3 ore and 20 obsidian. +Blueprint 17: Each ore robot costs 4 ore. Each clay robot costs 4 ore. Each obsidian robot costs 2 ore and 12 clay. Each geode robot costs 3 ore and 15 obsidian. +Blueprint 18: Each ore robot costs 4 ore. Each clay robot costs 3 ore. Each obsidian robot costs 2 ore and 19 clay. Each geode robot costs 3 ore and 13 obsidian. +Blueprint 19: Each ore robot costs 2 ore. Each clay robot costs 3 ore. Each obsidian robot costs 3 ore and 18 clay. Each geode robot costs 2 ore and 19 obsidian. +Blueprint 20: Each ore robot costs 2 ore. Each clay robot costs 4 ore. Each obsidian robot costs 2 ore and 16 clay. Each geode robot costs 2 ore and 9 obsidian. +Blueprint 21: Each ore robot costs 3 ore. Each clay robot costs 3 ore. Each obsidian robot costs 2 ore and 20 clay. Each geode robot costs 2 ore and 20 obsidian. +Blueprint 22: Each ore robot costs 3 ore. Each clay robot costs 3 ore. Each obsidian robot costs 3 ore and 6 clay. Each geode robot costs 2 ore and 16 obsidian. +Blueprint 23: Each ore robot costs 3 ore. Each clay robot costs 4 ore. Each obsidian robot costs 3 ore and 6 clay. Each geode robot costs 4 ore and 11 obsidian. +Blueprint 24: Each ore robot costs 4 ore. Each clay robot costs 4 ore. Each obsidian robot costs 4 ore and 5 clay. Each geode robot costs 2 ore and 10 obsidian. +Blueprint 25: Each ore robot costs 3 ore. Each clay robot costs 4 ore. Each obsidian robot costs 2 ore and 14 clay. Each geode robot costs 3 ore and 14 obsidian. +Blueprint 26: Each ore robot costs 3 ore. Each clay robot costs 4 ore. Each obsidian robot costs 3 ore and 15 clay. Each geode robot costs 4 ore and 16 obsidian. +Blueprint 27: Each ore robot costs 4 ore. Each clay robot costs 3 ore. Each obsidian robot costs 4 ore and 18 clay. Each geode robot costs 4 ore and 11 obsidian. +Blueprint 28: Each ore robot costs 4 ore. Each clay robot costs 3 ore. Each obsidian robot costs 3 ore and 14 clay. Each geode robot costs 4 ore and 17 obsidian. +Blueprint 29: Each ore robot costs 2 ore. Each clay robot costs 3 ore. Each obsidian robot costs 3 ore and 11 clay. Each geode robot costs 3 ore and 14 obsidian. +Blueprint 30: Each ore robot costs 4 ore. Each clay robot costs 4 ore. Each obsidian robot costs 4 ore and 8 clay. Each geode robot costs 4 ore and 14 obsidian. \ No newline at end of file diff --git a/day19/testinput b/day19/testinput new file mode 100644 index 0000000..5212cde --- /dev/null +++ b/day19/testinput @@ -0,0 +1,2 @@ +Blueprint 1: Each ore robot costs 4 ore. Each clay robot costs 2 ore. Each obsidian robot costs 3 ore and 14 clay. Each geode robot costs 2 ore and 7 obsidian. +Blueprint 2: Each ore robot costs 2 ore. Each clay robot costs 3 ore. Each obsidian robot costs 3 ore and 8 clay. Each geode robot costs 3 ore and 12 obsidian. \ No newline at end of file