@@ -12,7 +12,7 @@ import inputs.Input.loadFileSync
1212def loadInput (): String = loadFileSync(s " $currentDir/../input/day16 " )
1313
1414/*
15- Copyright 2022 Tyler Coles (javadocmd.com) & Quentin Bernet
15+ Copyright 2022 Tyler Coles (javadocmd.com), Quentin Bernet, Sébastien Doeraene and Jamie Thompson
1616
1717Licensed under the Apache License, Version 2.0 (the "License");
1818you may not use this file except in compliance with the License.
@@ -98,36 +98,39 @@ def bestPath(map: RoomsInfo, start: Id, valves: Set[Id], timeAllowed: Int): Int
9898 // we limit our options by only considering the still-closed valves
9999 // and `valves` has already culled any room with a flow value of 0 -- no point in considering these rooms!
100100
101- val valvesArray = valves.toArray
102- val valveCount = valvesArray.length
103- val valvesIndicesLeft = Array .fill[Boolean ](valveCount)(true )
104- val roomsByIndices = Array .tabulate(valveCount)(i => map.rooms(valvesArray(i)))
105-
106- def recurse (current : Id , timeLeft : Int , totalValue : Int ): Int =
101+ val valvesLookup = IArray .from(valves)
102+ val valveCount = valvesLookup.size
103+ val _activeValveIndices = Array .fill[Boolean ](valveCount + 1 )(true ) // add an extra valve for the initial state
104+ def valveIndexLeft (i : Int ) = _activeValveIndices(i)
105+ def withoutValve (i : Int )(f : => Int ) =
106+ try
107+ _activeValveIndices(i) = false
108+ f
109+ finally _activeValveIndices(i) = true
110+ val roomsByIndices = IArray .tabulate(valveCount)(i => map.rooms(valvesLookup(i)))
111+
112+ def recurse (hiddenValve : Int , current : Id , timeLeft : Int , totalValue : Int ): Int = withoutValve(hiddenValve):
107113 // recursively consider all plausible options
108114 // we are finished when we no longer have time to reach another valve or all valves are open
109115 val routesOfCurrent = map.routes(current)
110116 var bestValue = totalValue
111- for index <- 0 until valveCount do
112- if valvesIndicesLeft(index) then
113- val id = valvesArray(index)
114- val distance = routesOfCurrent(id)
115- // how much time is left after we traverse there and open the valve?
116- val t = timeLeft - distance - 1
117- // if `t` is zero or less this option can be skipped
118- if t > 0 then
119- // the value of choosing a particular valve (over the life of our simulation)
120- // is its flow rate multiplied by the time remaining after opening it
121- val value = roomsByIndices(index).flow * t
122- valvesIndicesLeft(index) = false
123- val recValue = recurse(id, t, totalValue + value)
124- valvesIndicesLeft(index) = true
125- if recValue > bestValue then
126- bestValue = recValue
117+ for index <- valvesLookup.indices if valveIndexLeft(index) do
118+ val id = valvesLookup(index)
119+ val distance = routesOfCurrent(id)
120+ // how much time is left after we traverse there and open the valve?
121+ val t = timeLeft - distance - 1
122+ // if `t` is zero or less this option can be skipped
123+ if t > 0 then
124+ // the value of choosing a particular valve (over the life of our simulation)
125+ // is its flow rate multiplied by the time remaining after opening it
126+ val value = roomsByIndices(index).flow * t
127+ val recValue = recurse(hiddenValve = index, id, t, totalValue + value)
128+ if recValue > bestValue then
129+ bestValue = recValue
127130 end for
128131 bestValue
129132 end recurse
130- recurse(start, timeAllowed, 0 )
133+ recurse(valveCount, start, timeAllowed, 0 )
131134
132135def part1 (input : String ) =
133136 val time = 30
@@ -151,7 +154,7 @@ def part2(input: String) =
151154 // taking the best of those.
152155
153156 // we can now calculate the efforts separately and sum their values to find the best
154- val allPaths =
157+ val allPaths =
155158 for va <- valvesA yield
156159 val vb = map.valves -- va
157160 val scoreA = bestPath(map, " AA" , va, time)
0 commit comments