Day 18 & Day 20 done
This commit is contained in:
@@ -1,228 +1,42 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
|
||||
helpers "git.bullercodeworks.com/brian/adventofcode/helpers"
|
||||
h "git.bullercodeworks.com/brian/adventofcode/helpers"
|
||||
)
|
||||
|
||||
type MazeMap map[h.Coordinate3d]bool
|
||||
|
||||
type Maze struct {
|
||||
start *MazeCoord
|
||||
end *MazeCoord
|
||||
maze map[string]*MazeCoord
|
||||
portals map[string]*Portal
|
||||
|
||||
current *MazeCoord
|
||||
|
||||
BotX, BotY int
|
||||
TopX, TopY int
|
||||
MazeMap
|
||||
Outer Square
|
||||
Inner Square
|
||||
Portals map[h.Coordinate3d]Portal
|
||||
Start h.Coordinate3d
|
||||
End h.Coordinate3d
|
||||
}
|
||||
|
||||
func NewMaze(file string) *Maze {
|
||||
inp := helpers.FileToBytes(file)
|
||||
lines := bytes.Split(inp, []byte{'\n'})
|
||||
m := Maze{
|
||||
maze: make(map[string]*MazeCoord),
|
||||
portals: make(map[string]*Portal),
|
||||
}
|
||||
for yk, yv := range lines {
|
||||
for xk, xv := range yv {
|
||||
if xv == '.' || xv == '#' {
|
||||
m.maze[c(xk, yk)] = &MazeCoord{
|
||||
X: xk,
|
||||
Y: yk,
|
||||
Value: xv,
|
||||
steps: helpers.MAX_INT,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Now hook up neighbor coords
|
||||
for _, v := range m.maze {
|
||||
if v.X < m.BotX {
|
||||
m.BotX = v.X
|
||||
}
|
||||
if v.X > m.TopX {
|
||||
m.TopX = v.X
|
||||
}
|
||||
if v.Y < m.BotY {
|
||||
m.BotY = v.Y
|
||||
}
|
||||
if v.Y > m.TopY {
|
||||
m.TopY = v.Y
|
||||
}
|
||||
var d *MazeCoord
|
||||
var ok bool
|
||||
// Hook up north
|
||||
if d, ok = m.maze[c(v.X, v.Y-1)]; ok {
|
||||
v.N = d
|
||||
} else if v.Value == '.' {
|
||||
// North Portal
|
||||
name := string([]byte{lines[v.Y-2][v.X], lines[v.Y-1][v.X]})
|
||||
var p *Portal
|
||||
if p, ok = m.portals[name]; ok {
|
||||
v.N = m.maze[c(p.X1, p.Y1)]
|
||||
m.maze[c(p.X1, p.Y1)].S = v
|
||||
p.X2 = v.X
|
||||
p.Y2 = v.Y
|
||||
} else {
|
||||
m.portals[name] = &Portal{
|
||||
Name: name,
|
||||
X1: v.X,
|
||||
Y1: v.Y,
|
||||
}
|
||||
}
|
||||
}
|
||||
// Hook up east
|
||||
if d, ok = m.maze[c(v.X+1, v.Y)]; ok {
|
||||
v.E = d
|
||||
} else if v.Value == '.' {
|
||||
// East Portal
|
||||
name := string([]byte{lines[v.Y][v.X+1], lines[v.Y][v.X+2]})
|
||||
var p *Portal
|
||||
if p, ok = m.portals[name]; ok {
|
||||
v.E = m.maze[c(p.X1, p.Y1)]
|
||||
m.maze[c(p.X1, p.Y1)].W = v
|
||||
p.X2 = v.X
|
||||
p.Y2 = v.Y
|
||||
} else {
|
||||
m.portals[name] = &Portal{
|
||||
Name: name,
|
||||
X1: v.X,
|
||||
Y1: v.Y,
|
||||
}
|
||||
}
|
||||
}
|
||||
// Hook up south
|
||||
if d, ok = m.maze[c(v.X, v.Y+1)]; ok {
|
||||
v.S = d
|
||||
} else if v.Value == '.' {
|
||||
// South Portal
|
||||
name := string([]byte{lines[v.Y+1][v.X], lines[v.Y+2][v.X]})
|
||||
var p *Portal
|
||||
if p, ok = m.portals[name]; ok {
|
||||
v.S = m.maze[c(p.X1, p.Y1)]
|
||||
m.maze[c(p.X1, p.Y1)].N = v
|
||||
fmt.Println(v.S, "<=>", m.maze[c(p.X1, p.Y1)].N)
|
||||
p.X2 = v.X
|
||||
p.Y2 = v.Y
|
||||
} else {
|
||||
m.portals[name] = &Portal{
|
||||
Name: name,
|
||||
X1: v.X,
|
||||
Y1: v.Y,
|
||||
}
|
||||
}
|
||||
}
|
||||
// Hook up west
|
||||
if d, ok = m.maze[c(v.X-1, v.Y)]; ok {
|
||||
v.W = d
|
||||
} else if v.Value == '.' {
|
||||
// West Portal
|
||||
name := string([]byte{lines[v.Y][v.X-2], lines[v.Y][v.X-1]})
|
||||
var p *Portal
|
||||
if p, ok = m.portals[name]; ok {
|
||||
v.W = m.maze[c(p.X1, p.Y1)]
|
||||
m.maze[c(p.X1, p.Y1)].E = v
|
||||
p.X2 = v.X
|
||||
p.Y2 = v.Y
|
||||
} else {
|
||||
m.portals[name] = &Portal{
|
||||
Name: name,
|
||||
X1: v.X,
|
||||
Y1: v.Y,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
st := m.portals["AA"]
|
||||
m.current = m.maze[c(st.X1, st.Y1)]
|
||||
return &m
|
||||
}
|
||||
|
||||
func (m *Maze) MoveNorth() bool {
|
||||
if m.current.N != nil && m.current.N.Value == '.' {
|
||||
m.current = m.current.N
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (m *Maze) MoveEast() bool {
|
||||
if m.current.E != nil && m.current.E.Value == '.' {
|
||||
m.current = m.current.E
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (m *Maze) MoveSouth() bool {
|
||||
if m.current.S != nil && m.current.S.Value == '.' {
|
||||
m.current = m.current.S
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (m *Maze) MoveWest() bool {
|
||||
if m.current.W != nil && m.current.W.Value == '.' {
|
||||
m.current = m.current.W
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (m *Maze) Print() {
|
||||
for y := m.BotY; y <= m.TopY; y++ {
|
||||
for x := m.BotX; x <= m.TopX; x++ {
|
||||
if m.current.X == x && m.current.Y == y {
|
||||
fmt.Print("%")
|
||||
} else {
|
||||
if v, ok := m.maze[c(x, y)]; ok {
|
||||
fmt.Print(string(v.Value))
|
||||
func (m *Maze) Print(visited map[h.Coordinate3d]bool) {
|
||||
for y := m.Outer.Tl.Y - 1; y < m.Outer.Br.Y+1; y++ {
|
||||
for x := m.Outer.Tl.X - 1; x < m.Outer.Br.X+1; x++ {
|
||||
c := h.Coordinate3d{X: x, Y: y, Z: 0}
|
||||
if _, pok := m.Portals[c]; pok {
|
||||
fmt.Print("*")
|
||||
//} else if m.Inner.IsInBorder(c) {
|
||||
// fmt.Print("$")
|
||||
//} else if m.Inner.ContainsButNotBorder(c) {
|
||||
// fmt.Print(" ")
|
||||
} else if m.MazeMap[c] {
|
||||
if v, ok := visited[c]; ok && v {
|
||||
fmt.Print(h.FILL_CHAR)
|
||||
} else {
|
||||
fmt.Print(" ")
|
||||
fmt.Print(".")
|
||||
}
|
||||
} else {
|
||||
fmt.Print("#")
|
||||
}
|
||||
}
|
||||
fmt.Println()
|
||||
}
|
||||
}
|
||||
|
||||
func (m *Maze) GetStart() *MazeCoord {
|
||||
start := m.portals["AA"]
|
||||
return m.maze[c(start.X1, start.Y1)]
|
||||
}
|
||||
|
||||
func (m *Maze) IsDone() bool {
|
||||
return m.IsEnd(m.current.X, m.current.Y)
|
||||
}
|
||||
|
||||
func (m *Maze) GetEnd() *MazeCoord {
|
||||
end := m.portals["ZZ"]
|
||||
return m.maze[c(end.X1, end.Y1)]
|
||||
}
|
||||
|
||||
func (m *Maze) IsEnd(x, y int) bool {
|
||||
return x == m.GetEnd().X && y == m.GetEnd().Y
|
||||
}
|
||||
|
||||
type Portal struct {
|
||||
Name string
|
||||
X1, Y1, X2, Y2 int
|
||||
}
|
||||
|
||||
type MazeCoord struct {
|
||||
X, Y int
|
||||
N, E, S, W *MazeCoord
|
||||
Value byte
|
||||
visited bool
|
||||
steps int
|
||||
}
|
||||
|
||||
func c(x, y int) string {
|
||||
return fmt.Sprintf("[%d, %d]", x, y)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user