@@ -5,80 +5,64 @@ package day10
55
66import common.aocreader.fetchAdventOfCodeInput
77import common.intpos2d.*
8- import common.parsing.parseGrid
98
109private typealias Trail = List <IntPos2D >
1110private typealias Trails = Set <List <IntPos2D >>
1211
13- private enum class Direction (val delta : IntPos2D ) {
14- NORTH (IntPos2D (- 1 , 0 )),
15- EAST (IntPos2D (0 , 1 )),
16- SOUTH (IntPos2D (1 , 0 )),
17- WEST (IntPos2D (0 , - 1 )),
18- }
19-
2012private fun parse (input : String ): List <List <Int >> =
2113 input.trim().lines()
22- .map { line -> line.trim().toList().map { it.digitToInt() } }
14+ .map { line -> line.trim().toList().map { it.digitToIntOrNull() ? : - 1 } }
2315
24- private fun findTrailheads (grid : List <List <Int >>): Map <IntPos2D , Trails > {
16+ private fun findTrails (grid : List <List <Int >>): Map <IntPos2D , Trails > {
2517 val height = grid.size
2618 val width = grid[0 ].size
2719
28- // Instead of going from zeros to nines, we go from nines to zeros
29- // to count the number of trails to the peak.
30- // Find the nines, i.e. the ending positions of the map.
31- val nines = grid.flatMapIndexed { rowIdx, row ->
20+ val zeros = grid.flatMapIndexed { rowIdx, row ->
3221 row.mapIndexedNotNull { colIdx, height ->
33- if (height == 9 ) IntPos2D (rowIdx, colIdx) else null
22+ if (height == 0 ) IntPos2D (rowIdx, colIdx) else null
3423 }
3524 }.toSet()
3625
37- // We need to track the number of trails to each nine.
38- val trails: MutableMap <IntPos2D , Trails > = mutableMapOf ()
39-
4026 // For each 9, we want to find the trails that lead to the peak.
4127 fun aux (trailSoFar : Trail ): Trails {
4228 val currentPos = trailSoFar.last()
4329 val (currY, currX) = currentPos
4430 val currHeight = grid[currY][currX]
45- if (currHeight == 0 ) return setOf (trailSoFar)
31+ if (currHeight == 9 ) return setOf (trailSoFar)
4632
4733 // Try all the valid neighbours.
4834 val neighbours = Direction .entries
4935 .map { currentPos + it.delta }
5036 .filter { coords -> coords.first in 0 until height && coords.second in 0 until width }
51- .filter { coords -> grid[coords.first][coords.second] == currHeight - 1 }
37+ .filter { coords -> grid[coords.first][coords.second] == currHeight + 1 }
5238 if (neighbours.isEmpty()) return emptySet()
5339
5440 return neighbours.flatMap { pos -> aux(trailSoFar + pos) }.toSet()
5541 }
5642
57- nines.forEach { nine ->
58- val allTrails = aux(listOf (nine))
59- trails[nine] = allTrails
60- }
61-
62- return trails
43+ return zeros.associate { zero -> zero to aux(listOf (zero)) }
6344}
6445
65- fun countTrailheads (trails : Map <IntPos2D , Trails >): Int =
66- trails.values.flatten().toSet().size
46+ private fun countTrailheads (trails : Map <IntPos2D , Trails >): Int =
47+ trails.values.sumOf { it.map { it.last() }.toSet().size }
48+
49+ private fun countTrails (trails : Map <IntPos2D , Trails >): Int =
50+ trails.values.sumOf { it.count() }
6751
6852fun answer1 (input : String ): Int =
69- parse(input).let (::findTrailheads ).let (::countTrailheads)
53+ parse(input).let (::findTrails ).let (::countTrailheads)
7054
7155fun answer2 (input : String ): Int =
72- TODO ( )
56+ parse(input). let (::findTrails). let (::countTrails )
7357
7458fun main () {
7559 val input = fetchAdventOfCodeInput(2024 , 10 )
7660
77- println (" --- Day 10: Resonant Collinearity ---" )
61+ println (" --- Day 10: Hoof It ---" )
7862
79- // Part 1:
63+ // Part 1: 719
8064 println (" Part 1: ${answer1(input)} " )
8165
82- // Part 2:
66+ // Part 2: 1530
8367 println (" Part 2: ${answer2(input)} " )
8468}
0 commit comments