gastar 1.0.1 → 1.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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==
|