Introduction
The Day 20 problem seemed to be quite straightforward at first sight and the base can be passed here really quickly. The magic is in boundaries conditions of the task and the given sample, that doesn’t include such situation, so we have to deal with it on ourselves.
Solution
To solve the problem of enhancing the image, we need some more information that the locations of lighten
pixel (that we store in Image::enlighten
field). We need to take care of the current background
state, as it can also change during the enhancement. However, it can only change from
fully empty to fully filled with enlighten pixels, so it’s enough if we remember only a Boolean
flag
for this state in fillInfty
.
It’s not so obvious at first to include the infinity of image also in its computations, but it was definitely the hardest part of this task (and to realize what’s going on when base sample is working but the final answer is wrong).
Day20.kt
|
|
Extra notes
We used extension properties as well extension functions in our solution to make it more readable. For example, it’s more convenient to define the
|
|
if we check for this equality a few times in a file, and it can be precisely named. That’s just a single line
that enables nice syntax like c.isLight
instead of writing the symbol explicitly with ==
.
Notice also the definition of infix fun on
for Pixel
class that was later used in encoding
method.
We can define such functions in Kotlin for every type and give them the names, which make reading code
more pleasant. Remember about that, when writing your libraries in Kotlin, just to give the developers
possibility to use infix notation for functions with single argument.
Once again, we should see and remember how the builders for collections in Kotlin can be used. Let’s see that
the usage of buildSet { }
contains just single nested instruction, while it is a nested for
loop with the
let { }
usage on pixel - it’s really efficient approach of going through the image and building the new one
at the same time.
We came up with also some tricky local definition of extension function for IntRange
that made it expand
in both directions by just writing
|
|
Then, it was used to process the pixels from the border in standard loop by iterating like
|
|
This kind of approach is really cool and removes a lot of code repetitions, but we need to define them usually with private visibility, as they might have been understood differently in different contexts, e.g. we could have also
|
|
or even
|
|
so always remember to make sure, that the other developers will understand what you meant or just forbid using your definitions outside your world, to make code safe 😉.