algorithms 0.6.1 → 1.0.0
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 +7 -0
- data/README.markdown +4 -22
- data/Rakefile +4 -0
- data/algorithms.gemspec +2 -3
- data/ext/algorithms/string/string.c +2 -2
- data/ext/containers/bst/bst.c +1 -1
- data/ext/containers/deque/deque.c +2 -2
- data/ext/containers/rbtree_map/rbtree.c +6 -6
- data/ext/containers/splaytree_map/splaytree.c +4 -4
- data/lib/algorithms.rb +1 -0
- data/lib/algorithms/sort.rb +130 -0
- data/spec/deque_gc_mark_spec.rb +1 -1
- data/spec/deque_spec.rb +18 -18
- data/spec/heap_spec.rb +25 -25
- data/spec/kd_tree_spec.rb +2 -2
- data/spec/map_gc_mark_spec.rb +2 -2
- data/spec/priority_queue_spec.rb +20 -20
- data/spec/queue_spec.rb +10 -10
- data/spec/rb_tree_map_spec.rb +23 -23
- data/spec/search_spec.rb +9 -9
- data/spec/sort_spec.rb +6 -5
- data/spec/splay_tree_map_spec.rb +16 -16
- data/spec/stack_spec.rb +10 -10
- data/spec/string_spec.rb +6 -6
- data/spec/suffix_array_spec.rb +17 -17
- data/spec/trie_spec.rb +16 -16
- metadata +12 -15
data/spec/heap_spec.rb
CHANGED
@@ -7,29 +7,29 @@ describe Containers::Heap do
|
|
7
7
|
end
|
8
8
|
|
9
9
|
it "should not let you merge with non-heaps" do
|
10
|
-
|
11
|
-
|
10
|
+
expect { @heap.merge!(nil) }.to raise_error(ArgumentError)
|
11
|
+
expect { @heap.merge!([]) }.to raise_error(ArgumentError)
|
12
12
|
end
|
13
13
|
|
14
14
|
describe "(empty)" do
|
15
15
|
|
16
16
|
it "should return nil when getting the maximum" do
|
17
|
-
@heap.max
|
17
|
+
expect(@heap.max!).to be_nil
|
18
18
|
end
|
19
19
|
|
20
20
|
it "should let you insert and remove one item" do
|
21
|
-
@heap.size.
|
21
|
+
expect(@heap.size).to eql(0)
|
22
22
|
|
23
23
|
@heap.push(1)
|
24
|
-
@heap.size.
|
24
|
+
expect(@heap.size).to eql(1)
|
25
25
|
|
26
|
-
@heap.max
|
27
|
-
@heap.size.
|
26
|
+
expect(@heap.max!).to eql(1)
|
27
|
+
expect(@heap.size).to eql(0)
|
28
28
|
end
|
29
29
|
|
30
30
|
it "should let you initialize with an array" do
|
31
31
|
@heap = Containers::MaxHeap.new([1,2,3])
|
32
|
-
@heap.size.
|
32
|
+
expect(@heap.size).to eql(3)
|
33
33
|
end
|
34
34
|
|
35
35
|
end
|
@@ -38,25 +38,25 @@ describe Containers::Heap do
|
|
38
38
|
before(:each) do
|
39
39
|
@random_array = []
|
40
40
|
@num_items = 100
|
41
|
-
@num_items.times {
|
41
|
+
@num_items.times { @random_array << rand(@num_items) }
|
42
42
|
@heap = Containers::MaxHeap.new(@random_array)
|
43
43
|
end
|
44
44
|
|
45
45
|
it "should display the correct size" do
|
46
|
-
@heap.size.
|
46
|
+
expect(@heap.size).to eql(@num_items)
|
47
47
|
end
|
48
48
|
|
49
49
|
it "should have a next value" do
|
50
|
-
@heap.next.
|
51
|
-
@heap.next_key.
|
50
|
+
expect(@heap.next).to be_truthy
|
51
|
+
expect(@heap.next_key).to be_truthy
|
52
52
|
end
|
53
53
|
|
54
54
|
it "should delete random keys" do
|
55
|
-
@heap.delete(@random_array[0]).
|
56
|
-
@heap.delete(@random_array[1]).
|
55
|
+
expect(@heap.delete(@random_array[0])).to eql(@random_array[0])
|
56
|
+
expect(@heap.delete(@random_array[1])).to eql(@random_array[1])
|
57
57
|
ordered = []
|
58
58
|
ordered << @heap.max! until @heap.empty?
|
59
|
-
ordered.
|
59
|
+
expect(ordered).to eql( @random_array[2..-1].sort.reverse )
|
60
60
|
end
|
61
61
|
|
62
62
|
it "should delete all keys" do
|
@@ -64,15 +64,15 @@ describe Containers::Heap do
|
|
64
64
|
@random_array.size.times do |t|
|
65
65
|
ordered << @heap.delete(@random_array[t])
|
66
66
|
end
|
67
|
-
@heap.
|
68
|
-
ordered.
|
67
|
+
expect(@heap).to be_empty
|
68
|
+
expect(ordered).to eql( @random_array )
|
69
69
|
end
|
70
70
|
|
71
71
|
it "should be in max->min order" do
|
72
72
|
ordered = []
|
73
73
|
ordered << @heap.max! until @heap.empty?
|
74
74
|
|
75
|
-
ordered.
|
75
|
+
expect(ordered).to eql(@random_array.sort.reverse)
|
76
76
|
end
|
77
77
|
|
78
78
|
it "should change certain keys" do
|
@@ -84,12 +84,12 @@ describe Containers::Heap do
|
|
84
84
|
heap.change_key(8, 0)
|
85
85
|
ordered = []
|
86
86
|
ordered << heap.min! until heap.empty?
|
87
|
-
ordered.
|
87
|
+
expect(ordered).to eql( [8,3,4,5,6,7,9,10,101,100] )
|
88
88
|
end
|
89
89
|
|
90
90
|
it "should not delete keys it doesn't have" do
|
91
|
-
@heap.delete(:nonexisting).
|
92
|
-
@heap.size.
|
91
|
+
expect(@heap.delete(:nonexisting)).to be_nil
|
92
|
+
expect(@heap.size).to eql(@num_items)
|
93
93
|
end
|
94
94
|
|
95
95
|
it "should delete certain keys" do
|
@@ -101,19 +101,19 @@ describe Containers::Heap do
|
|
101
101
|
heap.delete(100)
|
102
102
|
ordered = []
|
103
103
|
ordered << heap.min! until heap.empty?
|
104
|
-
ordered.
|
104
|
+
expect(ordered).to eql( [3,4,6,7,8,9,10,101] )
|
105
105
|
end
|
106
106
|
|
107
107
|
it "should let you merge with another heap" do
|
108
108
|
numbers = [1,2,3,4,5,6,7,8]
|
109
109
|
otherheap = Containers::MaxHeap.new(numbers)
|
110
|
-
otherheap.size.
|
110
|
+
expect(otherheap.size).to eql(8)
|
111
111
|
@heap.merge!(otherheap)
|
112
112
|
|
113
113
|
ordered = []
|
114
114
|
ordered << @heap.max! until @heap.empty?
|
115
115
|
|
116
|
-
ordered.
|
116
|
+
expect(ordered).to eql( (@random_array + numbers).sort.reverse)
|
117
117
|
end
|
118
118
|
|
119
119
|
describe "min-heap" do
|
@@ -122,7 +122,7 @@ describe Containers::Heap do
|
|
122
122
|
ordered = []
|
123
123
|
ordered << @heap.min! until @heap.empty?
|
124
124
|
|
125
|
-
ordered.
|
125
|
+
expect(ordered).to eql(@random_array.sort)
|
126
126
|
end
|
127
127
|
end
|
128
128
|
|
data/spec/kd_tree_spec.rb
CHANGED
@@ -6,7 +6,7 @@ describe Containers::KDTree do
|
|
6
6
|
kdtree = Containers::KDTree.new( {0 => [4, 3], 1 => [3, 0], 2 => [-1, 2], 3 => [6, 4],
|
7
7
|
4 => [3, -5], 5 => [-2, -5] })
|
8
8
|
closest_2 = kdtree.find_nearest([0, 0], 2)
|
9
|
-
closest_2.
|
9
|
+
expect(closest_2).to eql([[5, 2], [9, 1]])
|
10
10
|
end
|
11
11
|
|
12
12
|
it "should work for real-life example from facebook puzzle" do
|
@@ -28,7 +28,7 @@ describe Containers::KDTree do
|
|
28
28
|
}
|
29
29
|
|
30
30
|
expected = File.read(File.join(File.dirname(__FILE__), 'kd_expected_out.txt'))
|
31
|
-
expected.
|
31
|
+
expect(expected).to eql(out)
|
32
32
|
end
|
33
33
|
|
34
34
|
end
|
data/spec/map_gc_mark_spec.rb
CHANGED
@@ -21,9 +21,9 @@ if !(defined? RUBY_ENGINE && RUBY_ENGINE == 'jruby')
|
|
21
21
|
# Check if any instances were swept
|
22
22
|
count = 0
|
23
23
|
ObjectSpace.each_object(anon_key_class) { |x| count += 1 }
|
24
|
-
count.
|
24
|
+
expect(count).to eql(200)
|
25
25
|
ObjectSpace.each_object(anon_val_class) { |x| count += 1 }
|
26
|
-
count.
|
26
|
+
expect(count).to eql(400)
|
27
27
|
end
|
28
28
|
end
|
29
29
|
end
|
data/spec/priority_queue_spec.rb
CHANGED
@@ -8,32 +8,32 @@ describe Containers::PriorityQueue do
|
|
8
8
|
|
9
9
|
describe "(empty priority queue)" do
|
10
10
|
it "should return 0 for size and be empty" do
|
11
|
-
@q.size.
|
12
|
-
@q.
|
11
|
+
expect(@q.size).to eql(0)
|
12
|
+
expect(@q).to be_empty
|
13
13
|
end
|
14
14
|
|
15
15
|
it "should not return anything" do
|
16
|
-
@q.next.
|
17
|
-
@q.pop.
|
18
|
-
@q.delete(1).
|
19
|
-
@q.has_priority?(1).
|
16
|
+
expect(@q.next).to be_nil
|
17
|
+
expect(@q.pop).to be_nil
|
18
|
+
expect(@q.delete(1)).to be_nil
|
19
|
+
expect(@q.has_priority?(1)).to be false
|
20
20
|
end
|
21
21
|
|
22
22
|
it "should give the correct size when adding items" do
|
23
23
|
20.times do |i|
|
24
|
-
@q.size.
|
24
|
+
expect(@q.size).to eql(i)
|
25
25
|
@q.push(i, i)
|
26
26
|
end
|
27
27
|
10.times do |i|
|
28
|
-
@q.size.
|
28
|
+
expect(@q.size).to eql(20-i)
|
29
29
|
@q.pop
|
30
30
|
end
|
31
31
|
10.times do |i|
|
32
|
-
@q.size.
|
32
|
+
expect(@q.size).to eql(i+10)
|
33
33
|
@q.push(i, i)
|
34
34
|
end
|
35
35
|
@q.delete(5)
|
36
|
-
@q.size.
|
36
|
+
expect(@q.size).to eql(19)
|
37
37
|
end
|
38
38
|
end
|
39
39
|
|
@@ -45,31 +45,31 @@ describe Containers::PriorityQueue do
|
|
45
45
|
end
|
46
46
|
|
47
47
|
it "should next/pop the highest priority" do
|
48
|
-
@q.next.
|
49
|
-
@q.size.
|
50
|
-
@q.pop.
|
51
|
-
@q.size.
|
48
|
+
expect(@q.next).to eql("Alaska")
|
49
|
+
expect(@q.size).to eql(3)
|
50
|
+
expect(@q.pop).to eql("Alaska")
|
51
|
+
expect(@q.size).to eql(2)
|
52
52
|
end
|
53
53
|
|
54
54
|
it "should not be empty" do
|
55
|
-
@q.
|
55
|
+
expect(@q).not_to be_empty
|
56
56
|
end
|
57
57
|
|
58
58
|
it "should has_priority? priorities it has" do
|
59
|
-
@q.has_priority?(50).
|
60
|
-
@q.has_priority?(10).
|
59
|
+
expect(@q.has_priority?(50)).to be true
|
60
|
+
expect(@q.has_priority?(10)).to be false
|
61
61
|
end
|
62
62
|
|
63
63
|
it "should return nil after popping everything" do
|
64
64
|
3.times do
|
65
65
|
@q.pop
|
66
66
|
end
|
67
|
-
@q.pop.
|
67
|
+
expect(@q.pop).to be_nil
|
68
68
|
end
|
69
69
|
|
70
70
|
it "should delete things it has and not things it doesn't" do
|
71
|
-
@q.delete(50).
|
72
|
-
@q.delete(10).
|
71
|
+
expect(@q.delete(50)).to eql("Alaska")
|
72
|
+
expect(@q.delete(10)).to eql(nil)
|
73
73
|
end
|
74
74
|
end
|
75
75
|
end
|
data/spec/queue_spec.rb
CHANGED
@@ -8,20 +8,20 @@ describe "empty queue" do
|
|
8
8
|
|
9
9
|
|
10
10
|
it "should return nil when sent #pop" do
|
11
|
-
@queue.pop.
|
11
|
+
expect(@queue.pop).to be_nil
|
12
12
|
end
|
13
13
|
|
14
14
|
it "should return a size of 1 when sent #push" do
|
15
15
|
@queue.push(1)
|
16
|
-
@queue.size.
|
16
|
+
expect(@queue.size).to eql(1)
|
17
17
|
end
|
18
18
|
|
19
19
|
it "should return nil when sent #next" do
|
20
|
-
@queue.next.
|
20
|
+
expect(@queue.next).to be_nil
|
21
21
|
end
|
22
22
|
|
23
23
|
it "should return empty?" do
|
24
|
-
@queue.empty
|
24
|
+
expect(@queue.empty?).to be true
|
25
25
|
end
|
26
26
|
end
|
27
27
|
|
@@ -33,29 +33,29 @@ describe "non-empty queue" do
|
|
33
33
|
end
|
34
34
|
|
35
35
|
it "should return first pushed object" do
|
36
|
-
@queue.pop.
|
36
|
+
expect(@queue.pop).to eql(10)
|
37
37
|
end
|
38
38
|
|
39
39
|
it "should return the size" do
|
40
|
-
@queue.size.
|
40
|
+
expect(@queue.size).to eql(2)
|
41
41
|
end
|
42
42
|
|
43
43
|
it "should not return empty?" do
|
44
|
-
@queue.empty
|
44
|
+
expect(@queue.empty?).to be false
|
45
45
|
end
|
46
46
|
|
47
47
|
it "should iterate in FIFO order" do
|
48
48
|
arr = []
|
49
49
|
@queue.each { |obj| arr << obj }
|
50
|
-
arr.
|
50
|
+
expect(arr).to eql([10, "10"])
|
51
51
|
end
|
52
52
|
|
53
53
|
it "should return nil after all gets" do
|
54
54
|
2.times do
|
55
55
|
@queue.pop
|
56
56
|
end
|
57
|
-
@queue.pop.
|
58
|
-
@queue.next.
|
57
|
+
expect(@queue.pop).to be_nil
|
58
|
+
expect(@queue.next).to be_nil
|
59
59
|
end
|
60
60
|
|
61
61
|
end
|
data/spec/rb_tree_map_spec.rb
CHANGED
@@ -4,30 +4,30 @@ require 'algorithms'
|
|
4
4
|
shared_examples "empty rbtree" do
|
5
5
|
it "should let you push stuff in" do
|
6
6
|
100.times { |x| @tree[x] = x }
|
7
|
-
@tree.size.
|
7
|
+
expect(@tree.size).to eql(100)
|
8
8
|
end
|
9
9
|
|
10
10
|
it "should be empty?" do
|
11
|
-
@tree.empty
|
11
|
+
expect(@tree.empty?).to be true
|
12
12
|
end
|
13
13
|
|
14
14
|
it "should return 0 for height" do
|
15
|
-
@tree.height.
|
15
|
+
expect(@tree.height).to eql(0)
|
16
16
|
end
|
17
17
|
|
18
18
|
it "should return 0 for size" do
|
19
|
-
@tree.size.
|
19
|
+
expect(@tree.size).to eql(0)
|
20
20
|
end
|
21
21
|
|
22
22
|
it "should return nil for max and min" do
|
23
|
-
@tree.min.
|
24
|
-
@tree.max.
|
25
|
-
@tree.min_key.
|
26
|
-
@tree.max_key.
|
23
|
+
expect(@tree.min).to be_nil
|
24
|
+
expect(@tree.max).to be_nil
|
25
|
+
expect(@tree.min_key).to be_nil
|
26
|
+
expect(@tree.max_key).to be_nil
|
27
27
|
end
|
28
28
|
|
29
29
|
it "should not delete" do
|
30
|
-
@tree.delete(:non_existing).
|
30
|
+
expect(@tree.delete(:non_existing)).to be_nil
|
31
31
|
end
|
32
32
|
end
|
33
33
|
|
@@ -39,52 +39,52 @@ shared_examples "non-empty rbtree" do
|
|
39
39
|
end
|
40
40
|
|
41
41
|
it "should return correct size (uniqify items first)" do
|
42
|
-
@tree.
|
43
|
-
@tree.size.
|
42
|
+
expect(@tree).not_to be_empty
|
43
|
+
expect(@tree.size).to eql(@random_array.uniq.size)
|
44
44
|
end
|
45
45
|
|
46
46
|
it "should return correct max and min" do
|
47
|
-
@tree.min_key.
|
48
|
-
@tree.max_key.
|
49
|
-
@tree.min[0].
|
50
|
-
@tree.max[0].
|
47
|
+
expect(@tree.min_key).to eql(@random_array.min)
|
48
|
+
expect(@tree.max_key).to eql(@random_array.max)
|
49
|
+
expect(@tree.min[0]).to eql(@random_array.min)
|
50
|
+
expect(@tree.max[0]).to eql(@random_array.max)
|
51
51
|
end
|
52
52
|
|
53
53
|
it "should not #has_key? keys it doesn't have" do
|
54
|
-
@tree.has_key?(100000).
|
54
|
+
expect(@tree.has_key?(100000)).to be false
|
55
55
|
end
|
56
56
|
|
57
57
|
it "should #has_key? keys it does have" do
|
58
|
-
@tree.has_key?(@random_array[0]).
|
58
|
+
expect(@tree.has_key?(@random_array[0])).to be true
|
59
59
|
end
|
60
60
|
|
61
61
|
it "should remove all keys" do
|
62
62
|
ordered = []
|
63
63
|
@random_array.uniq.each do |key|
|
64
|
-
@tree.has_key?(key).
|
64
|
+
expect(@tree.has_key?(key)).to eql(true)
|
65
65
|
ordered << @tree.delete(key)
|
66
|
-
@tree.has_key?(key).
|
66
|
+
expect(@tree.has_key?(key)).to eql(false)
|
67
67
|
end
|
68
|
-
ordered.
|
68
|
+
expect(ordered).to eql(@random_array.uniq)
|
69
69
|
end
|
70
70
|
|
71
71
|
it "should delete_min keys correctly" do
|
72
72
|
ascending = []
|
73
73
|
ascending << @tree.delete_min until @tree.empty?
|
74
|
-
ascending.
|
74
|
+
expect(ascending).to eql(@random_array.uniq.sort)
|
75
75
|
end
|
76
76
|
|
77
77
|
it "should delete_max keys correctly" do
|
78
78
|
descending = []
|
79
79
|
descending << @tree.delete_max until @tree.empty?
|
80
|
-
descending.
|
80
|
+
expect(descending).to eql(@random_array.uniq.sort.reverse)
|
81
81
|
end
|
82
82
|
|
83
83
|
it "should let you iterate with #each" do
|
84
84
|
counter = 0
|
85
85
|
sorted_array = @random_array.uniq.sort
|
86
86
|
@tree.each do |key, val|
|
87
|
-
key.
|
87
|
+
expect(key).to eql(sorted_array[counter])
|
88
88
|
counter += 1
|
89
89
|
end
|
90
90
|
end
|
data/spec/search_spec.rb
CHANGED
@@ -8,21 +8,21 @@ describe "search algorithms" do
|
|
8
8
|
n = 1000
|
9
9
|
@rand_array = Array.new(n) { rand(n) }.sort
|
10
10
|
|
11
|
-
Algorithms::Search.binary_search(@rand_array, @rand_array.first).
|
12
|
-
Algorithms::Search.binary_search(@rand_array, 999999).
|
13
|
-
Algorithms::Search.binary_search(@rand_array, nil).
|
11
|
+
expect(Algorithms::Search.binary_search(@rand_array, @rand_array.first)).to eql(@rand_array.first)
|
12
|
+
expect(Algorithms::Search.binary_search(@rand_array, 999999)).to be_nil
|
13
|
+
expect(Algorithms::Search.binary_search(@rand_array, nil)).to be_nil
|
14
14
|
end
|
15
15
|
|
16
16
|
it "should use kmp_search to find substrings it has" do
|
17
17
|
string = "ABC ABCDAB ABCDABCDABDE"
|
18
|
-
Algorithms::Search.kmp_search(string, "ABCDABD").
|
19
|
-
Algorithms::Search.kmp_search(string, "ABCDEF").
|
20
|
-
Algorithms::Search.kmp_search(string, nil).
|
21
|
-
Algorithms::Search.kmp_search(string, "").
|
22
|
-
Algorithms::Search.kmp_search(nil, "ABCD").
|
18
|
+
expect(Algorithms::Search.kmp_search(string, "ABCDABD")).to eql(15)
|
19
|
+
expect(Algorithms::Search.kmp_search(string, "ABCDEF")).to be_nil
|
20
|
+
expect(Algorithms::Search.kmp_search(string, nil)).to be_nil
|
21
|
+
expect(Algorithms::Search.kmp_search(string, "")).to be_nil
|
22
|
+
expect(Algorithms::Search.kmp_search(nil, "ABCD")).to be_nil
|
23
23
|
end
|
24
24
|
|
25
25
|
it "should let you include Search in String to enable instance methods" do
|
26
|
-
"ABC ABCDAB ABCDABCDABDE".kmp_search("ABCDABD").
|
26
|
+
expect("ABC ABCDAB ABCDABCDABDE".kmp_search("ABCDABD")).to eql(15)
|
27
27
|
end
|
28
28
|
end
|