diff --git a/2019/day15/main.go b/2019/day15/main.go index a908b2d..9b932da 100644 --- a/2019/day15/main.go +++ b/2019/day15/main.go @@ -12,29 +12,32 @@ import ( ) var auto bool - var maze *Maze func main() { progFileName := "input" + auto = true - if len(os.Args) > 1 && os.Args[1] == "-auto" { - auto = true + if len(os.Args) > 1 && os.Args[1] == "-manual" { + auto = false } prog := intcode.ReadIntCodeFile(progFileName) maze = NewMaze() - play(prog) + part1(prog) + part2() } -func play(prog []int) { +var all map[string]*MazeCoord + +func part1(prog []int) { p := intcode.NewProgram(prog) go func() { var roadTaken []helpers.Coordinate for { - time.Sleep(500) - fmt.Println(helpers.CLEAR_SCREEN) - maze.Print() + //time.Sleep(500) + //fmt.Println(helpers.CLEAR_SCREEN) + //maze.Print() for !p.NeedsInput() { time.Sleep(1) } @@ -110,40 +113,118 @@ func play(prog []int) { fmt.Println(helpers.CLEAR_SCREEN) maze.Print() fmt.Println("Now find shortest path") - done, ret := BFS(maze.bfs[maze.startCoord], maze.bfs[maze.o2Coord]) - if done { - fmt.Println("Found Route") - } else { - fmt.Println("No Route Found") + all = make(map[string]*MazeCoord) + for k, v := range maze.maze { + if v == MAZE_EMPTY || v == MAZE_O2SYS { + c := helpers.CoordinateFromString(k) + 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) { - var queue, explored []*BFSNode - queue = append(queue, start) - if start == goal { - fmt.Println(queue) - return true, queue +func ProcessNode(m *MazeCoord, steps int) { + if m.coord.String() == maze.o2Coord.String() { + return } - explored = append(explored, start) - for len(queue) > 0 { - var current *BFSNode - if len(queue) > 1 { - current, queue = queue[0], queue[1:] - if current == goal { - fmt.Println(explored) - return true, explored - } else { - children := current.getChildren() - if len(children) != 0 { - queue = append(queue, children...) - } else { - return false, explored + for _, neighbor := range []*MazeCoord{m.N, m.E, m.S, m.W} { + if neighbor == nil { + continue + } + wrk, ok := all[neighbor.coord.String()] + if ok { + if m.Distance+1 < wrk.Distance { + wrk.Distance = m.Distance + 1 + if !wrk.Visited { + ProcessNode(wrk, m.Distance+1) } } } - 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 } diff --git a/2019/day15/maze.go b/2019/day15/maze.go index 403c6b5..62ef8b3 100644 --- a/2019/day15/maze.go +++ b/2019/day15/maze.go @@ -29,8 +29,6 @@ type Maze struct { dirHistory []int dnt bool - bfs map[*helpers.Coordinate]*BFSNode - startCoord *helpers.Coordinate o2Coord *helpers.Coordinate } @@ -43,7 +41,6 @@ func NewMaze() *Maze { 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)) @@ -51,29 +48,6 @@ func NewMaze() *Maze { } 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 } @@ -170,26 +144,3 @@ func (m *Maze) Print() { 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 -} diff --git a/helpers/coordinate.go b/helpers/coordinate.go index 46edcbe..943af77 100644 --- a/helpers/coordinate.go +++ b/helpers/coordinate.go @@ -42,7 +42,7 @@ func (c *Coordinate) GetWestCoord() *Coordinate { func CoordinateFromString(str string) *Coordinate { c := Coordinate{} 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 { panic(err) }