Advent of Code 2022 - Day 25, in Kotlin - Full of Hot Air
Kotlin solutions to parts 1 and 2 of Advent of Code 2022, Day 25: 'Full of Hot Air'
It’s Christmas morning, and that means one thing - the end of another year of Advent of Code puzzles! This closes out my eighth year participating and the sixth year of blogging about my solutions. While I enjoy Advent of Code very much, and look forward to it every year, I’m always a bit relieved and sad when it’s over. I hope you had a much fun solving these as I have. Some of the puzzles have been challenging, and not like the kind of code I usually write at work or for my own purposes. But that’s why we do this, to learn new things and hopefully have some fun. I want to thank you for reading my blog during Advent of Code 2022, and I hope you got something out of it.
If you’d rather just view code, the GitHub Repository is here .
Puzzle Input
We won’t do any parsing or manipulation of the input
today, other than to declare it as a property on Day25
so we can refer to it later. We’ll take it in a List<String>
.
class Day25(private val input: List<String>) {
}
⭐ Day 25, Part 1
The puzzle text can be found here.
While today’s puzzle only has one part, we will write two functions - one for converting SNAFU String
inputs to Long
numbers, and another for doing the reverse. Let’s start with String
(a SNAFU) to Long
, which we’ll implement as an extension function.
// In Day25
private fun String.fromSnafu(): Long =
fold(0) { carry, char ->
(carry * 5) + when(char) {
'-' -> -1
'=' -> -2
else -> char.digitToInt()
}
}
We will fold
over all of the characters in the String
the fromSnafu
function is called on. For each char
, we figure out its decimal value using a when
expression and add that to the carry
multiplied by 5. Why 5? Imagine if we were doing this with base 10 and converting the string “23” to an integer one character at a time. First we’d handle 2, and then handle 3. But we have to multiply 2 by 10 to get 20 so 20+3 works out properly. The same applies in our case with base-5, even if two of the symbols represent negative numbers.
Next, we’ll reverse this with an extension function on Long
. I had a bug here for a while, not realizing that I needed to use Long
and not Int
for all of this. D’oh! At any rate, we’ll set up a sequence starting with the number we’re called with, and continuously adding 2 and dividing by 5. We do this until we hit 0. For each successive value provided from the sequence generator, we take its value mod 5, and look up which character that maps to (0, 1, 2, =, or -). We join these characters into a String
via joinToString
taking care to specify that the separator we want is a blank string, and then reverse the results (because we are building the result String
backwards).
// In Day25
private fun Long.toSnafu(): String =
generateSequence(this) { (it + 2) / 5 }
.takeWhile { it != 0L }
.map { "012=-"[(it % 5).toInt()] }
.joinToString("")
.reversed()
By using these two functions to convert SNAFU to Long
and back, we can solve today’s puzzle! We’ll use sumOf
from the Kotlin Standard Library over the input
after converting each line from a SNAFU number, and then convert the result back to a SNAFU number.
// In Day25
fun solvePart1(): String=
input.sumOf { it.fromSnafu() }.toSnafu()
Star earned! Thanks for sticking with me for all these Advent of Code 2022 posts.
Further Reading
- Index of All Solutions - All posts and solutions for 2022, in Kotlin.
- My Github repo - Solutions and tests for each day.
- Solution - Full code for day 25
- Advent of Code - Come join in and do these challenges yourself!