Day 7: Laboratories

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
[โ€“] 2 points 10 months ago (1 child)

Kotlin

Tried recursive for part1, didn't work. LUCKILY for once I was smart and committed anyway, as it was the right solution for part2! I was losing my mind for a bit though as I had originally written my method with Integers...

Solution

class Day07 : Puzzle {

    val grid = mutableListOf<MutableList<Char>>()
    val partTwoCache = mutableMapOf<Pair<Int, Int>, Long>()

    override fun readFile() {
        val input = readInputFromFile(2025, 7, false)
        for (line in input.lines().filter { it.isNotBlank() }) {
            grid.add(line.toCharArray().toMutableList())
        }
    }

    override fun solvePartOne(): String {
        grid[1][grid[0].indexOf('S')] = '|'

        var splits = 0
        for (r in 1..<grid.size - 1) {
            for (c in 0..<grid[r].size) {
                if (grid[r][c] == '|') {
                    if (grid[r+1][c] == '.') {
                        grid[r+1][c] = '|'
                    } else if (grid[r+1][c] == '^') {
                        grid[r+1][c-1] = '|'
                        grid[r+1][c+1] = '|'
                        splits++
                    }
                }
            }
        }
        return splits.toString()
    }

    override fun solvePartTwo(): String {
        val start = grid[0].indexOf('S')
        return (1 + processBeamPartTwo(1, start)).toString() // don't forget to count the original timeline
    }

    private fun processBeamPartTwo(row: Int, column: Int): Long {
        if (partTwoCache.contains(Pair(row, column))) {
            return partTwoCache[Pair(row, column)]!!
        }

        if (row == grid.size) return 0L
        if (column == grid[row].size || column < 0) return 0L

        val out = if (grid[row][column] == '^') { // splitter
            1L + processBeamPartTwo(row, column - 1) + processBeamPartTwo(row, column + 1)
        } else {
            processBeamPartTwo(row + 1, column)
        }
        partTwoCache[Pair(row, column)] = out
        return out
    }
}

full code on Codeberg

  • source
  • hideshow 1 child comment
  • [โ€“] 2 points 10 months ago

    I didn't do recursion on part 1, so my part 1 and 2 were fairly different.

    const val start = 'S'
    const val empty = '.'
    const val splitter = '^'
    const val beam = '|'
    
    var width: IntRange = IntRange(0, 0)
    var height: IntRange = IntRange(0, 0)
    val cache: MutableMap<Pair<Int, Int>, Long> = mutableMapOf()
    var map: List<List<Char>> = listOf()
    
    fun main() {
        val input = getInput(7)
        map = parseInput1(input)
        height = map.indices
        width = map[0].indices
        val startLocation = map[0].indexOf(start) to 0
        val splits = moveBeam(startLocation) + 1
        println(splits)
    }
    
    fun parseInput1(input: String): List<List<Char>> = input.lines()
        .filter { it.isNotBlank() }
        .map { it.toCharArray().toList() }
    
    fun moveBeam(beamLocation: Pair<Int, Int>): Long {
        if (cache.containsKey(beamLocation)) {
            return cache[beamLocation]!!
        }
        val belowLocation = beamLocation.first to beamLocation.second + 1
        if (belowLocation.second !in height) {
            return 0L
        }
        if (cache.containsKey(belowLocation)) {
            return cache[belowLocation]!!
        }
        val below = map[belowLocation.second][belowLocation.first]
        var splits = 0L
        if (below == empty) {
            splits = moveBeam(belowLocation)
        } else if (below == splitter) {
            splits++
            val leftLocation = belowLocation.first - 1 to belowLocation.second
            val left = if (leftLocation.first in width) map[leftLocation.second][leftLocation.first] else '!'
            if (left == empty || left == splitter) {
                splits += moveBeam(leftLocation)
            }
            val rightLocation = belowLocation.first + 1 to belowLocation.second
            val right = if (rightLocation.first in width) map[rightLocation.second][rightLocation.first] else '!'
            if (right == empty || right == splitter) {
                splits += moveBeam(rightLocation)
            }
        }
        cache[beamLocation] = splits
        return splits
    }
    
  • source
  • parent