117 lines
2.2 KiB
Go
117 lines
2.2 KiB
Go
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
|
|
}
|