82 lines
2.5 KiB
Plaintext
82 lines
2.5 KiB
Plaintext
|
#!/usr/bin/env kotlin
|
||
|
import java.util.Scanner
|
||
|
|
||
|
|
||
|
class TrailHead(var x: Int, var y: Int, private val map: Map) {
|
||
|
private val peaks = mutableMapOf<Pair<Int, Int>, Int>()
|
||
|
fun getScore(): Int {
|
||
|
if (this.peaks.isEmpty()) {
|
||
|
for (peak in this.walkToPeak(this.x, this.y)) {
|
||
|
this.peaks[peak] = (this.peaks[peak] ?: 0) + 1
|
||
|
}
|
||
|
}
|
||
|
return this.peaks.keys.size
|
||
|
}
|
||
|
fun getGetRating(): Int {
|
||
|
this.getScore()
|
||
|
return this.peaks.values.sum()
|
||
|
}
|
||
|
|
||
|
private fun walkToPeak(x: Int, y: Int, previous: Int = -1): List<Pair<Int, Int>> {
|
||
|
if (x < 0 || x >= map.getLength() || y < 0 || y >= map.getHeight() || map.get(x, y) != (previous + 1)) {
|
||
|
return listOf()
|
||
|
} else if (map.get(x, y) == 9) {
|
||
|
return listOf(Pair(x, y))
|
||
|
} else {
|
||
|
val current = map.get(x, y)
|
||
|
return walkToPeak(x + 1, y, current) + walkToPeak(x - 1, y, current) + walkToPeak(x, y + 1, current) + walkToPeak(x, y - 1, current)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
class Map(private val grid: List<List<Int>>) {
|
||
|
private val trailHeads = mutableListOf<TrailHead>()
|
||
|
|
||
|
init {
|
||
|
grid.forEachIndexed { y, row ->
|
||
|
row.forEachIndexed { x, height ->
|
||
|
if (height == 0) {
|
||
|
trailHeads.add(TrailHead(x, y, this))
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
fun addTrailHead(trailHead: TrailHead) {
|
||
|
trailHeads.add(trailHead)
|
||
|
}
|
||
|
|
||
|
fun get(x: Int, y: Int): Int {
|
||
|
return grid[y][x]
|
||
|
}
|
||
|
|
||
|
fun getHeight(): Int {
|
||
|
return grid.size
|
||
|
}
|
||
|
|
||
|
fun getLength(): Int {
|
||
|
return if (grid.isNotEmpty()) grid[0].size else 0
|
||
|
}
|
||
|
|
||
|
fun getScore(): Int {
|
||
|
return trailHeads.fold(0) { acc, trailHead -> acc + trailHead.getScore() }
|
||
|
}
|
||
|
|
||
|
fun getGetRating(): Int {
|
||
|
return trailHeads.fold(0) { acc, trailHead -> acc + trailHead.getGetRating() }
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
val scanner = Scanner(System.`in`)
|
||
|
val mapInput = mutableListOf<List<Int>>()
|
||
|
while (scanner.hasNext()) {
|
||
|
val line = scanner.nextLine()
|
||
|
val numbers = line.split("").filter { it.isNotEmpty() }.map { it.toInt() }
|
||
|
mapInput.add(numbers)
|
||
|
}
|
||
|
val map = Map(mapInput.reversed())
|
||
|
|
||
|
println("Score: ${map.getScore()}")
|
||
|
println("Rating: ${map.getGetRating()}")
|