Skip to content

Commit 1ef8699

Browse files
committed
abstract away mutability
1 parent 641511b commit 1ef8699

File tree

1 file changed

+28
-25
lines changed

1 file changed

+28
-25
lines changed

2022/src/day16.scala

Lines changed: 28 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import inputs.Input.loadFileSync
1212
def 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
1717
Licensed under the Apache License, Version 2.0 (the "License");
1818
you 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

132135
def 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

Comments
 (0)