🌅
This commit is contained in:
153
solutions/day9/day9.go
Normal file
153
solutions/day9/day9.go
Normal file
@@ -0,0 +1,153 @@
|
||||
package day9
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"os"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
type Point struct {
|
||||
x int
|
||||
y int
|
||||
}
|
||||
|
||||
func makeSnake(length int) []*Point {
|
||||
snake := []*Point{}
|
||||
|
||||
for i := 0; i < length; i++ {
|
||||
snake = append(snake, &Point{0, 0})
|
||||
}
|
||||
|
||||
return snake
|
||||
}
|
||||
|
||||
func move(direction rune, point *Point) {
|
||||
switch direction {
|
||||
case 'U':
|
||||
point.y -= 1
|
||||
case 'R':
|
||||
point.x += 1
|
||||
case 'D':
|
||||
point.y += 1
|
||||
case 'L':
|
||||
point.x -= 1
|
||||
default:
|
||||
fmt.Println("PANIC! Bad direction", string(direction))
|
||||
}
|
||||
}
|
||||
|
||||
func abs(x int) int {
|
||||
if x >= 0 {
|
||||
return x
|
||||
} else {
|
||||
return -x
|
||||
}
|
||||
}
|
||||
|
||||
func areTouching(head *Point, tail *Point) bool {
|
||||
return abs(head.x-tail.x) <= 1 && abs(head.y-tail.y) <= 1
|
||||
}
|
||||
|
||||
func updateTail(head *Point, tail *Point) {
|
||||
if areTouching(head, tail) {
|
||||
return
|
||||
}
|
||||
|
||||
if head.x == tail.x {
|
||||
if head.y <= tail.y-2 {
|
||||
tail.y -= 1
|
||||
return
|
||||
}
|
||||
|
||||
if head.y >= tail.y+2 {
|
||||
tail.y += 1
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if head.y == tail.y {
|
||||
if head.x <= tail.x-2 {
|
||||
tail.x -= 1
|
||||
return
|
||||
}
|
||||
if head.x >= tail.x+2 {
|
||||
tail.x += 1
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
proposedTails := []Point{
|
||||
{tail.x - 1, tail.y - 1},
|
||||
{tail.x - 1, tail.y + 1},
|
||||
{tail.x + 1, tail.y - 1},
|
||||
{tail.x + 1, tail.y + 1}}
|
||||
|
||||
for _, proposed := range proposedTails {
|
||||
if areTouching(head, &proposed) {
|
||||
tail.x = proposed.x
|
||||
tail.y = proposed.y
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
fmt.Println("PANIC, couldn't figure out next step for", *head, "and", *tail)
|
||||
}
|
||||
|
||||
func contains(array *[]Point, point Point) bool {
|
||||
for _, val := range *array {
|
||||
if val == point {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func runMove(direction rune, amount int, snake []*Point, visitedPoints *[]Point) {
|
||||
for i := 0; i < amount; i++ {
|
||||
move(direction, snake[0])
|
||||
for t := 1; t < len(snake); t++ {
|
||||
updateTail(snake[t-1], snake[t])
|
||||
}
|
||||
lastPoint := snake[len(snake)-1]
|
||||
if !contains(visitedPoints, *lastPoint) {
|
||||
*visitedPoints = append(*visitedPoints, *lastPoint)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func Run(filename string, lengthStr string) {
|
||||
file, err := os.Open(filename)
|
||||
if err != nil {
|
||||
fmt.Println("Error opening file:", err)
|
||||
return
|
||||
}
|
||||
|
||||
snakeLength, err := strconv.Atoi(lengthStr)
|
||||
if err != nil {
|
||||
fmt.Println("Error parsing snake length:", err)
|
||||
return
|
||||
}
|
||||
|
||||
scanner := bufio.NewScanner(file)
|
||||
scanner.Split(bufio.ScanLines)
|
||||
|
||||
snake := makeSnake(snakeLength)
|
||||
visitedPoints := []Point{}
|
||||
|
||||
for scanner.Scan() {
|
||||
line := scanner.Text()
|
||||
|
||||
amount, err := strconv.Atoi(line[2:])
|
||||
if err != nil {
|
||||
fmt.Println("Could not parse argument", line)
|
||||
return
|
||||
}
|
||||
|
||||
runMove(rune(line[0]), amount, snake, &visitedPoints)
|
||||
}
|
||||
|
||||
fmt.Println("The tail visited", len(visitedPoints), "points")
|
||||
|
||||
file.Close()
|
||||
}
|
||||
Reference in New Issue
Block a user