gastar 1.0.1 → 1.0.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +9 -9
- data/example/example_runner.rb +79 -79
- data/lib/gastar/version.rb +3 -3
- data/spec/gastar_spec.rb +66 -67
- metadata +26 -15
checksums.yaml
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
---
|
2
2
|
!binary "U0hBMQ==":
|
3
3
|
metadata.gz: !binary |-
|
4
|
-
|
4
|
+
YjVmNGZmMWU5OTA0NWJjZmJjNzRhZmZjNjcwMjdlOTM0ZTE5NmJiYQ==
|
5
5
|
data.tar.gz: !binary |-
|
6
|
-
|
7
|
-
|
6
|
+
YWZhODVlMjIwYmFiNTQxOGE2ZWE5ODM1MzBjYWMyYWE5ZDY2NTA0Nw==
|
7
|
+
SHA512:
|
8
8
|
metadata.gz: !binary |-
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
YTg0ZDkwZmYyMzMzOTgwMGI3NjFiZWZkNzlmMTcxMmNkM2VmMmQ4ZGFiYjcz
|
10
|
+
YjYyMDM4MDRjMmMwMGEzOWFkOGZiMjlkYzdhZTM2ZjhlMmI3MmIwMjkxYzlj
|
11
|
+
M2ZkMmYzNjI5ZmE2MzQ0YzJhZTkzZjgyZDE5MTg0ODhkNzVkMTA=
|
12
12
|
data.tar.gz: !binary |-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
M2Q5YmMzNzgxNzRkZWUwZmNkN2E5ZWQ5NGUyN2Y1OGJjNWMyYmI4NzEwMzFk
|
14
|
+
ZjIwY2JlN2UyZjQzYTc1YjQwZTJmOWZjNDNmYTQyZDk0Yzk1NzM5YTBlMGQ2
|
15
|
+
OTM4MmE1YzlhNWVjNWQ3OGIwOTVjN2I4MTQzZmE3NWNkY2MzZWQ=
|
data/example/example_runner.rb
CHANGED
@@ -1,79 +1,79 @@
|
|
1
|
-
require_relative "../lib/gastar"
|
2
|
-
|
3
|
-
##########################################################
|
4
|
-
# Example implementations
|
5
|
-
##########################################################
|
6
|
-
|
7
|
-
class AStarGrid < AStar
|
8
|
-
def heuristic(node, start, goal)
|
9
|
-
Math.sqrt((goal.x - node.x)**2 + (goal.y - node.y)**2)
|
10
|
-
end
|
11
|
-
end
|
12
|
-
|
13
|
-
class AStarGridNode < AStarNode
|
14
|
-
attr_reader :x, :y
|
15
|
-
def initialize(x, y)
|
16
|
-
super()
|
17
|
-
@x, @y = x, y
|
18
|
-
end
|
19
|
-
def move_cost(other)
|
20
|
-
diagonal = (self.x - other.x).abs == 1 and (self.y - other.y).abs == 1
|
21
|
-
diagonal ? 14 : 10
|
22
|
-
end
|
23
|
-
def to_s
|
24
|
-
"(%d,%d)" % [x,y]
|
25
|
-
end
|
26
|
-
end
|
27
|
-
|
28
|
-
##########################################################
|
29
|
-
# Example graph generator and use of the search algoritm
|
30
|
-
##########################################################
|
31
|
-
|
32
|
-
def make_graph(width, height)
|
33
|
-
nodes = width.times.map{|x| height.times.map{|y| AStarGridNode.new(x, y) } }
|
34
|
-
graph = {}
|
35
|
-
width.times.to_a.product(height.times.to_a).each do |x, y|
|
36
|
-
node = nodes[x][y]
|
37
|
-
graph[node] = []
|
38
|
-
[-1, 0, 1].product([-1, 0, 1]).each do |i, j|
|
39
|
-
next unless 0 <= x + i && x + i < width
|
40
|
-
next unless 0 <= y + j && y + j < height
|
41
|
-
graph[nodes[x][y]] << nodes[x+i][y+j]
|
42
|
-
end
|
43
|
-
end
|
44
|
-
[graph, nodes]
|
45
|
-
end
|
46
|
-
|
47
|
-
def render(width,height,start, goal, path)
|
48
|
-
vertices = path.map{|step| [step.x, step.y] }
|
49
|
-
height.times.each do |y|
|
50
|
-
width.times.each do |x|
|
51
|
-
if [start.x, start.y] == [x,y]
|
52
|
-
print "S"
|
53
|
-
elsif [goal.x, goal.y] == [x,y]
|
54
|
-
print "G"
|
55
|
-
elsif vertices.include?([x,y])
|
56
|
-
print "+"
|
57
|
-
else
|
58
|
-
print "."
|
59
|
-
end
|
60
|
-
end
|
61
|
-
puts
|
62
|
-
end
|
63
|
-
end
|
64
|
-
|
65
|
-
def main
|
66
|
-
width, height = 16,10
|
67
|
-
graph, nodes = make_graph(width, height)
|
68
|
-
paths = AStarGrid.new(graph)
|
69
|
-
start, goal = nodes[1][2], nodes[ 12][7]
|
70
|
-
path = paths.search(start, goal)
|
71
|
-
unless path
|
72
|
-
puts "No path found"
|
73
|
-
else
|
74
|
-
puts "Path found:", path.join(" ")
|
75
|
-
render(width,height,start, goal, path)
|
76
|
-
end
|
77
|
-
end
|
78
|
-
|
79
|
-
main if __FILE__ == $0
|
1
|
+
require_relative "../lib/gastar"
|
2
|
+
|
3
|
+
##########################################################
|
4
|
+
# Example implementations
|
5
|
+
##########################################################
|
6
|
+
|
7
|
+
class AStarGrid < AStar
|
8
|
+
def heuristic(node, start, goal)
|
9
|
+
Math.sqrt((goal.x - node.x)**2 + (goal.y - node.y)**2)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
class AStarGridNode < AStarNode
|
14
|
+
attr_reader :x, :y
|
15
|
+
def initialize(x, y)
|
16
|
+
super()
|
17
|
+
@x, @y = x, y
|
18
|
+
end
|
19
|
+
def move_cost(other)
|
20
|
+
diagonal = (self.x - other.x).abs == 1 and (self.y - other.y).abs == 1
|
21
|
+
diagonal ? 14 : 10
|
22
|
+
end
|
23
|
+
def to_s
|
24
|
+
"(%d,%d)" % [x,y]
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
##########################################################
|
29
|
+
# Example graph generator and use of the search algoritm
|
30
|
+
##########################################################
|
31
|
+
|
32
|
+
def make_graph(width, height)
|
33
|
+
nodes = width.times.map{|x| height.times.map{|y| AStarGridNode.new(x, y) } }
|
34
|
+
graph = {}
|
35
|
+
width.times.to_a.product(height.times.to_a).each do |x, y|
|
36
|
+
node = nodes[x][y]
|
37
|
+
graph[node] = []
|
38
|
+
[-1, 0, 1].product([-1, 0, 1]).each do |i, j|
|
39
|
+
next unless 0 <= x + i && x + i < width
|
40
|
+
next unless 0 <= y + j && y + j < height
|
41
|
+
graph[nodes[x][y]] << nodes[x+i][y+j]
|
42
|
+
end
|
43
|
+
end
|
44
|
+
[graph, nodes]
|
45
|
+
end
|
46
|
+
|
47
|
+
def render(width,height,start, goal, path)
|
48
|
+
vertices = path.map{|step| [step.x, step.y] }
|
49
|
+
height.times.each do |y|
|
50
|
+
width.times.each do |x|
|
51
|
+
if [start.x, start.y] == [x,y]
|
52
|
+
print "S"
|
53
|
+
elsif [goal.x, goal.y] == [x,y]
|
54
|
+
print "G"
|
55
|
+
elsif vertices.include?([x,y])
|
56
|
+
print "+"
|
57
|
+
else
|
58
|
+
print "."
|
59
|
+
end
|
60
|
+
end
|
61
|
+
puts
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
def main
|
66
|
+
width, height = 16,10
|
67
|
+
graph, nodes = make_graph(width, height)
|
68
|
+
paths = AStarGrid.new(graph)
|
69
|
+
start, goal = nodes[1][2], nodes[ 12][7]
|
70
|
+
path = paths.search(start, goal)
|
71
|
+
unless path
|
72
|
+
puts "No path found"
|
73
|
+
else
|
74
|
+
puts "Path found:", path.join(" ")
|
75
|
+
render(width,height,start, goal, path)
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
main if __FILE__ == $0
|
data/lib/gastar/version.rb
CHANGED
@@ -1,3 +1,3 @@
|
|
1
|
-
module Gastar
|
2
|
-
VERSION = "1.0.
|
3
|
-
end
|
1
|
+
module Gastar
|
2
|
+
VERSION = "1.0.2"
|
3
|
+
end
|
data/spec/gastar_spec.rb
CHANGED
@@ -1,67 +1,66 @@
|
|
1
|
-
require_relative '../lib/gastar'
|
2
|
-
|
3
|
-
class Node < AStarNode
|
4
|
-
attr_reader :name, :x, :y
|
5
|
-
def initialize(name, x, y)
|
6
|
-
super()
|
7
|
-
@name, @x, @y = name, x, y
|
8
|
-
end
|
9
|
-
def move_cost(other) 1 end
|
10
|
-
def to_s() name end
|
11
|
-
end
|
12
|
-
|
13
|
-
class Space < AStar
|
14
|
-
def heuristic(node, start, goal)
|
15
|
-
Math.sqrt( (goal.x - node.x)**2 + (goal.y - node.y)**2 )
|
16
|
-
end
|
17
|
-
end
|
18
|
-
|
19
|
-
describe "AStar implementation" do
|
20
|
-
|
21
|
-
it "finds the shorted path between cities" do
|
22
|
-
|
23
|
-
sun = Node.new "Sundsvall", 9, 10
|
24
|
-
upp = Node.new "Uppsala", 9, 6
|
25
|
-
sth = Node.new "Stockholm", 10, 5
|
26
|
-
jon = Node.new "Jonkoping", 4, 3
|
27
|
-
got = Node.new "Gothenburg", 1, 3
|
28
|
-
mal = Node.new "Malmo", 2, 1
|
29
|
-
|
30
|
-
cities = {
|
31
|
-
sun => [upp],
|
32
|
-
sth => [sun,jon,upp],
|
33
|
-
jon => [sth,got,mal],
|
34
|
-
upp => [sth,sun],
|
35
|
-
mal => [jon],
|
36
|
-
got => [jon]
|
37
|
-
}
|
38
|
-
|
39
|
-
expected = [sun, upp, sth, jon, mal]
|
40
|
-
actual = Space.new(cities).search(sun, mal)
|
41
|
-
|
42
|
-
actual.
|
43
|
-
|
44
|
-
end
|
45
|
-
|
46
|
-
it "finds the longest path between cities" do
|
47
|
-
|
48
|
-
a = Node.new "C1", 1, 1
|
49
|
-
b = Node.new "C2", 2, 2
|
50
|
-
c = Node.new "C3", 1, 3
|
51
|
-
d = Node.new "C4", 1, 4
|
52
|
-
|
53
|
-
|
54
|
-
cities = {
|
55
|
-
a => [b,c],
|
56
|
-
b => [c],
|
57
|
-
c => [d],
|
58
|
-
d => [c],
|
59
|
-
}
|
60
|
-
|
61
|
-
Space.new(cities, false).search(a, d).
|
62
|
-
Space.new(cities, true).search(a, d).
|
63
|
-
|
64
|
-
end
|
65
|
-
|
66
|
-
end
|
67
|
-
|
1
|
+
require_relative '../lib/gastar'
|
2
|
+
|
3
|
+
class Node < AStarNode
|
4
|
+
attr_reader :name, :x, :y
|
5
|
+
def initialize(name, x, y)
|
6
|
+
super()
|
7
|
+
@name, @x, @y = name, x, y
|
8
|
+
end
|
9
|
+
def move_cost(other) 1 end
|
10
|
+
def to_s() name end
|
11
|
+
end
|
12
|
+
|
13
|
+
class Space < AStar
|
14
|
+
def heuristic(node, start, goal)
|
15
|
+
Math.sqrt( (goal.x - node.x)**2 + (goal.y - node.y)**2 )
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
describe "AStar implementation" do
|
20
|
+
|
21
|
+
it "finds the shorted path between cities" do
|
22
|
+
|
23
|
+
sun = Node.new "Sundsvall", 9, 10
|
24
|
+
upp = Node.new "Uppsala", 9, 6
|
25
|
+
sth = Node.new "Stockholm", 10, 5
|
26
|
+
jon = Node.new "Jonkoping", 4, 3
|
27
|
+
got = Node.new "Gothenburg", 1, 3
|
28
|
+
mal = Node.new "Malmo", 2, 1
|
29
|
+
|
30
|
+
cities = {
|
31
|
+
sun => [upp],
|
32
|
+
sth => [sun,jon,upp],
|
33
|
+
jon => [sth,got,mal],
|
34
|
+
upp => [sth,sun],
|
35
|
+
mal => [jon],
|
36
|
+
got => [jon]
|
37
|
+
}
|
38
|
+
|
39
|
+
expected = [sun, upp, sth, jon, mal]
|
40
|
+
actual = Space.new(cities).search(sun, mal)
|
41
|
+
|
42
|
+
expect(actual).to eql(expected)
|
43
|
+
|
44
|
+
end
|
45
|
+
|
46
|
+
it "finds the longest path between cities" do
|
47
|
+
|
48
|
+
a = Node.new "C1", 1, 1
|
49
|
+
b = Node.new "C2", 2, 2
|
50
|
+
c = Node.new "C3", 1, 3
|
51
|
+
d = Node.new "C4", 1, 4
|
52
|
+
|
53
|
+
|
54
|
+
cities = {
|
55
|
+
a => [b,c],
|
56
|
+
b => [c],
|
57
|
+
c => [d],
|
58
|
+
d => [c],
|
59
|
+
}
|
60
|
+
|
61
|
+
expect( Space.new(cities, false).search(a, d) ).to eql([a,c,d])
|
62
|
+
expect( Space.new(cities, true ).search(a, d) ).to eql([a,b,c,d])
|
63
|
+
|
64
|
+
end
|
65
|
+
|
66
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: gastar
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jonas Tingeborn
|
@@ -45,17 +45,28 @@ executables: []
|
|
45
45
|
extensions: []
|
46
46
|
extra_rdoc_files: []
|
47
47
|
files:
|
48
|
-
-
|
49
|
-
|
50
|
-
-
|
51
|
-
|
52
|
-
-
|
53
|
-
|
54
|
-
-
|
55
|
-
|
56
|
-
-
|
57
|
-
|
58
|
-
-
|
48
|
+
- !binary |-
|
49
|
+
LmdpdGlnbm9yZQ==
|
50
|
+
- !binary |-
|
51
|
+
LnJzcGVj
|
52
|
+
- !binary |-
|
53
|
+
R2VtZmlsZQ==
|
54
|
+
- !binary |-
|
55
|
+
TElDRU5TRS50eHQ=
|
56
|
+
- !binary |-
|
57
|
+
UkVBRE1FLm1k
|
58
|
+
- !binary |-
|
59
|
+
UmFrZWZpbGU=
|
60
|
+
- !binary |-
|
61
|
+
ZXhhbXBsZS9leGFtcGxlX3J1bm5lci5yYg==
|
62
|
+
- !binary |-
|
63
|
+
Z2FzdGFyLmdlbXNwZWM=
|
64
|
+
- !binary |-
|
65
|
+
bGliL2dhc3Rhci5yYg==
|
66
|
+
- !binary |-
|
67
|
+
bGliL2dhc3Rhci92ZXJzaW9uLnJi
|
68
|
+
- !binary |-
|
69
|
+
c3BlYy9nYXN0YXJfc3BlYy5yYg==
|
59
70
|
homepage: https://github.com/jojje/gastar
|
60
71
|
licenses:
|
61
72
|
- MIT
|
@@ -76,10 +87,10 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
76
87
|
version: '0'
|
77
88
|
requirements: []
|
78
89
|
rubyforge_project:
|
79
|
-
rubygems_version: 2.
|
90
|
+
rubygems_version: 2.2.2
|
80
91
|
signing_key:
|
81
92
|
specification_version: 4
|
82
93
|
summary: A generic A* implementation
|
83
94
|
test_files:
|
84
|
-
-
|
85
|
-
|
95
|
+
- !binary |-
|
96
|
+
c3BlYy9nYXN0YXJfc3BlYy5yYg==
|