回答編集履歴
2
更新
test
CHANGED
@@ -34,7 +34,7 @@
|
|
34
34
|
|
35
35
|
def min_key
|
36
36
|
|
37
|
-
@hash.select{|k,v| v.
|
37
|
+
@hash.select{|k,v| !v.empty?}.map(&:first).min
|
38
38
|
|
39
39
|
end
|
40
40
|
|
@@ -46,7 +46,9 @@
|
|
46
46
|
|
47
47
|
def empty?
|
48
48
|
|
49
|
-
@hash.
|
49
|
+
@hash.delete_if{|k,v| v.empty?}
|
50
|
+
|
51
|
+
.empty?
|
50
52
|
|
51
53
|
end
|
52
54
|
|
@@ -56,7 +58,7 @@
|
|
56
58
|
|
57
59
|
def distance(start, goal)
|
58
60
|
|
59
|
-
|
61
|
+
(start[0]-goal[0]).abs + (start[1]-goal[1]).abs
|
60
62
|
|
61
63
|
end
|
62
64
|
|
@@ -70,21 +72,23 @@
|
|
70
72
|
|
71
73
|
que.push([start,[]], distance(start, goal))
|
72
74
|
|
73
|
-
close = Set
|
75
|
+
close = Set[]
|
74
76
|
|
75
77
|
until que.empty?
|
76
78
|
|
77
79
|
now, route = que.pop
|
78
80
|
|
81
|
+
next unless close.add?(now)
|
82
|
+
|
79
83
|
next_route = route + [now]
|
84
|
+
|
85
|
+
return next_route if now == goal
|
80
86
|
|
81
87
|
dist = next_route.size
|
82
88
|
|
83
|
-
return next_route if now == goal
|
84
|
-
|
85
89
|
dirs = directions.map{|dx,dy| [now[0] + dx, now[1] + dy] }
|
86
90
|
|
87
|
-
.select{|pos| !except.include?(pos)
|
91
|
+
.select{|pos| !except.include?(pos) }
|
88
92
|
|
89
93
|
dirs.each do |to|
|
90
94
|
|
@@ -98,7 +102,19 @@
|
|
98
102
|
|
99
103
|
|
100
104
|
|
101
|
-
except = [
|
105
|
+
except = [
|
106
|
+
|
107
|
+
[3,10], # [4,11],[4,9],[5,10],
|
108
|
+
|
109
|
+
*Array.new(15){|i| [0,i] },
|
110
|
+
|
111
|
+
*Array.new(15){|i| [i,0] },
|
112
|
+
|
113
|
+
# *Array.new(14){|i| [14,i+1]},
|
114
|
+
|
115
|
+
# *Array.new(14){|i| [i+1, 14]},
|
116
|
+
|
117
|
+
]
|
102
118
|
|
103
119
|
p a_star([1,13],[4,10],except)
|
104
120
|
|
1
追記
test
CHANGED
@@ -1,3 +1,105 @@
|
|
1
1
|
A*で使う推定距離は実際の距離より短ければなんでもいいので
|
2
2
|
|
3
3
|
壁を通った場合の距離でも問題ありません。
|
4
|
+
|
5
|
+
|
6
|
+
|
7
|
+
**追記**
|
8
|
+
|
9
|
+
|
10
|
+
|
11
|
+
実装してみた
|
12
|
+
|
13
|
+
|
14
|
+
|
15
|
+
```ruby
|
16
|
+
|
17
|
+
require 'set'
|
18
|
+
|
19
|
+
|
20
|
+
|
21
|
+
class PriorityQueue
|
22
|
+
|
23
|
+
def initialize
|
24
|
+
|
25
|
+
@hash = Hash.new{|h,k| h[k] = [] }
|
26
|
+
|
27
|
+
end
|
28
|
+
|
29
|
+
def push(val, priority)
|
30
|
+
|
31
|
+
@hash[priority].push val
|
32
|
+
|
33
|
+
end
|
34
|
+
|
35
|
+
def min_key
|
36
|
+
|
37
|
+
@hash.select{|k,v| v.size != 0}.map(&:first).min
|
38
|
+
|
39
|
+
end
|
40
|
+
|
41
|
+
def pop
|
42
|
+
|
43
|
+
@hash[min_key].pop
|
44
|
+
|
45
|
+
end
|
46
|
+
|
47
|
+
def empty?
|
48
|
+
|
49
|
+
@hash.values.all?(&:empty?)
|
50
|
+
|
51
|
+
end
|
52
|
+
|
53
|
+
end
|
54
|
+
|
55
|
+
|
56
|
+
|
57
|
+
def distance(start, goal)
|
58
|
+
|
59
|
+
[start,goal].transpose.map{|s,g| (s-g).abs}.sum
|
60
|
+
|
61
|
+
end
|
62
|
+
|
63
|
+
|
64
|
+
|
65
|
+
def a_star(start, goal, except)
|
66
|
+
|
67
|
+
directions = [[0,1],[0,-1],[1,0],[-1,0]]
|
68
|
+
|
69
|
+
que = PriorityQueue.new
|
70
|
+
|
71
|
+
que.push([start,[]], distance(start, goal))
|
72
|
+
|
73
|
+
close = Set.new(start)
|
74
|
+
|
75
|
+
until que.empty?
|
76
|
+
|
77
|
+
now, route = que.pop
|
78
|
+
|
79
|
+
next_route = route + [now]
|
80
|
+
|
81
|
+
dist = next_route.size
|
82
|
+
|
83
|
+
return next_route if now == goal
|
84
|
+
|
85
|
+
dirs = directions.map{|dx,dy| [now[0] + dx, now[1] + dy] }
|
86
|
+
|
87
|
+
.select{|pos| !except.include?(pos) && close.add?(pos) }
|
88
|
+
|
89
|
+
dirs.each do |to|
|
90
|
+
|
91
|
+
que.push([to,next_route], dist + distance(to, goal))
|
92
|
+
|
93
|
+
end
|
94
|
+
|
95
|
+
end
|
96
|
+
|
97
|
+
end
|
98
|
+
|
99
|
+
|
100
|
+
|
101
|
+
except = [[3,10],[0,0],[0,1],[0,2],[0,3],[0,4],[0,5],[0,6],[0,7],[0,8],[0,9],[0,10],[0,11],[0,12],[0,13], [0,14], [1,0],[2,0],[3,0],[4,0],[0,4],[5,0],[6,0],[7,0],[8,0],[9,0],[10,0],[11,0],[12,0],[13,0], [14,0]]
|
102
|
+
|
103
|
+
p a_star([1,13],[4,10],except)
|
104
|
+
|
105
|
+
```
|