diff --git a/day19/day19.go b/day19/day19.go index f5174cf..f6cfbf8 100644 --- a/day19/day19.go +++ b/day19/day19.go @@ -26,13 +26,13 @@ func main() { 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, map[[9]int]State{[9]int{0, 0, 0, 0, 1, 0, 0, 0, 0}: State{[4]int{0, 0, 0, 0}, [4]int{1, 0, 0, 0}, 0}}, 2) + startStates := getAllPossibleCombinationsWithFastestTime(blueprint, map[[9]int]State{[9]int{0, 0, 0, 0, 1, 0, 0, 0, 0}: State{[4]int{0, 0, 0, 0}, [4]int{1, 0, 0, 0}, 0}}, 2, fastestTime) + tmpStates := getAllPossibleCombinationsWithFastestTime(blueprint, map[[9]int]State{[9]int{0, 0, 0, 0, 1, 0, 0, 0, 0}: 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) + fmt.Println(i) } sum := 0 for i, score := range highestGeode { @@ -42,7 +42,7 @@ func main() { } -func getHighestGeode(blueprint Blueprint, startStates []State) int { +func getHighestGeode(blueprint Blueprint, startStates map[[9]int]State) int { activeStates := startStates endStates := []State{} for len(activeStates) > 0 { @@ -50,14 +50,14 @@ func getHighestGeode(blueprint Blueprint, startStates []State) int { } highestgeode := 0 for _, state := range endStates { - if state.currentRessources[3] > highestgeode && state.runtime < 25 { + if state.currentRessources[3] > highestgeode && state.runtime >= 25 { highestgeode = state.currentRessources[3] } } return highestgeode } -func getFastestTimeToElementN(blueprint Blueprint, startStates []State, untilElementN int) int { +func getFastestTimeToElementN(blueprint Blueprint, startStates map[[9]int]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 { @@ -66,71 +66,75 @@ func getFastestTimeToElementN(blueprint Blueprint, startStates []State, untilEle return fastestTimeToObsidianState.runtime } -func getAllPossibleCombinationsWithFastestTime(blueprint Blueprint, startStates []State, untilElementN int, fastestTime int) []State { +func getAllPossibleCombinationsWithFastestTime(blueprint Blueprint, startStates map[[9]int]State, untilElementN int, fastestTime int) map[[9]int]State { activeStates := startStates - fastestTimeToObsidianState := map[[8]int]State{} + fastestTimeToObsidianState := map[[9]int]State{} for len(activeStates) > 0 { stepFindAllFastestTime(&activeStates, &fastestTimeToObsidianState, untilElementN, fastestTime, &blueprint) } - returnStates := []State{} - for _, val := range fastestTimeToObsidianState { - returnStates = append(returnStates, val) - } - return returnStates + return fastestTimeToObsidianState } -func step(activeStates *[]State, fastestTImeToObsidian *State, untilElementN int, blueprint *Blueprint) { - activeStates, newTmpStates := generatePossibleTmpStates(activeStates, blueprint) +func step(activeStates *map[[9]int]State, fastestTImeToObsidian *State, untilElementN int, blueprint *Blueprint) { + 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) + (*activeStates)[getIdentifier(tmpState)] = tmpState } } } -func stepHighestGeode(activeStates *[]State, endStates *[]State, blueprint *Blueprint) { - activeStates, newTmpStates := generatePossibleTmpStates(activeStates, blueprint) +func stepHighestGeode(activeStates *map[[9]int]State, endStates *[]State, blueprint *Blueprint) { + newTmpStates := generatePossibleTmpStates(activeStates, blueprint) for _, tmpState := range newTmpStates { if tmpState.runtime < 24 { - *activeStates = append(*activeStates, tmpState) + (*activeStates)[getIdentifier(tmpState)] = tmpState + } else if tmpState.runtime > 24 { + fmt.Println("WTF") } 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) +func stepFindAllFastestTime(activeStates *map[[9]int]State, fastestTImeStates *map[[9]int]State, untilElementN int, fastestTime int, blueprint *Blueprint) { + 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]) + if tmpState.currentProduction[untilElementN] > 0 && fastestTime >= tmpState.runtime && tmpState.runtime < 24 { + identifier := getIdentifier(tmpState) (*fastestTImeStates)[identifier] = tmpState } - if tmpState.currentProduction[untilElementN] == 0 && tmpState.runtime < fastestTime { - *activeStates = append(*activeStates, tmpState) + if tmpState.currentProduction[untilElementN] == 0 && tmpState.runtime < fastestTime && tmpState.runtime < 24 { + (*activeStates)[getIdentifier(tmpState)] = tmpState } } } -func generatePossibleTmpStates(activeStates *[]State, blueprint *Blueprint) (*[]State, []State) { - activeState := (*activeStates)[len(*activeStates)-1] - *activeStates = (*activeStates)[:len(*activeStates)-1] +func getIdentifier(tmpState State) [9]int { + identifier := [9]int{} + copy(identifier[:], append(append(tmpState.currentRessources[:], tmpState.currentProduction[:]...), tmpState.runtime)[:9]) + return identifier +} + +func generatePossibleTmpStates(activeStates *map[[9]int]State, blueprint *Blueprint) map[[9]int]State { + key := get_some_key(*activeStates) + activeState := (*activeStates)[key] + delete(*activeStates, key) possibleProductions := activeState.getPossibleProductions(blueprint) - newTmpStates := []State{} + newTmpStates := make(map[[9]int]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) + newTmpStates[getIdentifier(tmpState)] = tmpState } } - return activeStates, newTmpStates + return newTmpStates } func (state *State) produceRoboter(blueprint *Blueprint, roboter int) { @@ -189,3 +193,10 @@ func getBluePrint(line string) Blueprint { 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]}} } + +func get_some_key(m map[[9]int]State) [9]int { + for k := range m { + return k + } + return [9]int{} +}