package common import ( "bufio" "strconv" ) type Direction int const ( Right Direction = iota Left Down Up ) type Movement struct { direction Direction distance int } type Position struct { x int y int } func NewPosition(x int, y int) *Position { return &Position{x, y} } type Grid struct { rope []Position head *Position tail *Position } func NewGrid(size int) *Grid { rope := make([]Position, size) return &Grid{rope, &rope[0], &rope[size-1]} } func (grid *Grid) Move(movement Movement) (map[Position]struct{}) { visitedTail := make(map[Position]struct{}) visitedTail[*grid.tail] = struct{}{} for i := 0; i < movement.distance; i++ { switch movement.direction { case Right: grid.head.x++ case Left: grid.head.x-- case Up: grid.head.y-- case Down: grid.head.y++ } grid.Update() visitedTail[*grid.tail] = struct{}{} } return visitedTail } func (grid *Grid) Update() { for i := 1; i < len(grid.rope); i++ { head := &(grid.rope[i-1]) tail := &(grid.rope[i]) if tail.x < head.x - 1 || tail.x > head.x + 1 || tail.y < head.y - 1 || tail.y > head.y + 1 { if tail.x == head.x { tail.y = (tail.y + head.y) / 2 } else if tail.y == head.y { tail.x = (tail.x + head.x) / 2 } else if tail.x == head.x - 1 || tail.x == head.x + 1 { tail.x = head.x tail.y = (tail.y + head.y) / 2 } else if tail.y == head.y - 1 || tail.y == head.y + 1 { tail.x = (tail.x + head.x) / 2 tail.y = head.y } else { tail.x = (tail.x + head.x) / 2 tail.y = (tail.y + head.y) / 2 } } } } func Parse(scanner bufio.Scanner) []Movement { movements := []Movement{} for scanner.Scan() { line := scanner.Text() var movement Movement distance, _ := strconv.Atoi(line[2:]) switch line[0] { case 'L': movement = Movement{Left, distance} case 'R': movement = Movement{Right, distance} case 'U': movement = Movement{Up, distance} case 'D': movement = Movement{Down, distance} } movements = append(movements, movement) } return movements }