From e40c41ddfb5adfdd5bd12bee0829b479c7524264 Mon Sep 17 00:00:00 2001 From: Karma Riuk Date: Tue, 15 Aug 2023 18:43:18 +0200 Subject: [PATCH] feat: implemented a* algorithm --- solver/a-star.go | 66 ++++++++++++++++++++++++++++++++++++++++++++++++ solver/solver.go | 4 +++ 2 files changed, 70 insertions(+) create mode 100644 solver/a-star.go diff --git a/solver/a-star.go b/solver/a-star.go new file mode 100644 index 0000000..f4922b0 --- /dev/null +++ b/solver/a-star.go @@ -0,0 +1,66 @@ +package solver + +import ( + "maze-solver/maze" + "maze-solver/utils" + "sort" +) + +type AStarSolver struct { + dist_from_start map[*maze.Node]int + dist_from_end map[*maze.Node]int + parent map[*maze.Node]*maze.Node + stack sorted_stack +} + +func (s *AStarSolver) Solve(m *maze.Maze) *maze.SolvedMaze { + defer utils.Timer("A* algorithm", 2)() + s.dist_from_start = make(map[*maze.Node]int, len(m.Nodes)) + s.dist_from_end = make(map[*maze.Node]int, len(m.Nodes)) + s.parent = make(map[*maze.Node]*maze.Node, len(m.Nodes)) + + current, end := m.Nodes[0], m.Nodes[len(m.Nodes)-1] + + for _, node := range m.Nodes { + s.dist_from_start[node] = 0 + s.dist_from_end[node] = int(node.Coords.Distance(end.Coords)) + } + + for current != end { + current.Visited = true + + for _, child := range []*maze.Node{current.Left, current.Right, current.Up, current.Down} { + if child != nil { + dist := s.dist_from_start[current] + int(current.Coords.Distance(child.Coords)) + if !child.Visited { + s.parent[child] = current + s.dist_from_start[child] = dist + s.stack.insert(child, &s.dist_from_end) + } else if s.dist_from_start[child] > dist { + s.parent[child] = current + s.dist_from_start[child] = dist + sort.Slice(s.stack, func(i, j int) bool { + return s.dist_from_end[s.stack[i]] < s.dist_from_end[s.stack[j]] + }) + } + } + } + current = s.stack.pop() + } + + solution := make([]*maze.Node, 0, len(m.Nodes)) + for current != m.Nodes[0] { + solution = append(solution, current) + current = s.parent[current] + } + solution = append(solution, m.Nodes[0]) + + for i, j := 0, len(solution)-1; i < j; i, j = i+1, j-1 { + solution[i], solution[j] = solution[j], solution[i] + } + + return &maze.SolvedMaze{ + Maze: m, + Solution: solution, + } +} diff --git a/solver/solver.go b/solver/solver.go index bb985c4..1a735ed 100644 --- a/solver/solver.go +++ b/solver/solver.go @@ -17,12 +17,14 @@ const ( _DFS = "dfs" _BFS = "bfs" _Dijkstra = "dijkstra" + _AStar = "a-star" ) var TYPES = []string{ _DFS, _BFS, _Dijkstra, + _AStar, } func (f *SolverFactory) Get() Solver { @@ -31,6 +33,8 @@ func (f *SolverFactory) Get() Solver { return &DFSSolver{} case _BFS: return &BFSSolver{} + case _AStar: + return &AStarSolver{} case _Dijkstra: return &DijkstraSolver{} }