adventofcode/2019/day17/walk.go

176 lines
2.8 KiB
Go

package main
import (
"fmt"
"time"
helpers "git.bullercodeworks.com/brian/adventofcode/helpers"
)
const (
DIR_N = '^'
DIR_E = '>'
DIR_S = 'v'
DIR_W = '<'
)
func walk() {
bot := NewBot(layout)
for {
x, y := bot.GetNextSpot()
if bot.CanMove() && !bot.LastCoordWas(x, y) {
bot.Move()
} else {
bot.TurnLeft()
if bot.turns == 4 {
break
}
}
fmt.Print(helpers.CLEAR_SCREEN)
fmt.Println(bot.pathCoords)
bot.PrintLayout()
time.Sleep(time.Second / 10)
}
fmt.Println(bot.path)
}
type Bot struct {
X, Y int
Dir byte
layout [][]byte
path string
pathCoords []*helpers.Coordinate
turns int
moves int
}
func NewBot(layout [][]byte) *Bot {
b := &Bot{layout: layout}
// Find the bot
for y := range b.layout {
for x := range b.layout[y] {
if isBot(b.layout[y][x]) {
b.X = x
b.Y = y
b.Dir = b.layout[y][x]
b.layout[y][x] = '#'
}
}
}
return b
}
func (b *Bot) Visited(x, y int) bool {
for _, v := range b.pathCoords {
if v.X == x && v.Y == y {
return true
}
}
return false
}
func (b *Bot) LastCoordWas(x, y int) bool {
if len(b.pathCoords) == 0 {
return false
}
c := b.pathCoords[len(b.pathCoords)-1]
return c.X == x && c.Y == y
}
func (b *Bot) Move() bool {
if !b.CanMove() {
return false
}
b.pathCoords = append(b.pathCoords, helpers.NewCoordinate(b.X, b.Y))
b.X, b.Y = b.GetNextSpot()
if b.turns == 1 { // Left Turn
b.path = b.path + ",L"
} else if b.turns == 3 { // Right Turn
b.path = b.path + ",R"
}
b.moves++
b.turns = 0
return true
}
func (b *Bot) GetNextSpot() (int, int) {
testX, testY := b.X, b.Y
switch b.Dir {
case DIR_N:
testY--
case DIR_E:
testX++
case DIR_S:
testY++
case DIR_W:
testX--
}
return testX, testY
}
func (b *Bot) CanMove() bool {
x, y := b.GetNextSpot()
if y < 0 || y >= len(b.layout) {
return false
}
if x < 0 || x >= len(b.layout[y]) {
return false
}
return b.layout[y][x] == '#'
}
func (b *Bot) TurnLeft() {
switch b.Dir {
case DIR_N:
b.Dir = DIR_W
case DIR_E:
b.Dir = DIR_N
case DIR_S:
b.Dir = DIR_E
case DIR_W:
b.Dir = DIR_S
}
b.turns++
if b.moves > 0 {
b.path = b.path + "," + helpers.Itoa(b.moves)
b.moves = 0
}
}
func (b *Bot) TurnRight() {
switch b.Dir {
case DIR_N:
b.Dir = DIR_E
case DIR_E:
b.Dir = DIR_S
case DIR_S:
b.Dir = DIR_W
case DIR_W:
b.Dir = DIR_N
}
b.turns++
if b.moves > 0 {
b.path = b.path + "," + helpers.Itoa(b.moves)
b.moves = 0
}
}
func isBot(b byte) bool {
return b == DIR_N || b == DIR_E || b == DIR_S || b == DIR_W
}
func (b *Bot) PrintLayout() {
for y := range b.layout {
for x := range b.layout[y] {
if x == b.X && y == b.Y {
fmt.Print(string(b.Dir))
} else if b.Visited(x, y) {
fmt.Print("█")
} else {
fmt.Print(string(b.layout[y][x]))
}
}
fmt.Println()
}
}