Kotlin and Advent of Code 2021

2021-12-05

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. I'm 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 1moves.map {     val X = it.last().toInt()    when(it.first()) {        "forward" -> horizontal += X        "up"      -> depth -= X        "down"    -> depth += X    }}// part 2moves.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")    .readLines()    .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 1val (horizontal, depth) = moves.reduce { (h, d), (x, y) -> Pair(h + x, d + y) }// part 2val (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")    .readLines()    .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)) } }
``````