Day 3: Lobby

Megathread guidelines

  • Keep top level comments as only solutions, if you want to say something other than a solution put it in a new post. (replies to comments can be whatever)
  • You can send code in code blocks by using three backticks, the code, and then three backticks or use something such as https://topaz.github.io/paste/ if you prefer sending it through a URL

FAQ

you are viewing a single comment's thread
view the rest of the comments
[โ€“] 4 points 9 months ago (5 children)

Kotlin

First day this year where I am very happy with my solution. Just super simple, recursive string building.

Solution

class Day03 : Puzzle {

    val banks = mutableListOf<String>()

    override fun readFile() {
        val input = readInputFromFile("src/main/resources/a2025/day03.txt")
        banks.addAll(input.lines().filter(String::isNotBlank))
    }

    override fun solvePartOne(): String {
        val sum = banks.map { buildNumber(it, 2) }.sumOf { it.toLong() }
        return sum.toString()
    }

    override fun solvePartTwo(): String {
        val sum = banks.map { buildNumber(it, 12) }.sumOf { it.toLong() }
        return sum.toString()
    }

    private fun buildNumber(bank: String, remainingDigits: Int): String {
        if (remainingDigits <= 0) return ""
        val current = bank.dropLast(remainingDigits - 1)
        val max = current.max()
        return max + buildNumber(bank.split(max, limit = 2)[1], remainingDigits - 1)
    }
}

full code on Codeberg

  • source
  • hideshow 5 child comments
  • [โ€“] 2 points 9 months ago (4 children)

    Today was interesting. My first thought was that part 2 would be a lot more complex at first glance. But I realized that my solution for part 1 worked almost out of the box for part 2.

    I was also pleased to see that the algorithm ran in 1ms, which was a good deal faster than just parsing the input.

    fun main() {
        val input = getInput(3)
        val banks = parseInput(input)
        var total = 0L
        banks.forEach { bank ->
            var location = 0
            var joltage = 0L
            for (power in 11 downTo 0) {
                val multiplier = 10.toDouble().pow(power).toLong()
                val batteryLocation = findBattery(bank, location, bank.size - power - 1)
                val battery = bank[batteryLocation]
                location = batteryLocation + 1
                joltage += battery.toLong() * multiplier
            }
            total += joltage
        }
        println(total)
    }
    
    fun parseInput(input: String): List<List<Int>> = input
        .split("\n")
        .filter { it.isNotBlank() }
        .map { it.toCharArray() }
        .map { it.map { digit -> digit.digitToInt() } }
    
    fun findBattery(bank: List<Int>, start: Int, end: Int): Int {
        var max = 0
        var location = 0
        for (i in start..end) {
            val battery = bank[i]
            if (battery > max) {
                max = battery
                location = i
                if (battery == 9) {
                    break
                }
            }
        }
        return location
    }
    
  • source
  • parent
  • hideshow 4 child comments
  • [โ€“] 2 points 9 months ago (3 children)

    Nice! I thought about using numbers but then decided that strings are a lot easier to deal with.

  • source
  • parent
  • hideshow 3 child comments
  • [โ€“] 1 point 9 months ago (2 children)

    I was curious, so I ran yours and it is only like 3-4ms slower. I was honestly surprised it was that close.

    Just goes to show that we're often wrong when estimating and the only real way to know is to benchmark.

  • source
  • parent
  • hideshow 2 child comments
  • [โ€“] 2 points 9 months ago

    My version used strings as well, and I thought that as I was comparing small integers either way, it made sense to stay in ASCII as the strings were already easy to index, and it meant I could skip parsing input numbers, only needing to parse output numbers so they could be summed.

    I did start with numbers so I could convert it back to compare, but it's so fast (the whole thing takes 1ms - and that's reading/parsing the input twice) that it's almost a micro benchmark.

  • source
  • parent