Skip to Content

Advent of Code 2022 - Day 1, in Kotlin - Calorie Counting

Kotlin solutions to parts 1 and 2 of Advent of Code 2022, Day 1: 'Calorie Counting'

Posted on

It’s December 1st and that can only mean one thing - Advent of Code is back! Like the last few years, I will be attempting to solve each puzzle in Kotlin and writing a blog post about it each day. I will attempt to provide clear, idiomatic solutions. When solving the puzzles I will almost always trade clarity for speed. Since I only run the puzzle solution code once (ideally), I’m happy to have things run a bit slower than is strictly possible if the code is clearer and easier to understand.

As in past years, I will put my solutions in a GitHub Repository .

Let’s get started!

Puzzle Input

Each day we’ll have a class named after the day number (Day01 in our case today) which will have an input parameter that represents the puzzle input. In our case, this input comes from the unit test that runs the actual puzzle and tests the solution for correctness. The type of input may change from day to day. Today, for example, it is a single large String representing the entire puzzle input. Other days it might be a List<String> or List<Int>, depending on how we’ll use it when writing the solution. The work of loading the daily input file and possibly turning it into a List is done by a helper class class called Resources . which I’ve used in the past.

Before we start in on parsing our input, let’s decide how we want to store it. Part One of the puzzles asks us to find the largest amount of calories carried by one of the elves. This means we could store either the total sum of calories carried by each elf, or store the calorie amount of each food item carried by each elf (which looks like the problem input). Since I’ve already solved Part Two, and know we’ll only need to know the total-per-elf there as well, we’ll store our input as a List<Int> which represents the total calories carried by each elf.

To do this work, we’ll write a function called parseInput, which will be what we call this sort of thing in each puzzle (if we need one).

class Day01(input: String) {

    private val calories = parseInput(input)

    private fun parseInput(input: String): List<Int> =
        input
            .trim()
            .split("\n\n")
            .map { it.lines().sumOf(String::toInt) }
            .sortedDescending()
}

I don’t know about your input but mine ended with a blank line which I am using trim() to remove to make the rest of this easier. If yours didn’t end with a blank line, this won’t cause any harm as there will be nothing to trim() off. The trim() function is very handy when parsing inputs and manipulating strings - it removes leading and trailing whitespace characters from a String (a newline in our case).

Once that is done, we’ll turn our single String into a List<String> by splitting the input on the presence of two newlines (\n\n). This will put each elf’s calorie counts into a single String, with the individual values still separated by newlines (\n).

In order to turn each String into a total calorie count for a specific elf, we’ll need to map each String to an Int. In Kotlin (and many other languages), map means “convert” or “transform”. In this specific case we have a String but want it to represent an Int, so we map the String to an Int. We do this by getting each line of the String input which represents a single food item carried by a single elf. We can call sumOf and hand it a function reference that helps us do the String to Int conversion called String::toInt.

At this point we have a List<Int> that represents the total number of calories carried by each elf, in the order they appeared in the input. Because both parts of the puzzle ask us to find the highest values in this list, we’ll go ahead and sort it from highest to lowest by using sortDescending(). I’ll note here that if we wanted lowest to highest, we would have used sort().

Finally, calories represents the total number of calories carried by each elf, in descending order.

⭐ Day 1, Part 1

The puzzle text can be found here.

Since most of the real work was done in the input parsing section, we can jump right to a solution by finding the maximum value in the calories list. Because we sorted the list descending, the largest value is the first element in the list, which we can get with first() (or using [0] if you find the index accessor clearer, I like using first() or last() when I can).

// In Day01

fun solvePart1(): Int =
    calories.first()

Star earned! Onward!

⭐ Day 1, Part 2

The puzzle text can be found here.

Because we sorted our calorie list during input parsing, the largest counts will be the fist three elements of the calories list. We can get the first three elements by calling take(3) and then calling sum() on the resulting list to add them together.

// In Day01

fun solvePart2(): Int =
    calories.take(3).sum()

Running this gives us our second star!

I hope you enjoyed this puzzle as much as I did. See you tomorrow!

Further Reading

  1. Index of All Solutions - All posts and solutions for 2022, in Kotlin.
  2. My Github repo - Solutions and tests for each day.
  3. Solution - Full code for day 1
  4. Advent of Code - Come join in and do these challenges yourself!