2019 Day 15 Complete
This commit is contained in:
		@@ -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
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -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
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -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)
 | 
			
		||||
	}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user