Introduction
The Day 11 problem requires form us writing some simulation of flashing in described manner. We can implement this in some readable way by using custom data structures and redefining some operators in Kotlin - let’s begin and see how to express some complicated code in a few lines of text.
Solution
We defined the operators for modifying internal values of the map to get extra functionality by calculating
posOf
i.e. the map from values to the positions where we can find every of them on the map. Thanks to this
function we can always ask about the places with energy equal to 10 (in constant time) and propagate the
energy from them in single flash
execution.
Let’s notice that we defined the flash
function as tailrec fun
so it is optimized by the compiler to standard
loop. We did that because it’s usually more readable to see that was our intention when writing this code - we want
to mark current positions as flashed
, then for every of them propagate the energy to its neighbours and then
try to flash
again from the positions on which the maxVal
appeared in current step of flashing.
It’s worth mentioning also how we defined the LazyDefaultMap<K, V>
(and modified DefaultMap<K, V>
) when solving
this task. Now we ended up with the definition, that allows to compute the default value lazily, but also
it sets the computed value to the backing map. It seemed to be more reasonable approach as we think about the
value extracted from map as it would be in it - so when it’s a mutable value, then after its modifications,
we should observe this modification in map.
|
|
Don’t miss the definitions that uses Sequence<T>
in today code - they both were defined to improve
code readability and keep the performance in my opinion - let me know what you think about such
“functional” approaching to the problems 😉.
Day11.kt
|
|
Extra notes
Let’s see that we solved each of the parts of the task on the copy of the input map. That’s because the map internal state is mutable (it changes during the simulation) but we need to have a fresh map when trying to solve the second part of the problem.
We used with
Kotlin construct here, that simplified our code and introduced the context of current copy of
EnergyMap
. That’s one of the really cool Kotlin constructs that is in fact an inline function, so it brings no
extra overhead on runtime while really simplifying our code.
Also in this day we introduced tests running with expected outputs of days. We used for it some tricky and simple function
|
|
which is capable of catching the System.out
value and returning it as simple String
(that is later cmopared
with the expected output in tests and Advent days are defined to print their solutions).