diff --git a/day18/part1.kts b/day18/part1.kts new file mode 100755 index 0000000..b995c1d --- /dev/null +++ b/day18/part1.kts @@ -0,0 +1,62 @@ +#!/usr/bin/env kotlin + +import java.io.File +import java.util.LinkedList + +data class Block ( + var type: Type, + var seen: Boolean = false, + var distance: Int = Int.MAX_VALUE +) { + enum class Type { + Empty, + Byte, + } +} + +val bytes = File("input.txt").readLines().subList(0, 1024).map { it.split(",").let { s -> s[0].toInt() to s[1].toInt() } }.toSet() +val grid = (0..70).map { row -> (0..70).map { col -> + Block( + type = if (bytes.contains(col to row)) Block.Type.Byte + else Block.Type.Empty, + ) +}.toMutableList() }.toMutableList() +grid[0][0].seen = true +grid[0][0].distance = 0 + +val queue = LinkedList>() +queue.addFirst(0 to 0) + +while (!queue.isEmpty()) { + // Take one off the queue + val next = queue.pollLast() ?: break + + // Check if we reached goal + if (next.first == 70 && next.second == 70) { + break + } + + // Add neighbors + if ((0..70).contains(next.first + 1) && grid[next.first + 1][next.second].let { it.type == Block.Type.Empty && it.distance > grid[next.first][next.second].distance + 1 }) { + grid[next.first + 1][next.second].seen = true + grid[next.first + 1][next.second].distance = grid[next.first][next.second].distance + 1 + queue.addFirst(next.first + 1 to next.second) + } + if ((0..70).contains(next.second + 1) && grid[next.first][next.second + 1].let { it.type == Block.Type.Empty && it.distance > grid[next.first][next.second].distance + 1 }) { + grid[next.first][next.second + 1].seen = true + grid[next.first][next.second + 1].distance = grid[next.first][next.second].distance + 1 + queue.addFirst(next.first to next.second + 1) + } + if ((0..70).contains(next.first - 1) && grid[next.first - 1][next.second].let { it.type == Block.Type.Empty && it.distance > grid[next.first][next.second].distance + 1 }) { + grid[next.first - 1][next.second].seen = true + grid[next.first - 1][next.second].distance = grid[next.first][next.second].distance + 1 + queue.addFirst(next.first - 1 to next.second) + } + if ((0..70).contains(next.second - 1) && grid[next.first][next.second - 1].let { it.type == Block.Type.Empty && it.distance > grid[next.first][next.second].distance + 1 }) { + grid[next.first][next.second - 1].seen = true + grid[next.first][next.second - 1].distance = grid[next.first][next.second].distance + 1 + queue.addFirst(next.first to next.second - 1) + } +} + +println(grid[70][70].distance) \ No newline at end of file diff --git a/day18/part2.kts b/day18/part2.kts new file mode 100755 index 0000000..54b63e0 --- /dev/null +++ b/day18/part2.kts @@ -0,0 +1,70 @@ +#!/usr/bin/env kotlin + +import java.io.File +import java.util.LinkedList + +data class Block ( + var type: Type, + var seen: Boolean = false, + var distance: Int = Int.MAX_VALUE +) { + enum class Type { + Empty, + Byte, + } +} + +var cutOff = -1 +for (byteCount in 1025..File("input.txt").readLines().count()) { + val bytes = File("input.txt").readLines().subList(0, byteCount).map { it.split(",").let { s -> s[0].toInt() to s[1].toInt() } }.toSet() + val grid = (0..70).map { row -> (0..70).map { col -> + Block( + type = if (bytes.contains(col to row)) Block.Type.Byte + else Block.Type.Empty, + ) + }.toMutableList() }.toMutableList() + grid[0][0].seen = true + grid[0][0].distance = 0 + + val queue = LinkedList>() + queue.addFirst(0 to 0) + + while (!queue.isEmpty()) { + // Take one off the queue + val next = queue.pollLast() ?: break + + // Check if we reached goal + if (next.first == 70 && next.second == 70) { + break + } + + // Add neighbors + if ((0..70).contains(next.first + 1) && grid[next.first + 1][next.second].let { it.type == Block.Type.Empty && it.distance > grid[next.first][next.second].distance + 1 }) { + grid[next.first + 1][next.second].seen = true + grid[next.first + 1][next.second].distance = grid[next.first][next.second].distance + 1 + queue.addFirst(next.first + 1 to next.second) + } + if ((0..70).contains(next.second + 1) && grid[next.first][next.second + 1].let { it.type == Block.Type.Empty && it.distance > grid[next.first][next.second].distance + 1 }) { + grid[next.first][next.second + 1].seen = true + grid[next.first][next.second + 1].distance = grid[next.first][next.second].distance + 1 + queue.addFirst(next.first to next.second + 1) + } + if ((0..70).contains(next.first - 1) && grid[next.first - 1][next.second].let { it.type == Block.Type.Empty && it.distance > grid[next.first][next.second].distance + 1 }) { + grid[next.first - 1][next.second].seen = true + grid[next.first - 1][next.second].distance = grid[next.first][next.second].distance + 1 + queue.addFirst(next.first - 1 to next.second) + } + if ((0..70).contains(next.second - 1) && grid[next.first][next.second - 1].let { it.type == Block.Type.Empty && it.distance > grid[next.first][next.second].distance + 1 }) { + grid[next.first][next.second - 1].seen = true + grid[next.first][next.second - 1].distance = grid[next.first][next.second].distance + 1 + queue.addFirst(next.first to next.second - 1) + } + } + + if (grid[70][70].distance == Int.MAX_VALUE) { + cutOff = byteCount + break + } +} + +println(File("input.txt").readLines()[cutOff - 1]) \ No newline at end of file