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 {
activeValves [ ] string
remainingTime int
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 19:32:19 +01:00
activeRountes := [ ] Route { Route { [ ] string { currentValve } , 30 , remainingValves , [ ] string { } , 0 } }
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 )
}
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 ]
directions := make ( map [ string ] int )
for _ , remainingValve := range currentRoute . remainingValves {
movingTimeCost := ( * valves ) [ currentRoute . activeValves [ 0 ] ] . routes [ remainingValve ]
openingTimeCost := 1
if currentRoute . remainingTime > movingTimeCost + openingTimeCost {
directions [ remainingValve ] = movingTimeCost + openingTimeCost
}
}
if len ( directions ) == 0 {
* endedRoutes = append ( * endedRoutes , currentRoute )
}
for remainingValve , timeCost := range directions {
flowrate := ( * valves ) [ remainingValve ] . flowRate
newRemainingTime := currentRoute . remainingTime - timeCost
newRemainingValves := helper . RemoveElement ( currentRoute . remainingValves , remainingValve )
possibleGainedPressureReduction := newRemainingTime * flowrate
newReleasedPressure := currentRoute . releasedPressure + possibleGainedPressureReduction
newPastMoves := append ( currentRoute . pastMoves , remainingValve )
* remainingRoutes = append ( * remainingRoutes , Route { [ ] string { remainingValve } , newRemainingTime , newRemainingValves , newPastMoves , newReleasedPressure } )
}
}
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 ""
}