algorithms 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,29 @@
1
+ module Containers
2
+ # Use a Ruby array for storage
3
+ class Queue
4
+ def initialize(ary=[])
5
+ @container = ary
6
+ end
7
+
8
+ def put(object)
9
+ @container.push(object)
10
+ end
11
+
12
+ def peek
13
+ @container[0]
14
+ end
15
+
16
+ def get
17
+ @container.shift
18
+ end
19
+
20
+ def size
21
+ @container.size
22
+ end
23
+
24
+ def empty?
25
+ @container.empty?
26
+ end
27
+
28
+ end
29
+ end
@@ -0,0 +1,29 @@
1
+ module Containers
2
+ # Use a Ruby array for storage
3
+ class Stack
4
+ def initialize(ary=[])
5
+ @container = ary
6
+ end
7
+
8
+ def push(object)
9
+ @container.push(object)
10
+ end
11
+
12
+ def peek
13
+ @container.last
14
+ end
15
+
16
+ def pop
17
+ @container.pop
18
+ end
19
+
20
+ def size
21
+ @container.size
22
+ end
23
+
24
+ def empty?
25
+ @container.empty?
26
+ end
27
+
28
+ end
29
+ end
@@ -0,0 +1,265 @@
1
+ module Containers
2
+ # A TreeMap implemented with a self-balancing red-black tree
3
+ # Adapted from Robert Sedgewick's Left Leaning Red-Black Tree Implementation
4
+ # http://www.cs.princeton.edu/~rs/talks/LLRB/Java/RedBlackBST.java
5
+ class RubyTreeMap
6
+ include Enumerable
7
+
8
+ class Node
9
+ attr_accessor :color, :key, :value, :left, :right, :num_nodes, :height
10
+ def initialize(key, value)
11
+ @key = key
12
+ @value = value
13
+ @color = :red
14
+ @left = nil
15
+ @right = nil
16
+ @num_nodes = 1
17
+ @height = 1
18
+ end
19
+ end
20
+
21
+ attr_accessor :height_black
22
+
23
+ def initialize
24
+ @root = nil
25
+ @height_black = 0
26
+ end
27
+
28
+ def put(key, value)
29
+ @root = insert(@root, key, value)
30
+ @height_black += 1 if isred(@root)
31
+ @root.color = :black
32
+ end
33
+ alias :[]= :put
34
+
35
+ def size
36
+ sizeR(@root)
37
+ end
38
+
39
+ def height
40
+ heightR(@root)
41
+ end
42
+
43
+ def contains?(key)
44
+ !get(key).nil?
45
+ end
46
+
47
+ def get(key)
48
+ getR(@root, key)
49
+ end
50
+ alias :[] :get
51
+
52
+ def min_key
53
+ @root.nil? ? nil : minR(@root)
54
+ end
55
+
56
+ def max_key
57
+ @root.nil? ? nil : maxR(@root)
58
+ end
59
+
60
+ def delete(key)
61
+ result = nil
62
+ if @root
63
+ @root, result = deleteR(@root, key)
64
+ @root.color = :black
65
+ end
66
+ result
67
+ end
68
+
69
+ def each(&block)
70
+ @root.nil? ? nil : eachR(@root, block)
71
+ end
72
+
73
+ def to_s
74
+ return "" if @root.nil?
75
+ "#{@height_black} #{to_sR(@root)}"
76
+ end
77
+
78
+ private
79
+
80
+ def eachR(node, block)
81
+ return if node.nil?
82
+
83
+ eachR(node.left, block)
84
+ block.call(node.key, node.value)
85
+ eachR(node.right, block)
86
+ end
87
+
88
+ def deleteR(node, key)
89
+ if (key <=> node.key) == -1
90
+ node = move_red_left(node) if (!isred(node.left) && !isred(node.left.left))
91
+ node.left, result = deleteR(node.left, key)
92
+ else
93
+ node = rotate_right(node) if isred(node.left)
94
+ if ( ( (key <=> node.key) == 0) && node.right.nil? )
95
+ return nil, node.value
96
+ end
97
+ if (!isred(node.right) && !isred(node.right.left))
98
+ node = move_red_right(node);
99
+ end
100
+ if (key <=> node.key) == 0
101
+ result = node.value
102
+ node.value = getR(node.right, minR(node.right))
103
+ node.key = minR(node.right)
104
+ node.right = delete_minR(node.right)
105
+ else
106
+ node.right, result = deleteR(node.right, key)
107
+ end
108
+ end
109
+ return fixup(node), result
110
+ end
111
+
112
+ def delete_minR(node)
113
+ return nil if node.left.nil?
114
+ if ( !isred(node.left) && !isred(node.left.left) )
115
+ node = move_red_left(node)
116
+ end
117
+ node.left = delete_minR(node.left)
118
+
119
+ fixup(node)
120
+ end
121
+
122
+ def delete_maxR(node)
123
+ if (isred(node.left))
124
+ node = rotate_right(node)
125
+ end
126
+ return nil if node.right.nil?
127
+ if ( !isred(node.right) && !isred(node.right.left) )
128
+ node = move_red_right(node)
129
+ end
130
+ node.right = delete_maxR(node.right)
131
+
132
+ fixup(node)
133
+ end
134
+
135
+ def getR(node, key)
136
+ return nil if node.nil?
137
+ case key <=> node.key
138
+ when 0 then return node.value;
139
+ when -1 then return getR(node.left, key)
140
+ when 1 then return getR(node.right, key)
141
+ end
142
+ end
143
+
144
+ def to_sR(x)
145
+ s = "("
146
+ x.left.nil? ? s << '(' : s << to_sR(x.left)
147
+ s << "*" if isred(x)
148
+ x.right.nil? ? s << ')' : s << to_sR(x.right)
149
+ s + ')'
150
+ end
151
+
152
+ def sizeR(node)
153
+ return 0 if node.nil?
154
+
155
+ node.num_nodes
156
+ end
157
+
158
+ def heightR(node)
159
+ return 0 if node.nil?
160
+
161
+ node.height
162
+ end
163
+
164
+ def minR(node)
165
+ return node.key if node.left.nil?
166
+
167
+ minR(node.left)
168
+ end
169
+
170
+ def maxR(node)
171
+ return node.key if node.right.nil?
172
+
173
+ maxR(node.right)
174
+ end
175
+
176
+ def insert(node, key, value)
177
+ if(node.nil?)
178
+ return Node.new(key, value)
179
+ end
180
+
181
+ colorflip(node) if (isred(node.left) && isred(node.right))
182
+
183
+ case key <=> node.key
184
+ when 0 then node.value = value
185
+ when -1 then node.left = insert(node.left, key, value)
186
+ when 1 then node.right = insert(node.right, key, value)
187
+ end
188
+
189
+ node = rotate_left(node) if isred(node.right)
190
+ node = rotate_right(node) if (isred(node.left) && isred(node.left.left))
191
+
192
+ set_num_nodes(node)
193
+ end
194
+
195
+ def isred(h)
196
+ return false if h.nil?
197
+
198
+ h.color == :red
199
+ end
200
+
201
+ def rotate_left(h)
202
+ x = h.right
203
+ h.right = x.left
204
+ x.left = set_num_nodes(h)
205
+ x.color = x.left.color
206
+ x.left.color = :red
207
+
208
+ set_num_nodes(x)
209
+ end
210
+
211
+ def rotate_right(h)
212
+ x = h.left
213
+ h.left = x.right
214
+ x.right = set_num_nodes(h)
215
+ x.color = x.right.color
216
+ x.right.color = :red
217
+
218
+ set_num_nodes(x);
219
+ end
220
+
221
+ def colorflip(h)
222
+ h.color = h.color == :red ? :black : :red
223
+ h.left.color = h.left.color == :red ? :black : :red
224
+ h.right.color = h.right.color == :red ? :black : :red
225
+ end
226
+
227
+ def move_red_left(h)
228
+ colorflip(h)
229
+ if isred(h.right.left)
230
+ h.right = rotate_right(h.right)
231
+ h = rotate_left(h)
232
+ colorflip(h)
233
+ end
234
+ h
235
+ end
236
+
237
+ def move_red_right(h)
238
+ colorflip(h)
239
+ if isred(h.left.left)
240
+ h = rotate_right(h)
241
+ colorflip(h)
242
+ end
243
+ h
244
+ end
245
+
246
+ def fixup(h)
247
+ h = rotate_left(h) if isred(h.right)
248
+ h = rotate_right(h) if (isred(h.left) && isred(h.left.left))
249
+ colorflip(h) if (isred(h.left) && isred(h.right))
250
+
251
+ set_num_nodes(h)
252
+ end
253
+
254
+ def set_num_nodes(h)
255
+ h.num_nodes = sizeR(h.left) + sizeR(h.right) + 1
256
+ if heightR(h.left) > heightR(h.right)
257
+ h.height = heightR(h.left) + 1
258
+ else
259
+ h.height = heightR(h.right) + 1
260
+ end
261
+ h
262
+ end
263
+ end
264
+
265
+ end
@@ -0,0 +1,74 @@
1
+ require 'lib/algorithms'
2
+
3
+ describe Containers::Heap do
4
+ before(:each) do
5
+ @heap = Containers::MaxHeap.new
6
+ end
7
+
8
+ describe "(empty)" do
9
+
10
+ it "should return nil when getting the maximum" do
11
+ @heap.get_max!.should eql(nil)
12
+ end
13
+
14
+ it "should let you insert and remove one item" do
15
+ @heap.size.should eql(0)
16
+
17
+ @heap.insert(1)
18
+ @heap.size.should eql(1)
19
+
20
+ @heap.get_max!.should eql(1)
21
+ @heap.size.should eql(0)
22
+ end
23
+
24
+ it "should let you initialize with an array" do
25
+ @heap = Containers::MaxHeap.new([1,2,3])
26
+ @heap.size.should eql(3)
27
+ end
28
+
29
+ end
30
+
31
+ describe "(non-empty)" do
32
+ before(:each) do
33
+ @random_array = []
34
+ @num_items = 100
35
+ @num_items.times { |x| @random_array << rand(@num_items) }
36
+ @heap = Containers::MaxHeap.new(@random_array)
37
+ end
38
+
39
+ it "should display the correct size" do
40
+ @heap.size.should eql(@num_items)
41
+ end
42
+
43
+ it "should be in max->min order" do
44
+ ordered = []
45
+ ordered << @heap.get_max! until @heap.size == 0
46
+
47
+ ordered.should eql(@random_array.sort.reverse)
48
+ end
49
+
50
+ it "should let you merge with another heap" do
51
+ numbers = [1,3,4,5]
52
+ otherheap = Containers::MaxHeap.new(numbers)
53
+ otherheap.size.should eql(4)
54
+ @heap.merge!(otherheap)
55
+
56
+ ordered = []
57
+ ordered << @heap.get_max! until @heap.size == 0
58
+
59
+ ordered.should eql( (@random_array + numbers).sort.reverse)
60
+ end
61
+
62
+ describe "min-heap" do
63
+ it "should be in min->max order" do
64
+ @heap = Containers::MinHeap.new(@random_array)
65
+ ordered = []
66
+ ordered << @heap.get_min! until @heap.size == 0
67
+
68
+ ordered.should eql(@random_array.sort)
69
+ end
70
+ end
71
+
72
+ end
73
+
74
+ end
@@ -0,0 +1,31 @@
1
+ require 'lib/algorithms'
2
+
3
+ describe Containers::RubyPriorityQueue do
4
+ before(:each) do
5
+ @q = Containers::RubyPriorityQueue.new
6
+ end
7
+
8
+ describe "(empty)" do
9
+
10
+ end
11
+
12
+ describe "(non-empty)" do
13
+ it "should give the correct length/size" do
14
+ 20.times do | i |
15
+ @q.length.should eql(i)
16
+ @q[i] = i
17
+ end
18
+ 10.times do | i |
19
+ @q.length.should eql(20-i)
20
+ @q.delete_min
21
+ end
22
+ 10.times do | i |
23
+ @q.length.should eql(i+10)
24
+ @q[i] = i
25
+ end
26
+ @q.delete(5)
27
+ @q.length.should eql(19)
28
+ end
29
+ end
30
+
31
+ end
@@ -0,0 +1,371 @@
1
+ #!/usr/bin/ruby
2
+
3
+ # Priority Queue tests
4
+
5
+ $:.unshift '../ext/priority_queue/CPriorityQueue'
6
+ $:.unshift '../lib/'
7
+
8
+ require 'test/unit'
9
+
10
+ require 'priority_queue/ruby_priority_queue'
11
+ require 'priority_queue/poor_priority_queue'
12
+ begin
13
+ require 'priority_queue/CPriorityQueue'
14
+ rescue LoadError
15
+ require 'CPriorityQueue'
16
+ end
17
+
18
+
19
+ module PriorityQueueTest
20
+ # Check that the order is maintained
21
+ def teardown
22
+ last = @q.min_priority
23
+ while priority = @q.delete_min_return_priority
24
+ assert_operator(last, :<=, priority)
25
+ last = priority
26
+ end
27
+ end
28
+
29
+ def test_length
30
+ 20.times do | i |
31
+ assert_equal(i, @q.length)
32
+ @q[i] = i
33
+ end
34
+ 10.times do | i |
35
+ assert_equal(20-i, @q.length)
36
+ @q.delete_min
37
+ end
38
+ 10.times do | i |
39
+ assert_equal(10+i, @q.length)
40
+ @q[i] = i
41
+ end
42
+ @q.delete(5)
43
+ assert_equal(19, @q.length)
44
+ end
45
+
46
+ def test_merge
47
+ @q1 = @q.class.new
48
+ @q2 = @q.class.new
49
+
50
+ 20.times do | i |
51
+ @q1[i] = i
52
+ @q2[i+20] = i+20
53
+ end
54
+ end
55
+
56
+ # Assure that delete min works
57
+ def test_delete_min
58
+ assert_equal(nil, @q.delete_min, "Empty queue should pop nil")
59
+ @q["n1"] = 0
60
+ assert_equal(["n1", 0], @q.delete_min)
61
+ @q["n1"] = 0
62
+ @q["n2"] = -1
63
+ assert_equal(["n2", -1], @q.delete_min)
64
+ end
65
+
66
+ def test_delete_min_return_key
67
+ assert_equal(nil, @q.delete_min_return_key, "Empty queue should pop nil")
68
+ @q["n1"] = 0
69
+ assert_equal("n1", @q.delete_min_return_key)
70
+ @q["n1"] = 0
71
+ @q["n2"] = -1
72
+ assert_equal("n2", @q.delete_min_return_key)
73
+ end
74
+
75
+ def test_delete_min_return_priority
76
+ assert_equal(nil, @q.delete_min_return_priority, "Empty queue should pop nil")
77
+ @q["n1"] = 0
78
+ assert_equal(0, @q.delete_min_return_priority)
79
+ @q["n1"] = 0
80
+ @q["n2"] = -1
81
+ assert_equal(-1, @q.delete_min_return_priority)
82
+ end
83
+
84
+ def test_has_key?
85
+ assert(!@q.has_key?(1))
86
+ @q[1] = 1
87
+ assert(@q.has_key?(1))
88
+ end
89
+
90
+ def test_empty?
91
+ assert_equal(true, @q.empty?, "Empty queue should return true on empty?")
92
+ @q["node1"] = 10
93
+ assert_equal(false, @q.empty?, "Filled queue should return false on empty?")
94
+ end
95
+
96
+ def test_push
97
+ 20.times do | i |
98
+ @q.push i, i+10
99
+ end
100
+
101
+ 20.times do | i |
102
+ @q.push i, i
103
+ end
104
+
105
+ 20.times do | i |
106
+ assert_equal([i, i], @q.delete_min)
107
+ end
108
+
109
+ assert_equal(nil, @q.delete_min)
110
+ end
111
+
112
+ def test_push_pop
113
+ 20.times do | i |
114
+ @q.push i, i
115
+ end
116
+
117
+ 20.times do | i |
118
+ assert_equal([i, i], @q.delete_min)
119
+ end
120
+
121
+ assert_equal(nil, @q.delete_min)
122
+ end
123
+
124
+ def test_push_decrease_pop
125
+ 50.times do | i |
126
+ @q.push i, i
127
+ end
128
+
129
+ 10.times do | i |
130
+ assert_equal([i, i], @q.delete_min)
131
+ end
132
+
133
+ 10.times do | i |
134
+ @q[i+10] = i
135
+ end
136
+
137
+ 10.times do | i |
138
+ assert_equal([i+10, i], @q.delete_min)
139
+ end
140
+
141
+ 30.times do | i |
142
+ assert_equal([i+20, i+20], @q.delete_min)
143
+ end
144
+
145
+ assert_equal(nil, @q.delete_min)
146
+ end
147
+
148
+ def test_min_key
149
+ assert_equal(nil, @q.min_key)
150
+ @q["node1"] = 0
151
+ assert_equal("node1", @q.min_key)
152
+ @q["node2"] = 1
153
+ assert_equal("node1", @q.min_key)
154
+ @q["node3"] = -1
155
+ assert_equal("node3", @q.min_key)
156
+ end
157
+
158
+ def test_min_priority
159
+ assert_equal(nil, @q.min_priority)
160
+ @q["node1"] = 0
161
+ assert_equal(0, @q.min_priority)
162
+ @q["node2"] = 1
163
+ assert_equal(0, @q.min_priority)
164
+ @q["node3"] = -1
165
+ assert_equal(-1, @q.min_priority)
166
+ end
167
+
168
+ def test_access
169
+ assert_equal(0, @q["node1"] = 0)
170
+ assert_equal(["node1", 0], @q.min)
171
+ assert_equal(1, @q["node2"] = 1)
172
+ assert_equal(1, @q["node2"])
173
+ assert_equal("node1", @q.min_key)
174
+ assert_equal(2, @q["node3"] = 2)
175
+ assert_equal(2, @q["node3"])
176
+ assert_equal("node1", @q.min_key)
177
+ assert_equal(-1, @q["node3"] = -1)
178
+ assert_equal(-1, @q["node3"])
179
+ assert_equal("node3", @q.min_key)
180
+ end
181
+
182
+ def test_min
183
+ assert_equal(nil, @q.min)
184
+ @q["node1"] = 10
185
+ assert_equal(["node1", 10], @q.min)
186
+ @q["node2"] = 5
187
+ assert_equal(["node2", 5], @q.min)
188
+ end
189
+
190
+ def test_decrease_priority
191
+
192
+ 20.times do | i |
193
+ @q.push i, i / 20.0
194
+ end
195
+
196
+ assert_equal([0, 0], @q.delete_min)
197
+
198
+ @q[10] = -1
199
+ @q[11] = -0.5
200
+
201
+ [10, 11, (1..9).to_a, (12..19).to_a, nil].flatten.each do | shall |
202
+ key, priority = *@q.delete_min
203
+ assert_equal(shall, key)
204
+ end
205
+ end
206
+
207
+ def test_increase_priority
208
+ 20.times do | i |
209
+ @q[i] = i
210
+ end
211
+ @q[10] = 5
212
+ assert_equal([0,0], @q.delete_min)
213
+ assert_equal(10, @q[10] = 10)
214
+ assert_equal(20, @q[11] = 20)
215
+ assert_equal([1,1], @q.delete_min)
216
+ end
217
+
218
+ def test_delete
219
+ @q[1] = 1
220
+ @q[2] = 2
221
+ @q[3] = 3
222
+ assert_equal(1, @q[1])
223
+ assert_equal([1,1], @q.min)
224
+ assert_equal([1,1], @q.delete(1))
225
+ assert_equal(nil, @q[1])
226
+ assert_equal([2,2], @q.min)
227
+ assert_equal(nil, @q.delete(1))
228
+ end
229
+
230
+ def test_example_1
231
+ assert_equal(0, @q["node1"] = 0)
232
+ assert_equal(1, @q["node2"] = 1)
233
+ assert_equal("node1", @q.min_key)
234
+ assert_equal(0, @q[@q.min_key])
235
+ assert_equal(0, @q.min_priority)
236
+
237
+ @q["node2"] = -1
238
+ assert_equal(["node2", -1], @q.delete_min)
239
+ assert_equal(nil, @q["node2"])
240
+ @q["node3"] = 1
241
+
242
+ assert_equal(["node3", 1], @q.delete("node3"))
243
+ assert_equal(nil, @q.delete("node2"))
244
+ end
245
+
246
+ def test_dup
247
+ ('a'..'z').each do | n |
248
+ @q[n] = n[0]
249
+ end
250
+ qq = @q.dup
251
+ until @q.empty?
252
+ assert_equal(@q.delete_min, qq.delete_min)
253
+ end
254
+ end
255
+
256
+ def test_each
257
+ ('a'..'z').each do | n |
258
+ @q[n] = n[0]
259
+ end
260
+ queue = ('a'..'z').inject([]) { | r, n | r << [n, n[0]] }
261
+ assert_equal(queue.sort, @q.to_a.sort)
262
+ end
263
+
264
+ extend self
265
+ end
266
+
267
+ class CPriorityQueueTest < Test::Unit::TestCase
268
+ include PriorityQueueTest
269
+
270
+ def setup
271
+ @q = CPriorityQueue.new
272
+ end
273
+
274
+ def test_to_dot
275
+ 5.times do | i |
276
+ @q.push "N#{i}", i
277
+ end
278
+ @q.delete_min
279
+ assert_equal(
280
+ ['digraph fibonacci_heap {',
281
+ ' NODE [label="N1 (1)",shape=box];',
282
+ ' NODE [label="N3 (3)",shape=box];',
283
+ ' NODE [label="N4 (4)",shape=box];',
284
+ ' NODE -> NODE;',
285
+ ' NODE -> NODE;',
286
+ ' NODE [label="N2 (2)",shape=box];',
287
+ ' NODE -> NODE;',
288
+ '}',''].join("\n"), @q.to_dot.gsub(/NODE[0-9]*/, 'NODE'))
289
+ end
290
+
291
+ end
292
+
293
+ class PoorPriorityQueueTest < Test::Unit::TestCase
294
+ include PriorityQueueTest
295
+
296
+ def setup
297
+ @q = PoorPriorityQueue.new
298
+ end
299
+
300
+ end
301
+
302
+ class RubyPriorityQueueTest < Test::Unit::TestCase
303
+ include PriorityQueueTest
304
+
305
+ def setup
306
+ @q = RubyPriorityQueue.new
307
+ end
308
+
309
+ def test_private_link_nodes
310
+ q = RubyPriorityQueue.new
311
+ q[0] = 0
312
+ q[1] = 1
313
+ tc = self
314
+ q.instance_eval do
315
+ n0 = @nodes[0]
316
+ n1 = @nodes[1]
317
+ n0.right = n0.left = n0
318
+ n1.right = n1.left = n1
319
+ tc.assert_equal(n0, link_nodes(n0, n1))
320
+ tc.assert_equal(n0.child, n1)
321
+ tc.assert_equal(n1.child, nil)
322
+ tc.assert_equal(n0.left, n0)
323
+ tc.assert_equal(n1.left, n1)
324
+ tc.assert_equal(n0.right, n0)
325
+ tc.assert_equal(n1.right, n1)
326
+ end
327
+ q = RubyPriorityQueue.new
328
+ q[0] = 0
329
+ q[1] = 1
330
+ q.instance_eval do
331
+ n0 = @nodes[0]
332
+ n1 = @nodes[1]
333
+ n0.right = n0.left = n0
334
+ n1.right = n1.left = n1
335
+ tc.assert_equal(n0, link_nodes(n1, n0))
336
+ tc.assert_equal(n0.child, n1)
337
+ tc.assert_equal(n1.child, nil)
338
+ tc.assert_equal(n0.left, n0)
339
+ tc.assert_equal(n1.left, n1)
340
+ tc.assert_equal(n0.right, n0)
341
+ tc.assert_equal(n1.right, n1)
342
+ end
343
+ end
344
+
345
+
346
+ def test_private_delete_first
347
+ q = RubyPriorityQueue.new
348
+ q[0] = 0
349
+ q[1] = 1
350
+ q[2] = 2
351
+ tc = self
352
+ q.instance_eval do
353
+ 2.times do
354
+ r = @rootlist
355
+ tc.assert_equal(r, delete_first)
356
+ tc.assert_equal(r.right, r)
357
+ tc.assert_equal(r.left, r)
358
+ tc.assert_not_equal(r, @rootlist.left)
359
+ tc.assert_not_equal(r, @rootlist.right)
360
+ end
361
+ r = @rootlist
362
+ tc.assert_equal(r, delete_first)
363
+ tc.assert_equal(r.right, r)
364
+ tc.assert_equal(r.left, r)
365
+ tc.assert_equal(nil, @rootlist)
366
+
367
+ tc.assert_equal(nil, delete_first)
368
+ end
369
+ end
370
+ end
371
+