2022-12-17 18:02:58 +01:00
package main
import (
"AOC2022/helper"
"fmt"
"strconv"
"strings"
)
type Valve struct {
id string
flowRate int
routes map [ string ] int
cost int
before string
}
2022-12-17 19:32:19 +01:00
type Route struct {
2022-12-17 20:53:14 +01:00
activeValves [ 2 ] string
remainingTime [ 2 ] int
2022-12-17 19:32:19 +01:00
remainingValves [ ] string
pastMoves [ ] string
releasedPressure int
}
2022-12-17 18:02:58 +01:00
func main ( ) {
//args := os.Args[1:]
2022-12-17 19:32:19 +01:00
lines := helper . ReadTextFile ( "day16/input" )
2022-12-17 18:02:58 +01:00
valves := getValves ( lines )
valvesWithFlowRate := getValvesWithFlowRate ( valves )
valvesWithFlowRate = append ( valvesWithFlowRate , "AA" )
valvesCopy := deepCopyMap ( valves )
for i , activeValve := range valvesWithFlowRate {
routes := make ( map [ string ] int )
for j , valve := range valvesWithFlowRate {
if i != j {
tmpValves := deepCopyMap ( valvesCopy )
routeLenght := getRouteLength ( activeValve , valve , tmpValves )
routes [ valve ] = routeLenght
}
}
entry := valves [ activeValve ]
entry . routes = routes
valves [ activeValve ] = entry
}
currentValve := "AA"
remainingValves := valvesWithFlowRate [ : len ( valvesWithFlowRate ) - 1 ]
2022-12-17 20:53:14 +01:00
part2 ( currentValve , remainingValves , valves )
}
func part1 ( currentValve string , remainingValves [ ] string , valves map [ string ] Valve ) {
activeRountes := [ ] Route { Route { [ 2 ] string { currentValve } , [ 2 ] int { 30 } , remainingValves , [ ] string { } , 0 } }
2022-12-17 19:32:19 +01:00
endedRoutes := [ ] Route { }
for len ( activeRountes ) > 0 {
stepFindSolution ( & valves , & activeRountes , & endedRoutes )
}
highestPressureRelease := 0
for _ , route := range endedRoutes {
if route . releasedPressure > highestPressureRelease {
highestPressureRelease = route . releasedPressure
}
}
fmt . Println ( highestPressureRelease )
}
2022-12-17 20:53:14 +01:00
func part2 ( currentValve string , remainingValves [ ] string , valves map [ string ] Valve ) {
activeRountes := [ ] Route { Route { [ 2 ] string { currentValve , currentValve } , [ 2 ] int { 26 , 26 } , remainingValves , [ ] string { } , 0 } }
endedRoutes := [ ] Route { }
for len ( activeRountes ) > 0 {
stepFindSolution ( & valves , & activeRountes , & endedRoutes )
}
highestPressureReleaseRoute := Route { }
highestPressureReleaseRoute . releasedPressure = 0
for _ , route := range endedRoutes {
if route . releasedPressure > highestPressureReleaseRoute . releasedPressure {
highestPressureReleaseRoute = route
}
}
fmt . Println ( highestPressureReleaseRoute . releasedPressure )
}
2022-12-17 19:32:19 +01:00
func falseSolutionPart1 ( currentValve string , remainingValves [ ] string , valves map [ string ] Valve ) {
fmt . Println ( currentValve )
fmt . Println ( remainingValves )
2022-12-17 18:02:58 +01:00
remainingTime := 30
sumReleasedPressure := 0
2022-12-17 19:32:19 +01:00
for len ( remainingValves ) > 0 && remainingTime > 0 {
getNextStep ( & remainingValves , valves , & currentValve , & remainingTime , & sumReleasedPressure )
fmt . Println ( currentValve )
}
fmt . Println ( sumReleasedPressure )
2022-12-17 18:02:58 +01:00
}
func getNextStep ( remainingValves * [ ] string , valves map [ string ] Valve , currentValve * string , remainingTime * int , sumReleasedPressure * int ) {
bestValve := - 1
bestValue := 0
for i , remainingValve := range * remainingValves {
movingTimeCost := valves [ * currentValve ] . routes [ remainingValve ]
openingTimeCost := 1
flowrate := valves [ remainingValve ] . flowRate
possibleGainedPressureReduction := ( * remainingTime - openingTimeCost - movingTimeCost ) * flowrate
if possibleGainedPressureReduction > bestValue {
bestValue = possibleGainedPressureReduction
bestValve = i
}
}
2022-12-17 19:32:19 +01:00
if bestValve == - 1 {
* remainingTime = 0
return
}
2022-12-17 18:02:58 +01:00
* sumReleasedPressure += bestValue
* remainingTime -= ( valves [ * currentValve ] . routes [ ( * remainingValves ) [ bestValve ] ] + 1 )
* currentValve = ( * remainingValves ) [ bestValve ]
helper . Remove ( remainingValves , bestValve )
}
2022-12-17 19:32:19 +01:00
func stepFindSolution ( valves * map [ string ] Valve , remainingRoutes * [ ] Route , endedRoutes * [ ] Route ) {
currentRoute := ( * remainingRoutes ) [ len ( * remainingRoutes ) - 1 ]
* remainingRoutes = ( * remainingRoutes ) [ : len ( * remainingRoutes ) - 1 ]
2022-12-17 20:53:14 +01:00
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 } )
}
2022-12-17 19:32:19 +01:00
}
}
2022-12-17 20:53:14 +01:00
if len ( directionPairs ) == 0 {
2022-12-17 19:32:19 +01:00
* endedRoutes = append ( * endedRoutes , currentRoute )
}
2022-12-17 20:53:14 +01:00
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 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})
//}
}
func getNewTimeAndRemainingValves ( valves * map [ string ] Valve , remainingValve string , currentRoute Route , timeCost int ) ( int , int ) {
flowrate := ( * valves ) [ remainingValve ] . flowRate
newRemainingTime := currentRoute . remainingTime [ 0 ] - timeCost
possibleGainedPressureReduction := newRemainingTime * flowrate
return newRemainingTime , possibleGainedPressureReduction
}
func getDirections ( valves * map [ string ] Valve , remainingValves [ ] string , activeValve string , remainingTime int ) map [ string ] int {
directions := make ( map [ string ] int )
for _ , remainingValve := range remainingValves {
movingTimeCost := ( * valves ) [ activeValve ] . routes [ remainingValve ]
openingTimeCost := 1
if remainingTime > movingTimeCost + openingTimeCost {
directions [ remainingValve ] = movingTimeCost + openingTimeCost
}
2022-12-17 19:32:19 +01:00
}
2022-12-17 20:53:14 +01:00
return directions
2022-12-17 19:32:19 +01:00
}
2022-12-17 18:02:58 +01:00
func deepCopyMap ( valves map [ string ] Valve ) map [ string ] Valve {
tmpValves := make ( map [ string ] Valve )
for k , v := range valves {
tmpValves [ k ] = v
}
return tmpValves
}
func getValves ( lines [ ] string ) map [ string ] Valve {
valves := make ( map [ string ] Valve )
for _ , line := range lines {
id := line [ 6 : 8 ]
flowrate := helper . RemoveError ( strconv . Atoi ( strings . Split ( line [ 23 : ] , ";" ) [ 0 ] ) )
routesStrings := strings . Split ( strings . Split ( line [ 23 : ] , ";" ) [ 1 ] [ 24 : ] , ", " )
routes := make ( map [ string ] int )
for _ , routeString := range routesStrings {
routes [ routeString ] = 1
}
valves [ id ] = Valve { id , flowrate , routes , 0 , "" }
}
return valves
}
func getValvesWithFlowRate ( valves map [ string ] Valve ) [ ] string {
valvesWithFlowRate := [ ] string { }
for key , val := range valves {
if val . flowRate > 0 {
valvesWithFlowRate = append ( valvesWithFlowRate , key )
}
}
return valvesWithFlowRate
}
func getRouteLength ( valve1 , valve2 string , valves map [ string ] Valve ) int {
activeValves := make ( map [ string ] struct { } )
activeValves [ valve1 ] = struct { } { }
return getBestRouteLength ( activeValves , valves , valve2 )
}
func getBestRouteLength ( activeValves map [ string ] struct { } , valves map [ string ] Valve , endValve string ) int {
for len ( activeValves ) > 0 {
step ( & valves , & activeValves )
}
return valves [ endValve ] . cost
}
func step ( valves * map [ string ] Valve , activeValves * map [ string ] struct { } ) {
valve := get_some_key ( * activeValves )
delete ( * activeValves , valve )
currentValve := ( * valves ) [ valve ]
currentFieldSumCost := currentValve . cost
directions := currentValve . routes
2022-12-17 19:32:19 +01:00
for _ , v := range * valves {
lenthConnectionToCurrentValve := 0
for connectedValve , length := range v . routes {
if connectedValve == currentValve . id {
lenthConnectionToCurrentValve = length
}
}
if lenthConnectionToCurrentValve > 0 {
directions [ v . id ] = lenthConnectionToCurrentValve
}
}
2022-12-17 18:02:58 +01:00
for nextValve , _ := range directions {
cost := 1 + currentFieldSumCost
if nextValve != currentValve . before {
if ( * valves ) [ nextValve ] . cost > cost || ( * valves ) [ nextValve ] . cost == 0 {
entry := ( * valves ) [ nextValve ]
entry . cost = cost
entry . before = valve
( * valves ) [ nextValve ] = entry
( * activeValves ) [ nextValve ] = struct { } { }
}
}
}
}
func get_some_key ( m map [ string ] struct { } ) string {
for k := range m {
return k
}
return ""
}