|
| 1 | +package day_15 |
| 2 | + |
| 3 | +import println |
| 4 | +import readInput |
| 5 | +import kotlin.math.absoluteValue |
| 6 | + |
| 7 | +data class Point(val x: Int, val y: Int) { |
| 8 | + override fun toString() = "($x; $y)" |
| 9 | +} |
| 10 | + |
| 11 | +private operator fun Point.minus(other: Point) = (x - other.x).absoluteValue + (y - other.y).absoluteValue |
| 12 | + |
| 13 | +private fun MatchResult.toPoint() = Point( |
| 14 | + groupValues[1].toInt(), |
| 15 | + groupValues[2].toInt(), |
| 16 | +) |
| 17 | + |
| 18 | +fun puzzle1(input: List<String>, row: Int): Int { |
| 19 | + val ignoreX = hashSetOf<Int>() |
| 20 | + val xRanges = mutableListOf<IntRange>() |
| 21 | + |
| 22 | + input.forEach { line -> |
| 23 | + val (match1, match2) = """x=(-?\d+), y=(-?\d+)""".toRegex().findAll(line).toList() |
| 24 | + |
| 25 | + val sensor = match1.toPoint() |
| 26 | + val beacon = match2.toPoint() |
| 27 | + val distance = sensor - beacon |
| 28 | + val radius = if (sensor.y < row) { sensor.y + distance - row } else { row - (sensor.y - distance) } |
| 29 | + |
| 30 | + if (radius > 0) { |
| 31 | + xRanges += (sensor.x - radius)..(sensor.x + radius) |
| 32 | + } |
| 33 | + |
| 34 | + if (beacon.y == row) { |
| 35 | + ignoreX += beacon.x |
| 36 | + } |
| 37 | + } |
| 38 | + |
| 39 | + return xRanges |
| 40 | + .zipWithNext { a, b -> a.toSet() union b.toSet() } |
| 41 | + .flatten() |
| 42 | + .distinct() |
| 43 | + .subtract(ignoreX) |
| 44 | + .size |
| 45 | +} |
| 46 | + |
| 47 | +fun main() { |
| 48 | + val testInput = readInput("day_15/input_test") |
| 49 | + check(puzzle1(testInput, 10) == 26) |
| 50 | + |
| 51 | + val input = readInput("day_15/input") |
| 52 | + puzzle1(input, 2_000_000).println() // 4873353 |
| 53 | +} |
0 commit comments