Day 6: Trash Compactor

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

  • GiantTree@feddit.org
    link
    fedilink
    arrow-up
    2
    ·
    edit-2
    2 months ago

    Kotlin

    More grid stuff and two-dimensional problem solving, I like it!
    The first part just requires extracting the numbers and operators, transposing the grid and summing/multiplying the numbers.
    The second part is also not too hard. I just search for the numbers in the transposed grid, making sure to leave out the last column. That one might contain an operator (“+” or “*”). Remember it for later. If the entire row is made of spaces, we have finished parsing a math problem. Just remember to account for the last one! 😅
    As with part one, just reduce the found problems and we’re done!

    This solution requires the trailing spaces to be present in the input files. I had to disable an option in my IDE to prevent it from breaking my nice solution.

    Code on Github

    Code
    class Day06 : AOCSolution {
        override val year = 2025
        override val day = 6
    
        override fun part1(inputFile: String): String {
            val worksheet = readResourceLines(inputFile)
            // Arrange the problem in a grid and transpose it, so that the operation is the last element of each row
            val problems = worksheet.map { line -> line.trim().split(spaceSplitRegex) }.toGrid().transposed()
    
            val grandTotal = problems.rows().sumOf { line ->
                // Map the all but the last element to a number
                val numbers = line.mapToLongArray(0, line.lastIndex - 1, String::toLong)
                // Extract the operation
                val operation = line.last()[0]
    
                // Call the correct reduction
                // The "else" branch is needed for the compiler
                when (operation) {
                    ADD -> numbers.sum()
                    MULTIPLY -> numbers.reduce { acc, value -> acc * value }
                    else -> 0
                }
            }
            return grandTotal.toString()
        }
    
        override fun part2(inputFile: String): String {
            val worksheet = readResourceLines(inputFile)
    
            // In this part the problem is more complicated and dependent on the individual characters.
            val charGrid = worksheet.map(CharSequence::toList).toCharGrid().transposed()
    
            val numbers = mutableListOf<Long>()
            val sb = StringBuilder(charGrid.width)
    
            val problems = buildList {
                // Begin with an empty operation
                // Assume the operation will be set to a valid value
                var operation = SPACE
                for (y in 0 until charGrid.height) {
                    // Extract each row (transposed column)
                    sb.clear().append(charGrid[y])
                    // Find the bounds of the number
                    val numberOffset = sb.indexNotOf(SPACE)
    
                    if (numberOffset != -1) {
                        // A number was found, parse it and add it to the list.
                        val endIndex = sb.indexOfAny(STOP_CHARACTERS, numberOffset + 1)
                        val number = java.lang.Long.parseLong(sb, numberOffset, endIndex, 10)
                        numbers.add(number)
    
                        // Check whether there is an operation in the last column.
                        // IF so, that's the next relevant operation
                        val lastColumn = sb[sb.lastIndex]
                        if (lastColumn != SPACE) {
                            operation = lastColumn
                        }
                    } else {
                        // No number was found, that's the separator for two calculations.
                        // Finalize the collection and clear the numbers.
                        // `toLongArray` creates a neat copy of the Longs in the list.
                        add(Problem(operation, numbers.toLongArray()))
                        numbers.clear()
                    }
                }
                // Add the last remaining problem to the list
                add(Problem(operation, numbers.toLongArray()))
            }
    
            // Reduce all problems to their solutions and sum them up.
            val grandTotal = problems.sumOf { problem ->
                when (problem.operation) {
                    ADD -> problem.numbers.sum()
                    MULTIPLY -> problem.numbers.reduce { acc, value -> acc * value }
                    else -> 0
                }
            }
    
            return grandTotal.toString()
        }
    
        private companion object {
            private const val ADD = '+'
            private const val MULTIPLY = '*'
            private const val SPACE = ' '
            private val STOP_CHARACTERS = charArrayOf(SPACE, ADD, MULTIPLY)
    
            @JvmRecord
            @Suppress("ArrayInDataClass")
            private data class Problem(val operation: Char, val numbers: LongArray)
        }