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

  • eco_game@discuss.tchncs.de
    link
    fedilink
    arrow-up
    3
    ·
    3 days ago

    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

    • chunkystyles@sopuli.xyz
      link
      fedilink
      English
      arrow-up
      2
      ·
      3 days 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
      }