Day 6: Guard Gallivant
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
Not much inspiration. Brute forcing my way through today’s level.
Solution
typealias Grid = List<List<Char>> private val up: Char = '^' private val down: Char = 'v' private val left: Char = '<' private val right: Char = '>' private val obstacle: Char = '#' private val directions: Set<Char> = setOf(up, down, left, right) data class Position( var direction: Char, var row: Int, var col: Int, val visited: MutableSet<Pair<Int, Int>> = mutableSetOf(), val history: MutableSet<Triple<Char, Int, Int>> = mutableSetOf(), ) { override fun toString(): String = "Position(direction: $direction, position: ($row,$col))" } fun part1(input: String): Int { val grid: Grid = input.lines().map(String::toList) val position = findStartPosition(grid) while (!isEndPosition(position, grid)) { moveOrTurn(position, grid) } return position.visited.size } fun part2(input: String): Int { var loops = 0 for (i in input.indices) { if (input[i] != '.') { continue } val sb = StringBuilder(input) sb.setCharAt(i, obstacle) val grid: Grid = sb.toString().lines().map(String::toList) val position = findStartPosition(grid) while (!isEndPosition(position, grid)) { moveOrTurn(position, grid) if (isLoop(position)) { loops++ break } } } return loops } private fun findStartPosition(grid: Grid): Position { for (row in grid.indices) { for (col in grid[row].indices) { val c = grid[row][col] if (directions.contains(c)) { val pos = Position(c, row, col) pos.visited.add(Pair(row, col)) return pos } } } throw IllegalStateException("No start position found") } private fun isEndPosition(position: Position, grid: Grid): Boolean { return position.row == 0 || position.col == 0 || position.row == grid.size - 1 || position.col == grid.size - 1 } private fun isLoop(position: Position): Boolean { return position.history.contains(Triple(position.direction, position.row, position.col)) } private fun moveOrTurn(position: Position, grid: Grid) { position.history.add(Triple(position.direction, position.row, position.col)) when (position.direction) { up -> if (grid[position.row - 1][position.col] == obstacle) position.direction = right else position.row-- right -> if (grid[position.row][position.col + 1] == obstacle) position.direction = down else position.col++ down -> if (grid[position.row + 1][position.col] == obstacle) position.direction = left else position.row++ left -> if (grid[position.row][position.col - 1] == obstacle) position.direction = up else position.col-- else -> throw IllegalStateException("Invalid direction, cannot move") } position.visited.add(Pair(position.row, position.col)) }