AdventOfCode2020/12/main.go

198 lines
3.5 KiB
Go

package main
import (
"bufio"
"fmt"
"os"
"strconv"
"time"
)
func main() {
start := time.Now()
partOne()
duration := time.Since(start)
partTwo()
duration2 := time.Since(start)
fmt.Printf("p1: %s, p2: %s\n", duration, duration2-duration)
}
type ship struct {
horizontal int
vertical int
direction rune // E W N S
}
// both horizontal/vertical are relative to ship
type waypoint struct {
horizontal int
vertical int
}
func parseLine(s string) (rune, int) {
i, _ := strconv.Atoi(s[1:])
return []rune(s)[0], i
}
func movePartOne(s ship, action rune, vector int) ship {
switch action {
case 'R', 'L':
s.direction = rotateShip(s.direction, vector, action)
case 'N':
s.vertical = s.vertical + vector
case 'S':
s.vertical = s.vertical - vector
case 'E':
s.horizontal = s.horizontal + vector
case 'W':
s.horizontal = s.horizontal - vector
case 'F':
s = movePartOne(s, s.direction, vector)
}
return s
}
func movePartTwo(s ship, w waypoint, action rune, vector int) (ship, waypoint) {
switch action {
case 'R', 'L':
w = rotateWaypoint(w, action, vector)
case 'N':
w.vertical = w.vertical + vector
case 'S':
w.vertical = w.vertical - vector
case 'E':
w.horizontal = w.horizontal + vector
case 'W':
w.horizontal = w.horizontal - vector
case 'F':
s.horizontal = s.horizontal + (w.horizontal * vector)
s.vertical = s.vertical + (w.vertical * vector)
}
return s, w
}
// for example E, 90, L => N; E, 180, R => W; E, 90, R => S
func rotateShip(current rune, degrees int, rl rune) rune {
// easy
if degrees == 180 {
switch current {
case 'N':
return 'S'
case 'S':
return 'N'
case 'E':
return 'W'
case 'W':
return 'E'
}
}
// translate L to R
if rl == 'L' {
if degrees == 90 {
degrees = 270
} else {
degrees = 90
}
}
// the R set
if degrees == 90 {
switch current {
case 'N':
return 'E'
case 'S':
return 'W'
case 'E':
return 'S'
case 'W':
return 'N'
}
} else if degrees == 270 {
switch current {
case 'N':
return 'W'
case 'S':
return 'E'
case 'E':
return 'N'
case 'W':
return 'S'
}
}
return current // we're made a terrible mistake somewhere
}
func rotateWaypoint(w waypoint, action rune, vector int) waypoint {
if vector == 180 {
w.horizontal, w.vertical = -w.horizontal, -w.vertical
} else if action == 'R' {
if vector == 90 {
w.horizontal, w.vertical = w.vertical, -w.horizontal
}
if vector == 270 {
w.horizontal, w.vertical = -w.vertical, w.horizontal
}
} else if action == 'L' {
if vector == 90 {
w.horizontal, w.vertical = -w.vertical, w.horizontal
}
if vector == 270 {
w.horizontal, w.vertical = w.vertical, -w.horizontal
}
}
return w
}
func manhattan(i, j int) int {
return abs(i) + abs(j)
}
func abs(x int) int {
if x < 0 {
return -x
}
return x
}
func partOne() {
f, _ := os.Open("input")
reader := bufio.NewReader(f)
scanner := bufio.NewScanner(reader)
s := ship{
horizontal: 0,
vertical: 0,
direction: 'E',
}
for scanner.Scan() {
dir, vec := parseLine(scanner.Text())
s = movePartOne(s, dir, vec)
}
fmt.Println(manhattan(s.horizontal, s.vertical))
}
func partTwo() {
f, _ := os.Open("input")
reader := bufio.NewReader(f)
scanner := bufio.NewScanner(reader)
s := ship{
horizontal: 0,
vertical: 0,
// no longer care about ship direction
}
w := waypoint{
horizontal: 10,
vertical: 1,
}
for scanner.Scan() {
dir, vec := parseLine(scanner.Text())
s, w = movePartTwo(s, w, dir, vec)
}
fmt.Println(manhattan(s.horizontal, s.vertical))
}