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 }