Files
adventofcode/2022/go/day09/day09.go
2023-11-16 10:48:53 +00:00

119 lines
2.3 KiB
Go

package day09
import (
"strings"
"adventofcode2022/utils"
sparsegrid "adventofcode2022/utils/sparseGrid"
)
type rope struct {
size int
posX []int
posY []int
}
func Part1(input string) int {
rope := newRope(2)
grid := sparsegrid.NewGrid(false)
grid.Set(rope.posX[rope.size-1], rope.posY[rope.size-1], true)
for _, line := range strings.Split(input, "\n") {
dx := 0
dy := 0
switch line[0] {
case 'R':
dx = 1
case 'U':
dy = -1
case 'D':
dy = 1
case 'L':
dx = -1
}
n := utils.MustAtoi(line[2:])
for i := 0; i < n; i++ {
// move head
rope.posX[0] += dx
rope.posY[0] += dy
// update tail
rope.updateTail()
grid.Set(rope.posX[rope.size-1], rope.posY[rope.size-1], true)
}
}
return grid.Visited()
}
func Part2(input string) int {
rope := newRope(10)
grid := sparsegrid.NewGrid(false)
grid.Set(rope.posX[rope.size-1], rope.posY[rope.size-1], true)
for _, line := range strings.Split(input, "\n") {
dx := 0
dy := 0
switch line[0] {
case 'R':
dx = 1
case 'U':
dy = -1
case 'D':
dy = 1
case 'L':
dx = -1
}
n := utils.MustAtoi(line[2:])
for i := 0; i < n; i++ {
// move head
rope.posX[0] += dx
rope.posY[0] += dy
// update tail
rope.updateTail()
grid.Set(rope.posX[rope.size-1], rope.posY[rope.size-1], true)
}
}
return grid.Visited()
}
func newRope(size int) *rope {
return &rope{
size: size,
posX: make([]int, size),
posY: make([]int, size),
}
}
func (r *rope) updateTail() {
outer:
for i := 1; i < r.size; i++ {
diffX := utils.Abs(r.posX[i-1] - r.posX[i])
diffY := utils.Abs(r.posY[i-1] - r.posY[i])
if diffX <= 1 && diffY <= 1 {
// no need to update node if it's touching
continue
}
moves := [][]int{{1, 0}, {-1, 0}, {0, 1}, {0, -1}}
for _, move := range moves {
t := utils.Max(
utils.Abs(r.posX[i-1]-r.posX[i]+move[0]),
utils.Abs(r.posY[i-1]-r.posY[i]+move[1]))
if t == 1 {
r.posX[i] = r.posX[i-1] + move[0]
r.posY[i] = r.posY[i-1] + move[1]
continue outer
}
}
moves = [][]int{{1, 1}, {-1, 1}, {1, -1}, {-1, -1}}
for _, move := range moves {
t := utils.Max(
utils.Abs(r.posX[i-1]-r.posX[i]+move[0]),
utils.Abs(r.posY[i-1]-r.posY[i]+move[1]))
if t == 1 {
r.posX[i] = r.posX[i-1] + move[0]
r.posY[i] = r.posY[i-1] + move[1]
continue outer
}
}
panic("unreachable")
}
}