Advent of Code 2022 in Kotlin - Day 1

Introduction

We start with Day 1 problem for which the solution is based on the template from the two years ago Advent of Code. Let’s begin to see some cool features of modern language - Kotlin 😎.

Solution

The biggest problem - parsing the data properly - was solved in my case by some helper function, that I’ve written during last year Advent of Code. It’s a pretty generic function that was designed to help with input which is built of separated groups of data

fun <U, V> List<U>.groupSeparatedBy(
  separator: (U) -> Boolean,
  includeSeparator: Boolean = false,
  transform: (List<U>) -> V
): Sequence<V> = sequence {
  var curr = mutableListOf<U>()
  [email protected] {
    if (separator(it) && curr.isNotEmpty()) yield(transform(curr))
    if (separator(it)) curr = if (includeSeparator) mutableListOf(it) else mutableListOf()
    else curr += it
  }
  if (curr.isNotEmpty()) yield(transform(curr))
}

with such a helper we can easily group input lines separated by empty lines and make calculations on these groups. As in both parts we’re interested in sum of values for each Elf, we can sum them in advance.

Day1.kt

object Day1 : AdventDay() {
  override fun solve() {
    val lines = getInputLines() ?: exit()
    val carry = lines.groupSeparatedBy(
      separator = { line -> line == "" },
      transform = { group -> group.sumOf { it.toInt() } }
    )
    carry.max().printIt()
    carry.sortedDescending().take(3).sum().printIt()
  }
}

Extra notes

Let’s see that we used [email protected] when defining the helper function. It allows us to refer explicitly to specified object, when this identifier may refer to different objects in current context. In Kotlin, it might be seen more often in iterations over some loop, if you want to continue using forEach extension function like

listOf(1, 2, 3, 4).forEach {
  val even = it % 2 == 0
  if (!even) [email protected]
  val result = it * it
  println(result)
}

or any other function that defines some new context that you can jump out.

Moreover, what I really like in Kotlin, you can do this more explicitly and name this context on your own usually, just to make your code more readable like

listOf(1, 2, 3, 4).forEach [email protected]{
  val even = it % 2 == 0
  if (!even) [email protected]
  val result = it * it
  println(result)
}

Conclusions

Let’s grab the groupSeparatedBy to your codebase and reuse it as definitely it might be helpful in some future tasks. I hope you’ve had a great start of advent as well and naming the contexts in Kotlin is no longer some mystery to you 🤞.

Student of Computer Science

My interests include robotics (mainly with Arduino), mobile development for Android (love Kotlin) and Java SE/EE applications development.