| 
 | 1 | +package net.olegg.aoc.year2024.day18  | 
 | 2 | + | 
 | 3 | +import net.olegg.aoc.someday.SomeDay  | 
 | 4 | +import net.olegg.aoc.utils.Directions.Companion.NEXT_4  | 
 | 5 | +import net.olegg.aoc.utils.Vector2D  | 
 | 6 | +import net.olegg.aoc.utils.parseInts  | 
 | 7 | +import net.olegg.aoc.utils.get  | 
 | 8 | +import net.olegg.aoc.utils.set  | 
 | 9 | +import net.olegg.aoc.year2024.DayOf2024  | 
 | 10 | + | 
 | 11 | +/**  | 
 | 12 | + * See [Year 2024, Day 18](https://adventofcode.com/2024/day/18)  | 
 | 13 | + */  | 
 | 14 | +object Day18 : DayOf2024(18) {  | 
 | 15 | + private val size = 71  | 
 | 16 | + | 
 | 17 | + override fun first(): Any? {  | 
 | 18 | + val bytes = lines.map { line ->  | 
 | 19 | + val (x, y) = line.parseInts(",")  | 
 | 20 | + Vector2D(x, y)  | 
 | 21 | + }.take(1024).toSet()  | 
 | 22 | + | 
 | 23 | + val map = List(size) { y -> List(size) { x -> Vector2D(x, y) in bytes } }  | 
 | 24 | + | 
 | 25 | + val start = Vector2D(0, 0) to 0  | 
 | 26 | + val finish = Vector2D(size - 1, size - 1)  | 
 | 27 | + val queue = ArrayDeque(listOf(start))  | 
 | 28 | + val seen = mutableSetOf<Pair<Vector2D, Int>>()  | 
 | 29 | + | 
 | 30 | + while (queue.isNotEmpty()) {  | 
 | 31 | + val curr = queue.removeFirst()  | 
 | 32 | + val (point, step) = curr  | 
 | 33 | + if (point == finish) {  | 
 | 34 | + return step  | 
 | 35 | + }  | 
 | 36 | + if (curr in seen) {  | 
 | 37 | + continue  | 
 | 38 | + }  | 
 | 39 | + seen += curr  | 
 | 40 | + | 
 | 41 | + queue += NEXT_4.map { point + it.step }  | 
 | 42 | + .filter { map[it] == false }  | 
 | 43 | + .map { it to step + 1 }  | 
 | 44 | + }  | 
 | 45 | + | 
 | 46 | + return -1  | 
 | 47 | + }  | 
 | 48 | + | 
 | 49 | + override fun second(): Any? {  | 
 | 50 | + val bytes = lines.map { line ->  | 
 | 51 | + val (x, y) = line.parseInts(",")  | 
 | 52 | + Vector2D(x, y)  | 
 | 53 | + }  | 
 | 54 | + | 
 | 55 | + var left = 0  | 
 | 56 | + var right = bytes.lastIndex  | 
 | 57 | + var mid = (left + right) / 2  | 
 | 58 | + | 
 | 59 | + while (right - left > 1) {  | 
 | 60 | + val cut = bytes.take(mid).toSet()  | 
 | 61 | + val map = List(size) { y -> MutableList(size) { x -> Vector2D(x, y) in cut } }  | 
 | 62 | + | 
 | 63 | + if (fill(map)) {  | 
 | 64 | + left = mid  | 
 | 65 | + } else {  | 
 | 66 | + right = mid  | 
 | 67 | + }  | 
 | 68 | + mid = (left + right) / 2  | 
 | 69 | + }  | 
 | 70 | + | 
 | 71 | + return bytes[left].let { "${it.x},${it.y}" }  | 
 | 72 | + }  | 
 | 73 | + | 
 | 74 | + private fun fill(map: List<MutableList<Boolean>>): Boolean {  | 
 | 75 | + val start = Vector2D(0, 0)  | 
 | 76 | + val finish = Vector2D(size - 1, size - 1)  | 
 | 77 | + val queue = ArrayDeque(listOf(start))  | 
 | 78 | + val seen = mutableSetOf<Vector2D>()  | 
 | 79 | + | 
 | 80 | + while (queue.isNotEmpty()) {  | 
 | 81 | + val curr = queue.removeFirst()  | 
 | 82 | + if (curr == finish) {  | 
 | 83 | + return true  | 
 | 84 | + }  | 
 | 85 | + if (curr in seen) {  | 
 | 86 | + continue  | 
 | 87 | + }  | 
 | 88 | + seen += curr  | 
 | 89 | + | 
 | 90 | + val next = NEXT_4.map { curr + it.step }  | 
 | 91 | + .filter { map[it] == false }  | 
 | 92 | + | 
 | 93 | + next.forEach { map[it] = true }  | 
 | 94 | + | 
 | 95 | + queue += next  | 
 | 96 | + }  | 
 | 97 | + | 
 | 98 | + return map[finish]!!  | 
 | 99 | + }  | 
 | 100 | +}  | 
 | 101 | + | 
 | 102 | +fun main() = SomeDay.mainify(Day18)  | 
0 commit comments