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