### Kotlin and Advent of Code 2021

Posted on

This year, I'm doing Advent of Code in the Kotlin programming language. I wanted to briefly present some of my solutions. I'm also committing the solutions on GitHub as a notebook, having tried the wonderful Kotlin Jupyter kernel.

As of Day 6, my personal stats so far are below. I couldn't strictly solve the problems on time at 10:30AM IST as I am on vacation.

``````      --------Part 1--------   --------Part 2--------
Day       Time   Rank  Score       Time   Rank  Score
6   00:26:09   7818      0   01:50:03  10209      0
5   06:29:40  24271      0   06:29:48  20773      0
4   23:23:28  52511      0   23:23:41  48883      0
3   00:56:29  14015      0   01:04:16   7074      0
2   00:08:19   5877      0   00:15:40   6746      0
1   00:06:57   3878      0   00:14:02   3648      0``````

### DAY 2

The rough idea of day 2 is to take some navigational instructions and compute the result as the product of final horizontal and vertical positions after making the moves. The full problem statement is available at https://adventofcode.com/2021/day/2. I enjoy that I could simply read the file into a list like below in Kotlin, which also sets us up nicely to do all sorts of input parsing for more complicated use cases.

``val moves = File("input.txt").readLines().map { it.split(" ") }``

At first, I tried using `map` and `when`

``````// part 1
moves.map {
val X = it.last().toInt()
when(it.first()) {
"forward" -> horizontal += X
"up"      -> depth -= X
"down"    -> depth += X
}
}

// part 2
moves.map {
val X = it.last().toInt()
when(it.first()) {
"forward" -> {
horizontal += X
depth = depth + (aim * X)
}
"up"      -> aim -= X
"down"    -> aim += X
}
}``````

but later, I noticed that it is possible to model the instructions as movement in some `(X, Y)` plane. Therefore, the `forward`, `up`, `down` becomes irrelevant. And I could leverage `reduce` and `fold`. To achieve that, here is how the moves can be parsed:

``````val moves = File("2.txt")
.map { it.split(" ") }
.map {
val X = it.toInt()
when(it) {
"forward" -> Pair(+X, 0)
"up" -> Pair(0, -X)
else -> Pair(0, +X)
}
}``````

and once that's done:

``````// part 1
val (horizontal, depth) = moves.reduce { (h, d), (x, y) -> Pair(h + x, d + y) }

// part 2
val (h, d, a) = moves.fold(
initial = Triple(0, 0, 0),
operation = {
(h, d, a), (x, y) -> Triple(h + x, d + a * x, a + y)
}
)``````

### Day 6

Today (6th of December, 2021) is the sixth day of the Advent of Code, and below is a solution. I must admit I can already see a few possible refactoring opportunities, but it is what it is for now.

``````var fishes = File("6.txt")
.split(",")
.map { it.toInt() }
.groupingBy { it }
.eachCount()
.mapValues { it -> it.value.toLong() }.toMutableMap()

for ( i in 1..256 ) {
val spawns = fishes.getOrDefault(0, 0L)
val sevens = fishes.getOrDefault(7, 0L)
val zeroes = fishes.getOrDefault(0, 0L)
for ( j in 0..8 ) {
when(j) {
6    -> fishes = sevens + zeroes
8    -> fishes = spawns
else -> fishes[j] = fishes.getOrDefault(j + 1, 0L)
}
}
}

fishes.values.sum()``````

### Day 7

2021 December 07, 12:00 noon IST. Today was a bit easier:

``````var positions = File("7.txt")
.split(",")
.map { it.toInt() }

val median = positions
.sorted()
.let { (it[it.size / 2] + it[(it.size - 1) / 2]) / 2 }

fun gauss(n: Int) = n * (n + 1) / 2

positions
.sumOf { abs(it - median) }

(1..positions.maxOrNull()!!)
.minOf { p -> positions.sumOf {  gauss(abs(p - it)) } }``````