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") } }