Introduction
In Day 19 we’re given a problem that is mostly related to the transformations in 3D space, including rotations and shifts of vectors. It’s been fun but also a hard work to implement it in Kotlin from basics in idiomatic way, so let’s see what the final solution is.
Solution
The approach to given problem is somehow straightforward as we try pairing each pair of scanners and remember
the transformations needed to go from one coordinates system to another. To do that, we remember a list of
transformations for each scanner, that is required to transform its coordinate system to the system of the first
scanner (collected in transform
map). What’s more important we also remember if we’ve already check, if there
is some relation between some pair of scanners (which is remembered in triedToPair
). It’s important not to
check multiple times for the same $\textnormal{fromId} \rightarrow \textnormal{toId}$ connection if there
was no transformation found in the past. It cannot be deduced only from cahcedPair
map because it has no value
also if the pair was checked, and it was not found.
We search by starting from some start
scanner that is the reference system and append next scanners, step by step,
by finding next matching pairs between scanner from paired
and toPair
. Notice that we’ve implemented the new
hashCode
and equals
to represent scanner by its id
. This approach simplifies code a lot, so we don’t have
to worry about indices when working with maps.
Day19.kt
|
|
Extra notes
We have used in the solution a few cool Kotlin features that are definitely worth mentioning. Let’s look at the:
- Definitions of
invoke
functions that are declared as operators for transformations of vectors. In this way we got some cool syntax to actually applying transformation to vector or scanner. - We encoded the transformation on vector as a number from range
0..23
which includes the rotation and the change of thez
axe of the coordinate system. It was pretty hard to express it in some good way, so we decided to do it explicitly with writing all possible transformations by hand. If it’s not readable, I encourage you to use your first 3 finger of your hand and see how these axes are transformed (that’s what I did in fact). - Take a look at the
operator fun
defined forV3
class representing the operations on vectors. They’re somehow obvious, but we have to remember that it’s convenient to define them as overloaded operators in Kotlin. - In the search of pair matches we used the named scope
search@
- in this way we can exit the outer loop in Kotlin (and other modern programming languages) and it somehow simplifies the code. - Once again we’ve used the builders methods that’re new stable feature from Kotlin - building
iterables with
buildSet { }
andsequence { }
is really pleasant and straightforward.