-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathDay12RainRisk.kt
More file actions
122 lines (108 loc) · 4.95 KB
/
Day12RainRisk.kt
File metadata and controls
122 lines (108 loc) · 4.95 KB
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
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
package adventofcode.year2020
import adventofcode.Puzzle
import adventofcode.PuzzleInput
import adventofcode.year2020.Day12RainRisk.Companion.Action.EAST
import adventofcode.year2020.Day12RainRisk.Companion.Action.FORWARD
import adventofcode.year2020.Day12RainRisk.Companion.Action.LEFT
import adventofcode.year2020.Day12RainRisk.Companion.Action.NORTH
import adventofcode.year2020.Day12RainRisk.Companion.Action.RIGHT
import adventofcode.year2020.Day12RainRisk.Companion.Action.SOUTH
import adventofcode.year2020.Day12RainRisk.Companion.Action.WEST
import kotlin.math.absoluteValue
class Day12RainRisk(
customInput: PuzzleInput? = null,
) : Puzzle(customInput) {
private val navigationInstructions by lazy { input.lines().map(::NavigationInstruction) }
override fun partOne() =
navigationInstructions
.fold(NavigationDirection.EAST to Pair(0, 0)) { (direction, position), instruction ->
when (instruction.action) {
EAST -> direction to position.copy(first = position.first + instruction.value)
WEST -> direction to position.copy(first = position.first - instruction.value)
NORTH -> direction to position.copy(second = position.second + instruction.value)
SOUTH -> direction to position.copy(second = position.second - instruction.value)
FORWARD ->
when (direction) {
NavigationDirection.EAST -> direction to position.copy(first = position.first + instruction.value)
NavigationDirection.WEST -> direction to position.copy(first = position.first - instruction.value)
NavigationDirection.NORTH -> direction to position.copy(second = position.second + instruction.value)
NavigationDirection.SOUTH -> direction to position.copy(second = position.second - instruction.value)
}
RIGHT -> NavigationDirection(direction.heading + instruction.value) to position
LEFT -> NavigationDirection(direction.heading - instruction.value) to position
}
}.second
.toList()
.sumOf { it.absoluteValue }
override fun partTwo() =
navigationInstructions
.fold(Pair(Pair(10, 1), Pair(0, 0))) { acc, instruction ->
val value = instruction.value
val waypoint = acc.first
val position = acc.second
when (instruction.action) {
EAST -> acc.copy(first = waypoint.copy(first = waypoint.first + value))
WEST -> acc.copy(first = waypoint.copy(first = waypoint.first - value))
NORTH -> acc.copy(first = waypoint.copy(second = waypoint.second + value))
SOUTH -> acc.copy(first = waypoint.copy(second = waypoint.second - value))
FORWARD -> acc.copy(second = Pair(position.first + value * waypoint.first, position.second + value * waypoint.second))
RIGHT -> {
var wx = waypoint.first
var wy = waypoint.second
repeat(value / 90) {
val oldwx = wx
wx = wy
wy = -oldwx
}
acc.copy(first = Pair(wx, wy))
}
LEFT -> {
var wx = waypoint.first
var wy = waypoint.second
repeat(value / 90) {
val oldwx = wx
wx = -wy
wy = oldwx
}
acc.copy(first = Pair(wx, wy))
}
}
}.second
.toList()
.sumOf { it.absoluteValue }
companion object {
private enum class NavigationDirection(
val heading: Int,
) {
EAST(0),
SOUTH(90),
WEST(180),
NORTH(270),
;
companion object {
operator fun invoke(heading: Int) = entries.associateBy(NavigationDirection::heading)[Math.floorMod(heading, 360)]!!
}
}
private enum class Action(
val action: String,
) {
NORTH("N"),
SOUTH("S"),
EAST("E"),
WEST("W"),
LEFT("L"),
RIGHT("R"),
FORWARD("F"),
;
companion object {
operator fun invoke(action: String) = entries.associateBy(Action::action)[action]!!
}
}
private data class NavigationInstruction(
val action: Action,
val value: Int,
) {
constructor(action: String) : this(Action(action.substring(0, 1)), action.substring(1).toInt())
}
}
}