aboutsummaryrefslogtreecommitdiff
path: root/src/Day15.kt
diff options
context:
space:
mode:
Diffstat (limited to 'src/Day15.kt')
-rw-r--r--src/Day15.kt159
1 files changed, 74 insertions, 85 deletions
diff --git a/src/Day15.kt b/src/Day15.kt
index abb4bfc..6d0de5c 100644
--- a/src/Day15.kt
+++ b/src/Day15.kt
@@ -1,128 +1,117 @@
import java.util.*
-class CustomPriorityQueue<T>(private val array: Array<T>, private val comparator: Comparator<T>) {
- init {
- array.sortWith(comparator)
- }
-
- private var i = 0
-
- private fun indexOfStartingFrom(elem: T, start: Int): Int {
- for (i in (start until array.size)) {
- if (array[i] == elem) {
- return i
- }
+object Day15 {
+ private class CustomPriorityQueue<T>(private val array: Array<T>, private val comparator: Comparator<T>) {
+ init {
+ array.sortWith(comparator)
}
- return -1
- }
-
- fun isNotEmpty(): Boolean = i < array.size
+ private var i = 0
- fun take(): T = array[i++]
-
- fun revalidate(elem: T) {
- val currentIndex = indexOfStartingFrom(elem, i)
+ private fun indexOfStartingFrom(elem: T, start: Int): Int {
+ for (i in (start until array.size)) {
+ if (array[i] == elem) {
+ return i
+ }
+ }
- if (currentIndex == -1) {
- return
+ return -1
}
- val newIndex = Arrays
- .binarySearch(array, i, currentIndex, elem, comparator)
- .let { if (it >= 0) it else -(it + 1) }
+ fun isNotEmpty(): Boolean = i < array.size
- System.arraycopy(array, newIndex, array, newIndex + 1, currentIndex - newIndex)
+ fun take(): T = array[i++]
- array[newIndex] = elem
- }
-}
+ fun revalidate(elem: T) {
+ val currentIndex = indexOfStartingFrom(elem, i)
-class Matrix(private val data: Array<IntArray>, private val size: Int) {
- companion object {
- fun fromInput(input: List<String>): Matrix {
- val data = input.map { line ->
- line.map { it.digitToInt() }.toIntArray()
- }.toTypedArray()
+ if (currentIndex == -1) {
+ return
+ }
- check(data.isNotEmpty()) { "No rows found!" }
- check(data.first().isNotEmpty()) { "No columns found!" }
+ val newIndex = Arrays
+ .binarySearch(array, i, currentIndex, elem, comparator)
+ .let { if (it >= 0) it else -(it + 1) }
- return Matrix(data, data.size)
+ System.arraycopy(array, newIndex, array, newIndex + 1, currentIndex - newIndex)
+
+ array[newIndex] = elem
}
}
- private fun inMatrix(row: Int, col: Int): Boolean = row in 0 until size && col in 0 until size
-
- fun set(row: Int, col: Int, value: Int) {
- check(inMatrix(row, col)) { "Invalid position!" }
- data[row][col] = value
- }
+ private class Matrix(private val data: Array<IntArray>, private val size: Int) {
+ companion object {
+ fun fromInput(input: List<String>): Matrix {
+ val data = input.map { line ->
+ line.map { it.digitToInt() }.toIntArray()
+ }.toTypedArray()
- fun get(row: Int, col: Int): Int {
- check(inMatrix(row, col)) { "Invalid position!" }
- return data[row][col]
- }
+ check(data.isNotEmpty()) { "No rows found!" }
+ check(data.first().isNotEmpty()) { "No columns found!" }
- fun expand(): Matrix {
- val expandedData = Array(size * 5) { row ->
- IntArray(size * 5) { col ->
- ((data[row % size][col % size] + row / size + col / size) - 1) % 9 + 1
+ return Matrix(data, data.size)
}
}
- return Matrix(expandedData, size * 5)
- }
+ fun expand(): Matrix {
+ val expandedData = Array(size * 5) { row ->
+ IntArray(size * 5) { col ->
+ ((data[row % size][col % size] + row / size + col / size) - 1) % 9 + 1
+ }
+ }
- private fun neighbours(pos: Pair<Int, Int>): Sequence<Pair<Int, Int>> {
- val offsets = sequenceOf(0 to 1, 1 to 0, 0 to -1, -1 to 0)
+ return Matrix(expandedData, size * 5)
+ }
- return offsets
- .map { pos.first + it.first to pos.second + it.second }
- .filter { it.first in 0 until size && it.second in 0 until size }
- }
+ private fun neighbours(pos: Pair<Int, Int>): Sequence<Pair<Int, Int>> {
+ val offsets = sequenceOf(0 to 1, 1 to 0, 0 to -1, -1 to 0)
+
+ return offsets
+ .map { pos.first + it.first to pos.second + it.second }
+ .filter { it.first in 0 until size && it.second in 0 until size }
+ }
- fun dijkstra(): Int {
- val positions = (0 until size)
- .flatMap { row -> (0 until size).map { col -> row to col } }
+ fun dijkstra(): Int {
+ val positions = (0 until size)
+ .flatMap { row -> (0 until size).map { col -> row to col } }
- val distances =
- positions
- .associateWith { Int.MAX_VALUE }
- .toMutableMap()
+ val distances =
+ positions
+ .associateWith { Int.MAX_VALUE }
+ .toMutableMap()
- distances[0 to 0] = 0
+ distances[0 to 0] = 0
- val queue = CustomPriorityQueue(positions.toTypedArray(), compareBy { distances[it]!! })
+ val queue = CustomPriorityQueue(positions.toTypedArray(), compareBy { distances[it]!! })
- while (queue.isNotEmpty()) {
- val u = queue.take()
+ while (queue.isNotEmpty()) {
+ val u = queue.take()
- for (v in neighbours(u)) {
- val newDist = distances[u]!! + data[v.first][v.second]
- if (distances[v]!! > newDist) {
- distances[v] = newDist
- queue.revalidate(v)
+ for (v in neighbours(u)) {
+ val newDist = distances[u]!! + data[v.first][v.second]
+ if (distances[v]!! > newDist) {
+ distances[v] = newDist
+ queue.revalidate(v)
+ }
}
}
- }
- return distances[size - 1 to size - 1]!!
+ return distances[size - 1 to size - 1]!!
+ }
}
-}
-fun main() {
fun part1(input: List<String>): Int = Matrix.fromInput(input).dijkstra()
fun part2(input: List<String>): Int = Matrix.fromInput(input).expand().dijkstra()
+}
-
+fun main() {
val testInput = readInputAsLines("Day15_test")
- check(part1(testInput) == 40)
- check(part2(testInput) == 315)
+ check(Day15.part1(testInput) == 40)
+ check(Day15.part2(testInput) == 315)
val input = readInputAsLines("Day15")
- println(part1(input))
- println(part2(input))
+ println(Day15.part1(input))
+ println(Day15.part2(input))
}