diff --git a/day16/day16.go b/day16/day16.go index 668c6ac..3f59e51 100644 --- a/day16/day16.go +++ b/day16/day16.go @@ -3,6 +3,7 @@ package main import ( "AOC2022/helper" "fmt" + "sort" "strconv" "strings" ) @@ -50,7 +51,8 @@ func main() { } func part1(currentValve string, remainingValves []string, valves map[string]Valve) { - activeRountes := []Route{Route{[2]string{currentValve}, [2]int{30}, remainingValves, []string{}, 0}} + activeRountes := make(map[string]Route) + activeRountes[stringSliceToString(remainingValves)] = Route{[2]string{currentValve}, [2]int{30}, remainingValves, []string{}, 0} endedRoutes := []Route{} for len(activeRountes) > 0 { stepFindSolution(&valves, &activeRountes, &endedRoutes) @@ -65,7 +67,8 @@ func part1(currentValve string, remainingValves []string, valves map[string]Valv } func part2(currentValve string, remainingValves []string, valves map[string]Valve) { - activeRountes := []Route{Route{[2]string{currentValve, currentValve}, [2]int{26, 26}, remainingValves, []string{}, 0}} + activeRountes := make(map[string]Route) + activeRountes[stringSliceToString(remainingValves)] = Route{[2]string{currentValve, currentValve}, [2]int{26, 26}, remainingValves, []string{}, 0} endedRoutes := []Route{} for len(activeRountes) > 0 { stepFindSolution(&valves, &activeRountes, &endedRoutes) @@ -80,6 +83,15 @@ func part2(currentValve string, remainingValves []string, valves map[string]Valv fmt.Println(highestPressureReleaseRoute.releasedPressure) } +func stringSliceToString(slice []string) string { + str := "" + sort.Strings(slice) + for i := 0; i < len(slice); i++ { + str += slice[i] + } + return str +} + func falseSolutionPart1(currentValve string, remainingValves []string, valves map[string]Valve) { fmt.Println(currentValve) fmt.Println(remainingValves) @@ -115,69 +127,45 @@ func getNextStep(remainingValves *[]string, valves map[string]Valve, currentValv helper.Remove(remainingValves, bestValve) } -func stepFindSolution(valves *map[string]Valve, remainingRoutes *[]Route, endedRoutes *[]Route) { - currentRoute := (*remainingRoutes)[len(*remainingRoutes)-1] - *remainingRoutes = (*remainingRoutes)[:len(*remainingRoutes)-1] +func stepFindSolution(valves *map[string]Valve, remainingRoutes *map[string]Route, endedRoutes *[]Route) { + key := get_some_key(*remainingRoutes) + currentRoute := (*remainingRoutes)[key] + delete(*remainingRoutes, key) directions1 := getDirections(valves, currentRoute.remainingValves, currentRoute.activeValves[0], currentRoute.remainingTime[0]) directions2 := getDirections(valves, currentRoute.remainingValves, currentRoute.activeValves[1], currentRoute.remainingTime[1]) - directionPairs := [][2]map[string]int{} - for valve1, cost1 := range directions1 { - if len(directions2) == 0 { - direction1 := map[string]int{valve1: cost1} - directionPairs = append(directionPairs, [2]map[string]int{direction1}) - } - for valve2, cost2 := range directions2 { - if valve1 != valve2 { - direction1 := map[string]int{valve1: cost1} - direction2 := map[string]int{valve2: cost2} - directionPairs = append(directionPairs, [2]map[string]int{direction1, direction2}) - } - } - } - if len(directionPairs) == 0 { + + if len(directions1) == 0 && len(directions2) == 0 { *endedRoutes = append(*endedRoutes, currentRoute) } - for _, pair := range directionPairs { - newRoute := Route{} - newPastMoves := currentRoute.pastMoves - newReleasedPressure := currentRoute.releasedPressure - newRemainingValves := currentRoute.remainingValves - for remainingValve, timeCost := range pair[0] { - newRemainingTime1, possibleGainedPressureReduction1 := getNewTimeAndRemainingValves(valves, remainingValve, currentRoute, timeCost) - newReleasedPressure += possibleGainedPressureReduction1 - newPastMoves = append(newPastMoves, remainingValve) - newRemainingValves = helper.RemoveElement(newRemainingValves, remainingValve) - newRoute.remainingTime[0] = newRemainingTime1 - newRoute.activeValves[0] = remainingValve + for remainingValve, timeCost := range directions1 { + newRemainingTime, possibleGainedPressureReduction := getNewTimeAndRemainingValves(valves, remainingValve, currentRoute.remainingTime[0], timeCost) + newRemainingValves := helper.RemoveElement(currentRoute.remainingValves, remainingValve) + newReleasedPressure := currentRoute.releasedPressure + possibleGainedPressureReduction + newPastMoves := append(currentRoute.pastMoves, remainingValve) + value, ok := (*remainingRoutes)[stringSliceToString(newRemainingValves)] + if !ok || newReleasedPressure > value.releasedPressure { + (*remainingRoutes)[stringSliceToString(newRemainingValves)] = Route{[2]string{remainingValve, currentRoute.activeValves[1]}, [2]int{newRemainingTime, currentRoute.remainingTime[1]}, newRemainingValves, newPastMoves, newReleasedPressure} } - for remainingValve, timeCost := range pair[1] { - newRemainingTime2, possibleGainedPressureReduction2 := getNewTimeAndRemainingValves(valves, remainingValve, currentRoute, timeCost) - newReleasedPressure += possibleGainedPressureReduction2 - newPastMoves = append(newPastMoves, remainingValve) - newRemainingValves = helper.RemoveElement(newRemainingValves, remainingValve) - newRoute.remainingTime[1] = newRemainingTime2 - newRoute.activeValves[1] = remainingValve - } - newRoute.pastMoves = newPastMoves - newRoute.releasedPressure = newReleasedPressure - newRoute.remainingValves = newRemainingValves - *remainingRoutes = append(*remainingRoutes, newRoute) } - //for remainingValve, timeCost := range directions1 { - // newRemainingTime, possibleGainedPressureReduction := getNewTimeAndRemainingValves(valves, remainingValve, currentRoute, timeCost) - // newRemainingValves := helper.RemoveElement(currentRoute.remainingValves, remainingValve) - // newReleasedPressure := currentRoute.releasedPressure + possibleGainedPressureReduction - // newPastMoves := append(currentRoute.pastMoves, remainingValve) - // *remainingRoutes = append(*remainingRoutes, Route{[2]string{remainingValve}, [2]int{newRemainingTime}, newRemainingValves, newPastMoves, newReleasedPressure}) - //} + for remainingValve, timeCost := range directions2 { + newRemainingTime, possibleGainedPressureReduction := getNewTimeAndRemainingValves(valves, remainingValve, currentRoute.remainingTime[1], timeCost) + newRemainingValves := helper.RemoveElement(currentRoute.remainingValves, remainingValve) + newReleasedPressure := currentRoute.releasedPressure + possibleGainedPressureReduction + newPastMoves := append(currentRoute.pastMoves, remainingValve) + value, ok := (*remainingRoutes)[stringSliceToString(newRemainingValves)] + if !ok || newReleasedPressure > value.releasedPressure { + (*remainingRoutes)[stringSliceToString(newRemainingValves)] = Route{[2]string{currentRoute.activeValves[0], remainingValve}, [2]int{currentRoute.remainingTime[0], newRemainingTime}, newRemainingValves, newPastMoves, newReleasedPressure} + + } + } } -func getNewTimeAndRemainingValves(valves *map[string]Valve, remainingValve string, currentRoute Route, timeCost int) (int, int) { +func getNewTimeAndRemainingValves(valves *map[string]Valve, remainingValve string, remainingTime int, timeCost int) (int, int) { flowrate := (*valves)[remainingValve].flowRate - newRemainingTime := currentRoute.remainingTime[0] - timeCost + newRemainingTime := remainingTime - timeCost possibleGainedPressureReduction := newRemainingTime * flowrate return newRemainingTime, possibleGainedPressureReduction } @@ -271,7 +259,7 @@ func step(valves *map[string]Valve, activeValves *map[string]struct{}) { } } -func get_some_key(m map[string]struct{}) string { +func get_some_key[T any](m map[string]T) string { for k := range m { return k }