Day 4: Printing Department
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
- What is this?: Here is a post with a large amount of details: https://programming.dev/post/6637268
- Where do I participate?: https://adventofcode.com/
- Is there a leaderboard for the community?: We have a programming.dev leaderboard with the info on how to join in this post: https://programming.dev/post/6631465


Kotlin
Pretty simple solution, just plain count / remove the rolls until none can be removed anymore. I would’ve liked to try using imaginary numbers this year (due to this article), but sadly Kotlin doesn’t natively support them and I was too lazy to use a library.
Solution
class Day04 : Puzzle { val grid = mutableListOf<MutableList<Char>>() override fun readFile() { val input = readInputFromFile("src/main/resources/a2025/day04.txt") for ((r, line) in input.lines().filter(String::isNotBlank).withIndex()) { grid.add(mutableListOf()) for (char in line) { grid[r].add(char) } } } override fun solvePartOne(): String { return countRolls(grid).toString() } override fun solvePartTwo(): String { var sum = 0 var removed = -1 while (removed != 0) { // main grid is modified here, not the best but doesn't really matter // also no idea how to clone 2D list in Kotlin removed = countRolls(grid, true) sum += removed } return sum.toString() } private fun countRolls(grid: MutableList<MutableList<Char>>, removeRolls: Boolean = false): Int { val dr = listOf(-1, -1, -1, 0, 0, 1, 1, 1) val dc = listOf(-1, 0, 1, -1, 1, -1, 0, 1) var sum = 0 for (r in grid.indices) { for (c in grid[r].indices) { if (grid[r][c] != '@') continue var neighborCount = 0 for (i in dr.indices) { if (gridGet(grid, r + dr[i], c + dc[i]) == '@') neighborCount++ } if (neighborCount < 4) { sum++ if (removeRolls) grid[r][c] = '.' } } } return sum } private fun gridGet(grid: List<List<Char>>, r: Int, c: Int, default: Char = '.'): Char { return if (r in grid.indices && c in grid[r].indices) { grid[r][c] } else { default } } }full code on Codeberg
Ha, I’ve got that article half-read in a tab somewhere. Same problem here though - they’re not in the standard library for anything I plan to use for AoC.
Edit: looking at your code, I had forgotten about
.indices. That would have made this a little easier to write.I completely forgot to do the puzzle yesterday somehow. I struggled a bit on this one for a while because I’d used a
<= 4where I should have used a< 4. Just a complete brainfart of thinking, “It needs to be 4 or less”. I wasted more time on that than I’d like to admit.My first stab at this set all of the adjacency counts to 0, and that lead to a few rolls that had no rolls adjacent to them staying on the map by accident.
const val toiletPaperRoll = '@' const val adjacentLimit = 4 var height = 0 var width = 0 fun main() { val input = getInput(4) val map = parseInput1(input) height = map.size width = map[0].size val adjacencyMap = createAdjacencyMap(map) var anyRemoved = true var count = 0 while (anyRemoved) { anyRemoved = false for (y in 0..<height) { for (x in 0..<width) { if (adjacencyMap[y][x] in 0..<adjacentLimit) { count++ anyRemoved = true removeToiletPaperRoll(adjacencyMap, x, y) } } } } println(count) } fun parseInput1(input: String): List<List<Char>> = input .lines() .filter { it.isNotBlank() } .map { it.toCharArray().toList() } fun createAdjacencyMap(map: List<List<Char>>): List<MutableList<Int>> { val adjacencyMap = List(height) { MutableList(width) { -1 } } for (y in 0..<height) { for (x in 0..<width) { if (map[y][x] != toiletPaperRoll) { continue } adjacencyMap[y][x]++ for (y2 in y - 1..y + 1) { for (x2 in x - 1..x + 1) { if (y == y2 && x == x2 || (y2 < 0 || x2 < 0 || y2 >= height || x2 >= width)) { continue } if (map[y2][x2] == toiletPaperRoll) { adjacencyMap[y2][x2]++ } } } } } return adjacencyMap } fun removeToiletPaperRoll(adjacencyMap: List<MutableList<Int>>, x: Int, y: Int) { adjacencyMap[y][x] = -1 for (y2 in y - 1..y + 1) { for (x2 in x - 1..x + 1) { if (y == y2 && x == x2 || (y2 < 0 || x2 < 0 || y2 >= height || x2 >= width)) { continue } if (adjacencyMap[y2][x2] >= adjacentLimit) { adjacencyMap[y2][x2]-- } } } }