11private const val DAY = 9
22
33fun main () {
4- fun part1 (input : List <List <Byte >>): Int {
4+ fun part1 (input : List <List <Point >>): Int {
55 var sum = 0
66 for (x in input.indices) {
77 for (y in input[0 ].indices) {
8- val currentHeight = input[x][y]
9- if (x > 0 && currentHeight >= input[x- 1 ][y]) {
8+ val currentHeight = input[x][y].height
9+ if (x > 0 && currentHeight >= input[x- 1 ][y].height ) {
1010 continue
1111 }
12- if (y > 0 && currentHeight >= input[x][y- 1 ]) {
12+ if (y > 0 && currentHeight >= input[x][y- 1 ].height ) {
1313 continue
1414 }
15- if (x < input.size - 1 && currentHeight >= input[x+ 1 ][y]) {
15+ if (x < input.size - 1 && currentHeight >= input[x+ 1 ][y].height ) {
1616 continue
1717 }
18- if (y < input[0 ].size - 1 && currentHeight >= input[x][y+ 1 ]) {
18+ if (y < input[0 ].size - 1 && currentHeight >= input[x][y+ 1 ].height ) {
1919 continue
2020 }
2121 sum + = currentHeight + 1
2222 }
2323 }
2424 return sum
2525 }
26- fun part2 (input : List <List <Byte >>) = - 1
26+
27+ fun part2 (input : List <List <Point >>): Int {
28+ val basinSizes = mutableListOf<Int >()
29+ for (x in input.indices) {
30+ for (y in input[0 ].indices) {
31+ val currentHeight = input[x][y].height
32+ if (x > 0 && currentHeight >= input[x- 1 ][y].height) {
33+ continue
34+ }
35+ if (y > 0 && currentHeight >= input[x][y- 1 ].height) {
36+ continue
37+ }
38+ if (x < input.size - 1 && currentHeight >= input[x+ 1 ][y].height) {
39+ continue
40+ }
41+ if (y < input[0 ].size - 1 && currentHeight >= input[x][y+ 1 ].height) {
42+ continue
43+ }
44+ val basinSize = getBasinSize(input, x, y) + 1 // plus low point itself
45+ basinSizes.add(basinSize)
46+ }
47+ }
48+ val biggest = basinSizes.apply {
49+ sort()
50+ reverse()
51+ }.take(3 )
52+ return biggest[0 ] * biggest[1 ] * biggest[2 ]
53+ }
2754
2855 // test if implementation meets criteria from the description, like:
2956 val testInput = parseInput(readInput(day = DAY , useTestInput = true ))
3057 check(part1(testInput) == 15 )
31- // check(part2(testInput) == 61229 )
58+ check(part2(testInput) == 1134 )
3259
3360 val input = parseInput(readInput(day = DAY ))
3461 println (part1(input))
3562 println (part2(input))
3663}
3764
38- private fun parseInput (input : List <String >): List <List <Byte >> {
65+ private fun getBasinSize (input : List <List <Point >>, x : Int , y : Int ): Int {
66+ var sum = 0
67+ val currentHeight = input[x][y].height
68+ if (x > 0 && currentHeight < input[x- 1 ][y].height && input[x- 1 ][y].height != 9 .toByte() && ! input[x- 1 ][y].marked) {
69+ input[x- 1 ][y].marked = true
70+ sum + = getBasinSize(input, x - 1 , y) + 1
71+ }
72+ if (y > 0 && currentHeight < input[x][y- 1 ].height && input[x][y- 1 ].height != 9 .toByte() && ! input[x][y- 1 ].marked) {
73+ input[x][y- 1 ].marked = true
74+ sum + = getBasinSize(input, x, y - 1 ) + 1
75+ }
76+ if (x < input.size - 1 && currentHeight < input[x+ 1 ][y].height && input[x+ 1 ][y].height != 9 .toByte() && ! input[x+ 1 ][y].marked) {
77+ input[x+ 1 ][y].marked = true
78+ sum + = getBasinSize(input, x + 1 , y) + 1
79+ }
80+ if (y < input[0 ].size - 1 && currentHeight < input[x][y+ 1 ].height && input[x][y+ 1 ].height != 9 .toByte() && ! input[x][y+ 1 ].marked) {
81+ input[x][y+ 1 ].marked = true
82+ sum + = getBasinSize(input, x, y + 1 ) + 1
83+ }
84+ return sum
85+ }
86+
87+ private fun parseInput (input : List <String >): List <List <Point >> {
3988 return input.map {
4089 it.map {
41- it.toString().toByte()
90+ Point ( it.toString().toByte() )
4291 }
4392 }
44- }
93+ }
94+
95+ private class Point (val height : Byte , var marked : Boolean = false )
0 commit comments