Files
advent-of-code-go/2020/day12/main.go
T

137 lines
2.8 KiB
Go

package main
import (
"flag"
"fmt"
"strings"
"github.com/alexchao26/advent-of-code-go/cast"
"github.com/alexchao26/advent-of-code-go/mathy"
"github.com/alexchao26/advent-of-code-go/util"
)
func main() {
var part int
flag.IntVar(&part, "part", 1, "part 1 or 2")
flag.Parse()
fmt.Println("Running part", part)
if part == 1 {
ans := part1(util.ReadFile("./input.txt"))
fmt.Println("Output:", ans)
} else {
ans := part2(util.ReadFile("./input.txt"))
fmt.Println("Output:", ans)
}
}
// globals for part 1
var directions = []string{"N", "E", "S", "W"}
var directionsToDiff = map[string][2]int{
// !! X and Y like a coordinate system! Not typical 2D matrices in algos
"N": [2]int{0, 1},
"E": [2]int{1, 0},
"S": [2]int{0, -1},
"W": [2]int{-1, 0},
}
func part1(input string) int {
instructions := parseInput(input)
// X and Y like a coordinate system
var shipX, shipY int
dirIndex := 1 // index in directions slice
for _, inst := range instructions {
switch inst.action {
case "N":
shipY += inst.value
case "S":
shipY -= inst.value
case "E":
shipX += inst.value
case "W":
shipX -= inst.value
case "L":
// rotate ship left, this is equivalent
// -1 + 4 to keeping dirIndex positive for the modding
dirIndex += (-1 + 4) * inst.value / 90
dirIndex %= 4
case "R":
dirIndex += inst.value / 90
dirIndex %= 4
case "F":
d := directionsToDiff[directions[dirIndex]]
shipX += d[0] * inst.value
shipY += d[1] * inst.value
default:
panic("unexpected action")
}
}
return mathy.ManhattanDistance(0, 0, shipX, shipY)
}
func part2(input string) int {
instructions := parseInput(input)
// X and Y like a coordinate system
waypointX := 10
waypointY := 1
var shipX, shipY int
for _, inst := range instructions {
switch inst.action {
case "N":
waypointY += inst.value
case "S":
waypointY -= inst.value
case "E":
waypointX += inst.value
case "W":
waypointX -= inst.value
case "L":
// rotate waypoint left around ship (origin)
turns := inst.value / 90
for turns > 0 {
// this simple bit is all it needs to rotate around the origin
// I had a 20 line if/else block...
waypointX, waypointY = -waypointY, waypointX
turns--
}
case "R":
turns := inst.value / 90
for turns > 0 {
waypointX, waypointY = waypointY, -waypointX
turns--
}
case "F":
shipX += inst.value * waypointX
shipY += inst.value * waypointY
default:
panic("unexpected action")
}
}
return mathy.ManhattanDistance(0, 0, shipX, shipY)
}
type instruction struct {
action string
value int
}
func parseInput(input string) []instruction {
var ans []instruction
lines := strings.Split(input, "\n")
for _, l := range lines {
inst := instruction{
action: l[:1],
value: cast.ToInt(l[1:]),
}
ans = append(ans, inst)
}
return ans
}