Skip to content

Commit fb73666

Browse files
committed
Day 9
1 parent f7502d5 commit fb73666

File tree

1 file changed

+82
-0
lines changed

1 file changed

+82
-0
lines changed

src/Day09.kt

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
import java.util.*
2+
3+
fun main() {
4+
5+
data class Point(
6+
val row: Int,
7+
val column: Int,
8+
val value: Int
9+
)
10+
11+
fun List<String>.parse() = map { row -> row.map { it.digitToInt() } }
12+
13+
fun List<List<Int>>.getOrMaxInt(
14+
rowIndex: Int,
15+
columnIndex: Int
16+
) = getOrElse(rowIndex) { emptyList() }.getOrElse(columnIndex) { Int.MAX_VALUE }
17+
18+
fun List<List<Int>>.getOrMinInt(
19+
rowIndex: Int,
20+
columnIndex: Int
21+
) = getOrElse(rowIndex) { emptyList() }.getOrElse(columnIndex) { Int.MIN_VALUE }.takeUnless { it == 9 }
22+
?: Int.MIN_VALUE
23+
24+
fun List<List<Int>>.findLowestPoints() = mapIndexed { rowIndex, row ->
25+
row.mapIndexedNotNull { columnIndex, value ->
26+
if (value < getOrMaxInt(rowIndex - 1, columnIndex)
27+
&& value < getOrMaxInt(rowIndex + 1, columnIndex)
28+
&& value < getOrMaxInt(rowIndex, columnIndex - 1)
29+
&& value < getOrMaxInt(rowIndex, columnIndex + 1)
30+
) {
31+
Point(rowIndex, columnIndex, value)
32+
} else null
33+
}
34+
}.flatten()
35+
36+
fun List<List<Int>>.findBasin(lowestPoint: Point): List<Point> {
37+
val visited = Array(size) { BooleanArray(first().size) { false } }
38+
val basin = mutableListOf<Point>()
39+
40+
val queue = LinkedList<Point>()
41+
queue.add(lowestPoint)
42+
basin.add(lowestPoint)
43+
visited[lowestPoint.row][lowestPoint.column] = true
44+
45+
while (queue.isNotEmpty()) {
46+
val point = queue.removeFirst()
47+
48+
listOf(
49+
Point(point.row - 1, point.column, getOrMinInt(point.row - 1, point.column)),
50+
Point(point.row + 1, point.column, getOrMinInt(point.row + 1, point.column)),
51+
Point(point.row, point.column - 1, getOrMinInt(point.row, point.column - 1)),
52+
Point(point.row, point.column + 1, getOrMinInt(point.row, point.column + 1))
53+
)
54+
.filter { point.value < getOrMinInt(it.row, it.column) && !visited[it.row][it.column] }
55+
.forEach {
56+
queue.add(it)
57+
basin.add(it)
58+
visited[it.row][it.column] = true
59+
}
60+
}
61+
62+
return basin
63+
}
64+
65+
fun part1(
66+
input: List<String>
67+
) = input.parse().let { array -> array.findLowestPoints().sumOf { it.value + 1 } }
68+
69+
fun part2(
70+
input: List<String>
71+
) = input.parse().let { array ->
72+
array.findLowestPoints()
73+
.map { array.findBasin(it).count() }
74+
.sortedDescending()
75+
.take(3)
76+
.reduce { acc, value -> acc * value }
77+
}
78+
79+
val input = readInput("Day09")
80+
println(part1(input))
81+
println(part2(input))
82+
}

0 commit comments

Comments
 (0)