-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathastar_search.rb
71 lines (59 loc) · 1.89 KB
/
astar_search.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
# A* Search Algorithm
# https://en.wikipedia.org/wiki/A*_search_algorithm
require './algorithms/priority_queue.rb'
require './algorithms/grids.rb'
module AstarSearch
def self.astar(grid, source, target, neighborship = 'neighbors4')
frontier = PriorityQueue.new
frontier.push(source, 0)
previous = {}
cost = {}
previous[source.key] = nil
cost[source.key] = 0
while !frontier.empty?
current = frontier.pop.first
return if current == target
neighbors = grid.send(neighborship, current)
neighbors.reject! { |neighbor| grid[neighbor.y][neighbor.x] != 0 }
neighbors.each do |neighbor|
new_cost = cost[current.key] + Grid.cityblock_distance(current, neighbor)
if !cost.keys.include?(neighbor.key) || new_cost < cost[neighbor.key]
cost[neighbor.key] = new_cost
priority = new_cost + Grid.cityblock_distance(target, neighbor)
frontier.push(neighbor, priority)
previous[neighbor.key] = current.key
end
end
end
return previous, cost
end
def self.shortest_path(grid, source, target, neighborship = 'neighbors4')
previous, cost = astar(grid, source, target, neighborship)
result = [target.key]
node = target.key
while previous[node]
result << previous[node]
node = previous[node]
end
result.reverse
end
def self.test
array = [[0, 0, 0, 0, 0, 1],
[1, 1, 0, 0, 0, 1],
[0, 0, 0, 1, 0, 0],
[0, 1, 1, 0, 0, 1],
[0, 1, 0, 0, 1, 0],
[0, 1, 0, 0, 0, 0]]
grid = Grid.new_from_array(array)
grid.print
result = shortest_path(grid, Point.new(0,0), Point.new(5,5))
puts "shortest path from top left to bottom right:"
puts result.join("\n")
grid.mark_points(result)
grid.print
end
end
# usage
# $ irb
# > require './algorithms/astar_search.rb'
# > AstarSearch.test