<Advent of Code 2022 day 25> :christmas_tree:
# advent-of-code
a
d
So thankful for an easy day. Merry holidays everyone and thank you for all the great discussions. 🎄
k
Once I saw that the numbers where 2,1,0,-1,-2 and just popped of. Balanced bases are so fun to work with =)
c
The shortest of all puzzles. Guess he didn't want to drag people too far away from holiday celebrations with family. Only 'tricky' bit is managing the carry for conversion back. Merry Christmas everyone.
s
Is there any trickiness to the actual input? My
toSnafu()
converter works well for all numbers in the example, but doesn't work for the input
My logic is that you add 1 to the remainder on the current step if on the previous step the remainder was greater than 2
c
I resorted to Long out of conservatism, but I'm not sure it's strictly necessary. Here's my sub if your curious: https://github.com/CognitiveGear/AdventOfCode-Kotlin/blob/main/calendar2022/src/main/kotlin/Day25.kt
s
That was not the
toSnafu()
, that was
fromSnafu()
giving me wrong results because of int overflow... 🤦‍♂️
j
decoding is super easy thanks to fold:
Copy code
fun part1(input: String) = input.lineSequence()
    .sumOf(::decode)
    .let(::encode)

private const val DIGITS = "=-012"

private fun decode(line: String) = line.fold(0L) { acc, c ->
    acc * 5 + DIGITS.indexOf(c) - 2
}
But I wonder if there’s a way to oneline encoding using kotlin’s stdlib goodies. so far mine looks like this:
Copy code
private fun encode(number: Long): String {
    if (number == 0L) return "0"
    var b = number
    return buildString {
        while (b > 0) {
            val m = (b + 2) % 5
            b = (b + 2) / 5
            append(DIGITS[m.toInt()])
        }
    }.reversed()
}
s
Here's the most concise I could get:
Copy code
fun Long.toSnafu() = generateSequence(this to "") { (number, acc) ->
    val remainder = number.mod(5)
    (number + 5 * (remainder / 3)) / 5 to "012=-"[remainder] + acc
}.first { it.first == 0L }.second
The actual challenge today was to get up at 6 am after so much Glühwein. Happy holidays, folks! 🎁
j
Merry Christmas you all
m
Took me 3 hours of debugging before I found out
5f.pow(19).toLong()
gives the wrong result. 😢
I was co confused why day 25 isn’t easy, it’s always easy. 😄
oh! wait! the maximum you can get from mod 5 is 4.
a
for an extra challenge, this Code Golf post is missing a Kotlin entry :) https://codegolf.stackexchange.com/questions/106441/convert-between-balanced-bases
s
Here's a solution without converting to decimal and back:
Copy code
class Day25(val contents: String) {

    private val digits = "=-012"

    fun part1() = contents.lines().fold("0") { acc, line ->
        val maxLen = max(line.length, acc.length) + 1
        acc.padStart(maxLen, '0').zip(line.padStart(maxLen, '0'))
            .foldRight("" to 0) { (a, b), (result, carry) ->
                val sum = digits.indexOf(a) + digits.indexOf(b) - 4 + carry
                (digits[(sum + 7) % 5] + result) to sum / 3
            }.first.trimStart('0')
    }

}
I guess I could have used
generateSequence
instead of a loop
r
Might be better approaches, but my logic was to convert to base-5 first and then replace
3
or
4
with it's equivalent
-
or
=
and add the the carry part to the next digit in left.
For part2 - you need all previous stars?
t
I spent a decent chunk of time wondering why my logic didn’t work only to discover I was overflowing an Int. Feels like I should have figured that out sooner, but at least I figured it out. 🙂BlogCode
e
I skipped reading too much of the problem and submitted the decimal sum first :D
j
I learned the hard way in previous years that it's better to work on Longs in AoC 🙂 even if that means ugly stuff like
i == 0L
or necessary
.toInt()
here and there, whenever indices are needed. Then, before committing to repo, I switch back to ints 🙂
o
I also submitted the decimal at first. 😅