-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathDay12.kt
106 lines (89 loc) · 3.66 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
103
104
105
106
package day12
import java.io.File
import kotlin.math.*
fun main() {
part1()
part2()
}
fun getInstructionFromFileInput(): List<Pair<Char, Long>> =
File("src/main/resources/day12_input.txt").readLines()
.map { it[0] to it.substring(1).toLong() }
const val EAST: Long = 0L
const val SOUTH: Long = 90L
const val WEST: Long = 180L
const val NORTH: Long = 270L
operator fun Pair<Long, Long>.plus(pos: Pair<Long, Long>) = first+pos.first to second+pos.second
operator fun Pair<Long, Long>.times(scale: Long) = first*scale to second*scale
fun Pair<Long, Long>.distanceAndAngleToCoordinates(): Pair<Long, Long> =
when(this.second) {
NORTH -> this.first to 0L
SOUTH -> -this.first to 0L
EAST -> 0L to this.first
WEST -> 0L to -this.first
else -> error("Does not support anything other than cardinal directions: ${this.second}")
}
fun part1() {
NavigationState().apply {
getInstructionFromFileInput().forEach {
when(it.first) {
'N' -> moveShipByDistanceAndAngle(it.second, NORTH)
'E' -> moveShipByDistanceAndAngle(it.second, EAST)
'S' -> moveShipByDistanceAndAngle(it.second, SOUTH)
'W' -> moveShipByDistanceAndAngle(it.second, WEST)
'L' -> turnShip(-it.second)
'R' -> turnShip(it.second)
'F' -> moveShipInCurrentDirection(it.second)
else -> error("Unsupported operation: $it")
}
}
println(manhattanDistance())
}
}
fun part2() {
NavigationState().apply {
getInstructionFromFileInput().forEach {
when(it.first) {
'N' -> moveWaypointInDirection(it.second, NORTH)
'E' -> moveWaypointInDirection(it.second, EAST)
'S' -> moveWaypointInDirection(it.second, SOUTH)
'W' -> moveWaypointInDirection(it.second, WEST)
'L' -> rotateWaypointAroundShip(-it.second)
'R' -> rotateWaypointAroundShip(it.second)
'F' -> moveShipTowardWaypoint(it.second)
else -> error("Unsupported operation: $it")
}
}
println(manhattanDistance())
}
}
class NavigationState(
private var shipDirection: Long = 0, //in degrees, 0 is due East
private var shipPosition: Pair<Long, Long> = 0L to 0L, //north to East
private var waypointPosition: Pair<Long, Long> = 1L to 10L
) {
fun moveShipByDistanceAndAngle(distance: Long, degrees: Long) {
shipPosition += (distance to degrees).distanceAndAngleToCoordinates()
}
fun moveShipInCurrentDirection(distance: Long) =
moveShipByDistanceAndAngle(distance, shipDirection)
fun turnShip(degrees: Long) {
shipDirection = Math.floorMod(shipDirection + degrees, 360L)
}
fun moveWaypointInDirection(distance: Long, degrees: Long) {
waypointPosition += (distance to degrees).distanceAndAngleToCoordinates()
}
fun moveShipTowardWaypoint(scale: Long) {
shipPosition += waypointPosition*scale
}
fun rotateWaypointAroundShip(degrees: Long) {
waypointPosition = when(Math.floorMod(degrees, 360)) {
0L -> waypointPosition
90L -> -waypointPosition.second to waypointPosition.first
180L -> -waypointPosition.first to -waypointPosition.second
270L -> waypointPosition.second to -waypointPosition.first
else -> error("Does not support anything other than cardinal directions: $degrees")
}
}
fun manhattanDistance(): Long =
abs(shipPosition.first) + abs(shipPosition.second)
}