-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathDay12.kt
102 lines (86 loc) · 3.82 KB
/
Day12.kt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
package aoc.years.year2022
import aoc.Day
@Year2022
class Day12 : Day() {
override fun solvePart1(input: List<String>): Any {
val hill = input.map { it.toCharArray() }
return hill.findPosition('S')
.map { startingPosition -> hill.stepsToEnd(startingPosition) }
.first()
}
override fun solvePart2(input: List<String>): Any {
val hill = input.map { it.toCharArray() }
return hill.findPosition('a')
.minOf { startingPosition -> hill.stepsToEnd(startingPosition) }
}
}
private fun List<CharArray>.findPosition(startingPositionSymbol: Char): List<Pair<Int, Int>> {
return this
.indices
.map { row ->
this.first().indices
.filter { column -> this[row][column] == startingPositionSymbol }
.map { column -> Pair(row, column) }
}
.flatten()
}
private fun List<CharArray>.stepsToEnd(startingPosition: Pair<Int, Int>): Int {
val visited = this.indices
.map {
this.first().indices
.map { Pair(false, Integer.MAX_VALUE) }
.toMutableList()
}
val nextSquares = mutableListOf(startingPosition)
visited[startingPosition.first][startingPosition.second] = Pair(false, 0)
while (nextSquares.isNotEmpty()) {
val currentSquarePos = nextSquares.removeFirst()
val (currentSquareVisited, currentSquareDistance) = visited[currentSquarePos.first][currentSquarePos.second]
if (!currentSquareVisited) {
visited[currentSquarePos.first][currentSquarePos.second] = Pair(true, currentSquareDistance)
if (currentSquarePos.first - 1 >= 0) {
val nextSquare = Pair(currentSquarePos.first - 1, currentSquarePos.second)
visitSquare(currentSquarePos, currentSquareDistance, nextSquare, nextSquares, visited)
}
if (currentSquarePos.first + 1 < this.size) {
val nextSquare = Pair(currentSquarePos.first + 1, currentSquarePos.second)
visitSquare(currentSquarePos, currentSquareDistance, nextSquare, nextSquares, visited)
}
if (currentSquarePos.second - 1 >= 0) {
val nextSquare = Pair(currentSquarePos.first, currentSquarePos.second - 1)
visitSquare(currentSquarePos, currentSquareDistance, nextSquare, nextSquares, visited)
}
if (currentSquarePos.second + 1 < this.first().size) {
val nextSquare = Pair(currentSquarePos.first, currentSquarePos.second + 1)
visitSquare(currentSquarePos, currentSquareDistance, nextSquare, nextSquares, visited)
}
}
}
val endPosition = findPosition('E').first()
return visited[endPosition.first][endPosition.second].second
}
private fun List<CharArray>.visitSquare(
currentSquarePos: Pair<Int, Int>,
currentSquareDistance: Int,
nextSquarePos: Pair<Int, Int>,
nextSquares: MutableList<Pair<Int, Int>>,
visited: List<MutableList<Pair<Boolean, Int>>>
) {
if (atMostOneStepHigher(currentSquarePos, nextSquarePos)) {
nextSquares.add(nextSquarePos)
val nextSquare = visited[nextSquarePos.first][nextSquarePos.second]
val distanceToNextSquare = nextSquare.second
if (currentSquareDistance + 1 < distanceToNextSquare) {
visited[nextSquarePos.first][nextSquarePos.second] = Pair(nextSquare.first, currentSquareDistance + 1)
}
}
}
private fun List<CharArray>.atMostOneStepHigher(current: Pair<Int, Int>, next: Pair<Int, Int>): Boolean {
return if (this[current.first][current.second] == 'S') {
this[next.first][next.second] == 'a'
} else if (this[next.first][next.second] == 'E') {
true
} else {
this[next.first][next.second].minus(this[current.first][current.second]) <= 1
}
}