adventofcode/2019/day15/maze.go

196 lines
3.4 KiB
Go

package main
import (
"fmt"
helpers "git.bullercodeworks.com/brian/adventofcode/helpers"
)
const (
MAZE_UNKNOWN = -1
MAZE_WALL = 0
MAZE_EMPTY = 1
MAZE_O2SYS = 2
)
const (
DIR_N = 1
DIR_S = 2
DIR_W = 3
DIR_E = 4
)
type Maze struct {
maze map[string]int
maxX, minX int
maxY, minY int
bot *helpers.Coordinate
path []*helpers.Coordinate
dirHistory []int
dnt bool
bfs map[*helpers.Coordinate]*BFSNode
startCoord *helpers.Coordinate
o2Coord *helpers.Coordinate
}
func NewMaze() *Maze {
m := &Maze{
maze: make(map[string]int),
maxX: helpers.MIN_INT,
minX: helpers.MAX_INT,
maxY: helpers.MIN_INT,
minY: helpers.MAX_INT,
bot: helpers.NewCoordinate(0, 0),
bfs: make(map[*helpers.Coordinate]*BFSNode),
startCoord: helpers.NewCoordinate(0, 0),
}
m.path = append(m.path, helpers.NewCoordinate(0, 0))
return m
}
func (m *Maze) SetCoord(c *helpers.Coordinate, val int) {
var b *BFSNode
var ok bool
if b, ok = m.bfs[c]; !ok {
b = &BFSNode{Value: val}
m.bfs[c] = b
}
// Create the BFS node for this
if n, ok := m.bfs[c.GetNorthCoord()]; ok {
n.South = b
b.North = n
}
if e, ok := m.bfs[c.GetEastCoord()]; ok {
e.West = b
b.East = e
}
if s, ok := m.bfs[c.GetSouthCoord()]; ok {
s.North = b
b.South = s
}
if w, ok := m.bfs[c.GetWestCoord()]; ok {
w.East = b
b.West = w
}
if val == 2 {
m.o2Coord = c
}
m.maze[c.String()] = val
if m.maxX < c.X {
m.maxX = c.X
}
if m.minX > c.X {
m.minX = c.X
}
if m.maxY < c.Y {
m.maxY = c.Y
}
if m.minY > c.Y {
m.minY = c.Y
}
}
func (m *Maze) GetCoord(c *helpers.Coordinate) int {
v, ok := m.maze[c.String()]
if !ok {
return MAZE_UNKNOWN
}
return v
}
func (m *Maze) GetDirFromBot(dir int) *helpers.Coordinate {
switch dir {
case DIR_N:
return m.bot.GetNorthCoord()
case DIR_E:
return m.bot.GetEastCoord()
case DIR_S:
return m.bot.GetSouthCoord()
case DIR_W:
return m.bot.GetWestCoord()
}
return nil
}
func (m *Maze) MoveBot(dir int) bool {
dest := m.GetDirFromBot(dir)
if m.GetCoord(dest) == MAZE_UNKNOWN || m.GetCoord(dest) == MAZE_WALL {
return false
}
m.bot.X, m.bot.Y = dest.X, dest.Y
if !m.dnt {
m.path = append(m.path, helpers.NewCoordinate(m.bot.X, m.bot.Y))
m.dirHistory = append(m.dirHistory, dir)
}
m.dnt = false
return true
}
func (m *Maze) GetDirectionToLast() int {
if len(m.dirHistory) == 0 {
return -1
}
m.dnt = true
var dir int
dir, m.dirHistory = m.dirHistory[len(m.dirHistory)-1], m.dirHistory[:len(m.dirHistory)-1]
switch dir {
case DIR_N:
return DIR_S
case DIR_S:
return DIR_N
case DIR_W:
return DIR_E
case DIR_E:
return DIR_W
}
return -1
}
func (m *Maze) Print() {
for y := m.minY; y <= m.maxY; y++ {
for x := m.minX; x <= m.maxX; x++ {
c := helpers.NewCoordinate(x, y)
if m.bot.Equals(*c) {
fmt.Print("%")
} else {
switch m.GetCoord(c) {
case MAZE_UNKNOWN:
fmt.Print("~")
case MAZE_WALL:
fmt.Print("#")
case MAZE_EMPTY:
fmt.Print(" ")
case MAZE_O2SYS:
fmt.Print("O")
}
}
}
fmt.Println()
}
}
type BFSNode struct {
Value int
North, East *BFSNode
South, West *BFSNode
}
func (b *BFSNode) getChildren() []*BFSNode {
var ret []*BFSNode
if b.North != nil {
ret = append(ret, b.North)
}
if b.East != nil {
ret = append(ret, b.East)
}
if b.South != nil {
ret = append(ret, b.South)
}
if b.West != nil {
ret = append(ret, b.West)
}
return ret
}