#!/usr/bin/env kotlin import java.util.Scanner class TrailHead(var x: Int, var y: Int, private val map: Map) { private val peaks = mutableMapOf, 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> { 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>) { private val trailHeads = mutableListOf() 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>() 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()}")