. 3 min read
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
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")
.readLines()
.map { it.split(" ") }
.map {
val X = it[1].toInt()
when(it[0]) {
"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)
}
)
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()[0]
.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[6] = sevens + zeroes
8 -> fishes[8] = spawns
else -> fishes[j] = fishes.getOrDefault(j + 1, 0L)
}
}
}
fishes.values.sum()
2021 December 07, 12:00 noon IST. Today was a bit easier:
var positions = File("7.txt")
.readLines()[0]
.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)) } }