2019 Day 15 Complete

This commit is contained in:
Brian Buller 2019-12-18 16:44:05 -06:00
parent 14fcb13c3c
commit 068b018cc0
3 changed files with 118 additions and 86 deletions

View File

@ -12,29 +12,32 @@ import (
) )
var auto bool var auto bool
var maze *Maze var maze *Maze
func main() { func main() {
progFileName := "input" progFileName := "input"
auto = true
if len(os.Args) > 1 && os.Args[1] == "-auto" { if len(os.Args) > 1 && os.Args[1] == "-manual" {
auto = true auto = false
} }
prog := intcode.ReadIntCodeFile(progFileName) prog := intcode.ReadIntCodeFile(progFileName)
maze = NewMaze() maze = NewMaze()
play(prog) part1(prog)
part2()
} }
func play(prog []int) { var all map[string]*MazeCoord
func part1(prog []int) {
p := intcode.NewProgram(prog) p := intcode.NewProgram(prog)
go func() { go func() {
var roadTaken []helpers.Coordinate var roadTaken []helpers.Coordinate
for { for {
time.Sleep(500) //time.Sleep(500)
fmt.Println(helpers.CLEAR_SCREEN) //fmt.Println(helpers.CLEAR_SCREEN)
maze.Print() //maze.Print()
for !p.NeedsInput() { for !p.NeedsInput() {
time.Sleep(1) time.Sleep(1)
} }
@ -110,40 +113,118 @@ func play(prog []int) {
fmt.Println(helpers.CLEAR_SCREEN) fmt.Println(helpers.CLEAR_SCREEN)
maze.Print() maze.Print()
fmt.Println("Now find shortest path") fmt.Println("Now find shortest path")
done, ret := BFS(maze.bfs[maze.startCoord], maze.bfs[maze.o2Coord]) all = make(map[string]*MazeCoord)
if done { for k, v := range maze.maze {
fmt.Println("Found Route") if v == MAZE_EMPTY || v == MAZE_O2SYS {
} else { c := helpers.CoordinateFromString(k)
fmt.Println("No Route Found") m := &MazeCoord{coord: c}
m.Distance = helpers.MAX_INT
all[c.String()] = m
}
} }
fmt.Println("Steps:", len(ret)) for _, v := range all {
n, ok := all[v.coord.GetNorthCoord().String()]
if ok {
v.N = n
}
e, ok := all[v.coord.GetEastCoord().String()]
if ok {
v.E = e
}
s, ok := all[v.coord.GetSouthCoord().String()]
if ok {
v.S = s
}
w, ok := all[v.coord.GetWestCoord().String()]
if ok {
v.W = w
}
}
start := all[maze.startCoord.String()]
start.Distance = 0
fmt.Println("Processing. . .")
ProcessNode(start, 0)
fmt.Println("Distance to O2:", all[maze.o2Coord.String()].Distance)
} }
func BFS(start, goal *BFSNode) (bool, []*BFSNode) { func ProcessNode(m *MazeCoord, steps int) {
var queue, explored []*BFSNode if m.coord.String() == maze.o2Coord.String() {
queue = append(queue, start) return
if start == goal {
fmt.Println(queue)
return true, queue
} }
explored = append(explored, start) for _, neighbor := range []*MazeCoord{m.N, m.E, m.S, m.W} {
for len(queue) > 0 { if neighbor == nil {
var current *BFSNode continue
if len(queue) > 1 { }
current, queue = queue[0], queue[1:] wrk, ok := all[neighbor.coord.String()]
if current == goal { if ok {
fmt.Println(explored) if m.Distance+1 < wrk.Distance {
return true, explored wrk.Distance = m.Distance + 1
} else { if !wrk.Visited {
children := current.getChildren() ProcessNode(wrk, m.Distance+1)
if len(children) != 0 {
queue = append(queue, children...)
} else {
return false, explored
} }
} }
} }
explored = append(explored, current)
} }
return false, explored m.Visited = true
}
func part2() {
// We're going to reuse the visited flag for oxygen
for _, v := range all {
v.Visited = false
}
fmt.Println("Unfilled", countUnfilledSpaces())
all[maze.o2Coord.String()].Visited = true
var cnt int
for countUnfilledSpaces() > 0 {
tick()
fmt.Println("Unfilled", countUnfilledSpaces())
cnt++
}
fmt.Println("Minutes:", cnt)
}
func countUnfilledSpaces() int {
var count int
for _, v := range all {
if !v.Visited {
count++
}
}
return count
}
func tick() bool {
// Start with the o2 coord
var toFill []*MazeCoord
for _, v := range all {
if v.N != nil && v.N.Visited {
toFill = append(toFill, v)
continue
}
if v.E != nil && v.E.Visited {
toFill = append(toFill, v)
continue
}
if v.S != nil && v.S.Visited {
toFill = append(toFill, v)
continue
}
if v.W != nil && v.W.Visited {
toFill = append(toFill, v)
continue
}
}
for k := range toFill {
all[toFill[k].coord.String()].Visited = true
}
fmt.Println("Filled", len(toFill), "spaces")
return len(toFill) > 0
}
type MazeCoord struct {
coord *helpers.Coordinate
N, S, E, W *MazeCoord
Distance int
Visited bool
} }

View File

@ -29,8 +29,6 @@ type Maze struct {
dirHistory []int dirHistory []int
dnt bool dnt bool
bfs map[*helpers.Coordinate]*BFSNode
startCoord *helpers.Coordinate startCoord *helpers.Coordinate
o2Coord *helpers.Coordinate o2Coord *helpers.Coordinate
} }
@ -43,7 +41,6 @@ func NewMaze() *Maze {
maxY: helpers.MIN_INT, maxY: helpers.MIN_INT,
minY: helpers.MAX_INT, minY: helpers.MAX_INT,
bot: helpers.NewCoordinate(0, 0), bot: helpers.NewCoordinate(0, 0),
bfs: make(map[*helpers.Coordinate]*BFSNode),
startCoord: helpers.NewCoordinate(0, 0), startCoord: helpers.NewCoordinate(0, 0),
} }
m.path = append(m.path, helpers.NewCoordinate(0, 0)) m.path = append(m.path, helpers.NewCoordinate(0, 0))
@ -51,29 +48,6 @@ func NewMaze() *Maze {
} }
func (m *Maze) SetCoord(c *helpers.Coordinate, val int) { 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 { if val == 2 {
m.o2Coord = c m.o2Coord = c
} }
@ -170,26 +144,3 @@ func (m *Maze) Print() {
fmt.Println() 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
}

View File

@ -42,7 +42,7 @@ func (c *Coordinate) GetWestCoord() *Coordinate {
func CoordinateFromString(str string) *Coordinate { func CoordinateFromString(str string) *Coordinate {
c := Coordinate{} c := Coordinate{}
r := strings.NewReader(str) r := strings.NewReader(str)
_, err := fmt.Fscanf(r, "[%d, %d]", c.X, c.Y) _, err := fmt.Fscanf(r, "[%d, %d]", &c.X, &c.Y)
if err != nil { if err != nil {
panic(err) panic(err)
} }