2019-12-16 23:31:11 +00:00
|
|
|
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
|
2019-12-18 13:25:25 +00:00
|
|
|
|
|
|
|
bfs map[*helpers.Coordinate]*BFSNode
|
|
|
|
|
|
|
|
startCoord *helpers.Coordinate
|
|
|
|
o2Coord *helpers.Coordinate
|
2019-12-16 23:31:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func NewMaze() *Maze {
|
|
|
|
m := &Maze{
|
2019-12-18 13:25:25 +00:00
|
|
|
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),
|
2019-12-16 23:31:11 +00:00
|
|
|
}
|
|
|
|
m.path = append(m.path, helpers.NewCoordinate(0, 0))
|
|
|
|
return m
|
|
|
|
}
|
|
|
|
|
|
|
|
func (m *Maze) SetCoord(c *helpers.Coordinate, val int) {
|
2019-12-18 13:25:25 +00:00
|
|
|
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
|
|
|
|
}
|
2019-12-16 23:31:11 +00:00
|
|
|
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()
|
|
|
|
}
|
|
|
|
}
|
2019-12-18 13:25:25 +00:00
|
|
|
|
|
|
|
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
|
|
|
|
}
|