142 lines
3.5 KiB
Go
142 lines
3.5 KiB
Go
package main
|
|
|
|
import (
|
|
"AoC2020/helper"
|
|
"fmt"
|
|
"os"
|
|
"strconv"
|
|
)
|
|
|
|
var Pointing rune
|
|
|
|
func main() {
|
|
args := os.Args[1:]
|
|
input, err := helper.GetInput(args[0])
|
|
if err != nil {
|
|
fmt.Println(err)
|
|
}
|
|
fmt.Printf("%v",input)
|
|
runPart2(input)
|
|
}
|
|
|
|
func run(input []string) {
|
|
Pointing = 'E'
|
|
position := [2]int{0,0}
|
|
for _, val := range input {
|
|
fmt.Println(val)
|
|
position = move(position,val)
|
|
fmt.Printf("Positon %v, Direction %v \n", position, string(Pointing))
|
|
}
|
|
}
|
|
|
|
func runPart2(input []string) {
|
|
positionBoat := [2]int{0,0}
|
|
positionWayPoint := [2]int{10,1}
|
|
for _, val := range input {
|
|
fmt.Println(val)
|
|
positionBoat, positionWayPoint = movePart2(positionBoat,positionWayPoint,val)
|
|
fmt.Printf("PositonBoat: %v, PositionWaypoint %v \n", positionBoat, positionWayPoint)
|
|
}
|
|
}
|
|
|
|
func move(position [2]int, command string) [2]int{
|
|
direction := rune(command[0])
|
|
distance, _ := strconv.Atoi(command[1:])
|
|
if direction == 'L' || direction == 'R' {
|
|
Pointing = turnByDegree(Pointing,direction,distance)
|
|
return position
|
|
}
|
|
if direction == 'F'{
|
|
newCommand := string(Pointing) + command[1:]
|
|
return move(position,newCommand)
|
|
}
|
|
return moveCompass(position,direction,distance)
|
|
}
|
|
|
|
func movePart2(positionBoat [2]int, positionWayPoint [2]int, command string) ([2]int, [2]int){
|
|
direction := rune(command[0])
|
|
if direction == 'F'{
|
|
distance, _ := strconv.Atoi(command[1:])
|
|
var newPositionBoat [2]int
|
|
newPositionBoat[0] = positionBoat[0] + distance * positionWayPoint[0]
|
|
newPositionBoat[1] = positionBoat[1] + distance * positionWayPoint[1]
|
|
positionBoat = newPositionBoat
|
|
}else {
|
|
newPositionWaypoint := moveWayPoint(positionWayPoint,command)
|
|
positionWayPoint = newPositionWaypoint
|
|
}
|
|
return positionBoat, positionWayPoint
|
|
}
|
|
|
|
func moveCompass(position [2]int, direction rune, distance int) [2]int {
|
|
switch direction {
|
|
case 'N':return [2]int{position[0], position[1] + distance}
|
|
case 'S':return [2]int{position[0], position[1] - distance}
|
|
case 'E':return [2]int{position[0] + distance, position[1]}
|
|
case 'W':return [2]int{position[0] - distance, position[1]}
|
|
}
|
|
return position
|
|
}
|
|
|
|
func moveWayPoint(position [2]int, command string) [2]int {
|
|
direction := rune(command[0])
|
|
distance, _ := strconv.Atoi(command[1:])
|
|
if direction == 'L' || direction == 'R' {
|
|
return turnWayPoint(position,direction,distance)
|
|
}
|
|
return moveCompass(position,direction,distance)
|
|
}
|
|
|
|
func turnWayPoint(position [2]int,turn rune, degree int) [2]int {
|
|
p0 := position[0]
|
|
p1 := position[1]
|
|
var newDs = make([]rune,2)
|
|
if p0 > 0 {
|
|
newDs[0] = turnByDegree('E', turn, degree)
|
|
}else {
|
|
newDs[0] = turnByDegree('W', turn, degree)
|
|
}
|
|
|
|
if p1 > 0 {
|
|
newDs[1] = turnByDegree('N', turn, degree)
|
|
}else {
|
|
newDs[1] = turnByDegree('S', turn, degree)
|
|
}
|
|
var newPosition [2]int
|
|
|
|
for i,val := range newDs {
|
|
switch val {
|
|
case 'N': newPosition[1] = Abs(position[i])
|
|
case 'S': newPosition[1] = -Abs(position[i])
|
|
case 'E': newPosition[0] = Abs(position[i])
|
|
case 'W': newPosition[0] = -Abs(position[i])
|
|
}
|
|
}
|
|
return newPosition
|
|
}
|
|
|
|
func turnByDegree(pointing rune, turn rune, degree int) rune {
|
|
directions := []rune{'N','E','S','W'}
|
|
move := degree / 90
|
|
if turn == 'L' {
|
|
move = -1 * move
|
|
}
|
|
for i, val := range directions {
|
|
if val == pointing {
|
|
newDirectionPointer := (i + move) % len(directions)
|
|
if newDirectionPointer < 0 {
|
|
newDirectionPointer = len(directions) + newDirectionPointer
|
|
}
|
|
return directions[newDirectionPointer]
|
|
}
|
|
}
|
|
return pointing
|
|
}
|
|
|
|
func Abs(x int) int {
|
|
if x < 0 {
|
|
return -x
|
|
}
|
|
return x
|
|
}
|