algorithms 0.0.1 → 0.1.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.
Files changed (54) hide show
  1. data/History.txt +139 -2
  2. data/Manifest +31 -8
  3. data/README +90 -0
  4. data/Rakefile +22 -9
  5. data/algorithms.gemspec +28 -101
  6. data/benchmark.rb +29 -27
  7. data/benchmarks/rbench.rb +16 -0
  8. data/benchmarks/rbench/column.rb +26 -0
  9. data/benchmarks/rbench/group.rb +43 -0
  10. data/benchmarks/rbench/report.rb +53 -0
  11. data/benchmarks/rbench/runner.rb +109 -0
  12. data/benchmarks/rbench/summary.rb +51 -0
  13. data/benchmarks/sorts.rb +33 -0
  14. data/ext/containers/bst/bst.c +205 -0
  15. data/ext/containers/{priority_queue → bst}/extconf.rb +1 -1
  16. data/ext/containers/deque/deque.c +233 -0
  17. data/ext/containers/deque/extconf.rb +4 -0
  18. data/ext/containers/tree_map/extconf.rb +1 -1
  19. data/ext/containers/tree_map/rbtree.c +73 -25
  20. data/lib/algorithms.rb +65 -6
  21. data/lib/algorithms/search.rb +84 -0
  22. data/lib/algorithms/sort.rb +238 -0
  23. data/lib/containers/deque.rb +176 -0
  24. data/lib/containers/heap.rb +451 -111
  25. data/lib/containers/kd_tree.rb +87 -0
  26. data/lib/containers/priority_queue.rb +107 -508
  27. data/lib/containers/queue.rb +62 -23
  28. data/lib/containers/rb_tree_map.rb +398 -0
  29. data/lib/containers/splay_tree_map.rb +274 -0
  30. data/lib/containers/stack.rb +59 -21
  31. data/lib/containers/suffix_array.rb +68 -0
  32. data/lib/containers/trie.rb +182 -0
  33. data/lib/graphs/graph.rb +25 -0
  34. data/spec/bst_spec.rb +31 -0
  35. data/spec/deque_spec.rb +108 -0
  36. data/spec/heap_spec.rb +111 -66
  37. data/spec/kd_tree_spec.rb +89 -0
  38. data/spec/priority_queue_spec.rb +71 -27
  39. data/spec/queue_spec.rb +53 -45
  40. data/spec/rb_tree_map_spec.rb +123 -0
  41. data/spec/search_spec.rb +28 -0
  42. data/spec/sort_spec.rb +28 -0
  43. data/spec/splay_tree_map_spec.rb +102 -0
  44. data/spec/stack_spec.rb +56 -49
  45. data/spec/suffix_array_spec.rb +40 -0
  46. data/spec/trie_spec.rb +59 -0
  47. metadata +54 -32
  48. data/README.txt +0 -58
  49. data/ext/containers/priority_queue/priority_queue.c +0 -948
  50. data/ext/containers/tree_map/Rakefile +0 -4
  51. data/lib/containers/hash.rb +0 -0
  52. data/lib/containers/tree_map.rb +0 -265
  53. data/spec/priority_queue_test.rb +0 -371
  54. data/spec/tree_map_spec.rb +0 -99
@@ -1,53 +1,61 @@
1
- require 'lib/algorithms'
1
+ $: << File.join(File.expand_path(File.dirname(__FILE__)), '..', 'lib')
2
+ require 'algorithms'
2
3
 
3
- describe Containers::Queue do
4
+ describe "empty queue" do
4
5
  before(:each) do
5
6
  @queue = Containers::Queue.new
6
7
  end
7
-
8
- describe "(empty)" do
9
- it "should return nil when sent #get" do
10
- @queue.get.should eql(nil)
11
- end
12
8
 
13
- it "should return a size of 1 when sent #put" do
14
- @queue.put(1).size.should eql(1)
15
- end
16
-
17
- it "should return nil when peeked" do
18
- @queue.peek.should eql(nil)
19
- end
20
-
21
- it "should return empty?" do
22
- @queue.empty?.should eql(true)
23
- end
9
+
10
+ it "should return nil when sent #pop" do
11
+ @queue.pop.should be_nil
24
12
  end
25
-
26
- describe "(non-empty)" do
27
- before(:each) do
28
- @queue.put(10)
29
- @queue.put("10")
30
- end
31
-
32
- it "should return first put object" do
33
- @queue.get.should eql(10)
34
- end
35
-
36
- it "should return the size" do
37
- @queue.size.should eql(2)
38
- end
39
-
40
- it "should not return empty?" do
41
- @queue.empty?.should eql(false)
42
- end
43
-
44
- it "should return nil after all gets" do
45
- @queue.get
46
- @queue.get
47
- @queue.get.should eql(nil)
48
- @queue.peek.should eql(nil)
13
+
14
+ it "should return a size of 1 when sent #push" do
15
+ @queue.push(1)
16
+ @queue.size.should eql(1)
17
+ end
18
+
19
+ it "should return nil when sent #next" do
20
+ @queue.next.should be_nil
21
+ end
22
+
23
+ it "should return empty?" do
24
+ @queue.empty?.should be_true
25
+ end
26
+ end
27
+
28
+ describe "non-empty queue" do
29
+ before(:each) do
30
+ @queue = Containers::Queue.new
31
+ @queue.push(10)
32
+ @queue.push("10")
33
+ end
34
+
35
+ it "should return first pushed object" do
36
+ @queue.pop.should eql(10)
37
+ end
38
+
39
+ it "should return the size" do
40
+ @queue.size.should eql(2)
41
+ end
42
+
43
+ it "should not return empty?" do
44
+ @queue.empty?.should be_false
45
+ end
46
+
47
+ it "should iterate in FIFO order" do
48
+ arr = []
49
+ @queue.each { |obj| arr << obj }
50
+ arr.should eql([10, "10"])
51
+ end
52
+
53
+ it "should return nil after all gets" do
54
+ 2.times do
55
+ @queue.pop
49
56
  end
50
-
57
+ @queue.pop.should be_nil
58
+ @queue.next.should be_nil
51
59
  end
52
-
53
- end
60
+
61
+ end
@@ -0,0 +1,123 @@
1
+ $: << File.join(File.expand_path(File.dirname(__FILE__)), '..', 'lib')
2
+ require 'algorithms'
3
+
4
+ describe "empty rbtree", :shared => true do
5
+ it "should let you push stuff in" do
6
+ 100.times { |x| @tree[x] = x }
7
+ @tree.size.should eql(100)
8
+ end
9
+
10
+ it "should be empty?" do
11
+ @tree.empty?.should be_true
12
+ end
13
+
14
+ it "should return 0 for height" do
15
+ @tree.height.should eql(0)
16
+ end
17
+
18
+ it "should return 0 for size" do
19
+ @tree.size.should eql(0)
20
+ end
21
+
22
+ it "should return nil for max and min" do
23
+ @tree.min.should be_nil
24
+ @tree.max.should be_nil
25
+ @tree.min_key.should be_nil
26
+ @tree.max_key.should be_nil
27
+ end
28
+
29
+ it "should not delete" do
30
+ @tree.delete(:non_existing).should be_nil
31
+ end
32
+ end
33
+
34
+ describe "non-empty rbtree", :shared => true do
35
+ before(:each) do
36
+ @num_items = 1000
37
+ @random_array = Array.new(@num_items) { rand(@num_items) }
38
+ @random_array.each { |x| @tree[x] = x }
39
+ end
40
+
41
+ it "should return correct size (uniqify items first)" do
42
+ @tree.should_not be_empty
43
+ @tree.size.should eql(@random_array.uniq.size)
44
+ end
45
+
46
+ it "should return correct max and min" do
47
+ @tree.min_key.should eql(@random_array.min)
48
+ @tree.max_key.should eql(@random_array.max)
49
+ @tree.min[0].should eql(@random_array.min)
50
+ @tree.max[0].should eql(@random_array.max)
51
+ end
52
+
53
+ it "should not #has_key? keys it doesn't have" do
54
+ @tree.has_key?(100000).should be_false
55
+ end
56
+
57
+ it "should #has_key? keys it does have" do
58
+ @tree.has_key?(@random_array[0]).should be_true
59
+ end
60
+
61
+ it "should remove all keys" do
62
+ ordered = []
63
+ @random_array.uniq.each do |key|
64
+ @tree.has_key?(key).should eql(true)
65
+ ordered << @tree.delete(key)
66
+ @tree.has_key?(key).should eql(false)
67
+ end
68
+ ordered.should eql(@random_array.uniq)
69
+ end
70
+
71
+ it "should delete_min keys correctly" do
72
+ ascending = []
73
+ ascending << @tree.delete_min until @tree.empty?
74
+ ascending.should eql(@random_array.uniq.sort)
75
+ end
76
+
77
+ it "should delete_max keys correctly" do
78
+ descending = []
79
+ descending << @tree.delete_max until @tree.empty?
80
+ descending.should eql(@random_array.uniq.sort.reverse)
81
+ end
82
+
83
+ it "should let you iterate with #each" do
84
+ counter = 0
85
+ sorted_array = @random_array.uniq.sort
86
+ @tree.each do |key, val|
87
+ key.should eql(sorted_array[counter])
88
+ counter += 1
89
+ end
90
+ end
91
+ end
92
+
93
+ describe "empty rbtreemap" do
94
+ before(:each) do
95
+ @tree = Containers::RubyRBTreeMap.new
96
+ end
97
+ it_should_behave_like "empty rbtree"
98
+ end
99
+
100
+ describe "full rbtreemap" do
101
+ before(:each) do
102
+ @tree = Containers::RubyRBTreeMap.new
103
+ end
104
+ it_should_behave_like "non-empty rbtree"
105
+ end
106
+
107
+ begin
108
+ Containers::CRBTreeMap
109
+ describe "empty crbtreemap" do
110
+ before(:each) do
111
+ @tree = Containers::CRBTreeMap.new
112
+ end
113
+ it_should_behave_like "empty rbtree"
114
+ end
115
+
116
+ describe "full crbtreemap" do
117
+ before(:each) do
118
+ @tree = Containers::CRBTreeMap.new
119
+ end
120
+ it_should_behave_like "non-empty rbtree"
121
+ end
122
+ rescue Exception
123
+ end
@@ -0,0 +1,28 @@
1
+ $: << File.join(File.expand_path(File.dirname(__FILE__)), '..', 'lib')
2
+ require 'algorithms'
3
+
4
+ class String; include Algorithms::Search; end
5
+
6
+ describe "search algorithms" do
7
+ it "should binary search sorted arrays" do
8
+ n = 1000
9
+ @rand_array = Array.new(n) { rand(n) }.sort
10
+
11
+ Algorithms::Search.binary_search(@rand_array, @rand_array.first).should eql(@rand_array.first)
12
+ Algorithms::Search.binary_search(@rand_array, 999999).should be_nil
13
+ Algorithms::Search.binary_search(@rand_array, nil).should be_nil
14
+ end
15
+
16
+ it "should use kmp_search to find substrings it has" do
17
+ string = "ABC ABCDAB ABCDABCDABDE"
18
+ Algorithms::Search.kmp_search(string, "ABCDABD").should eql(15)
19
+ Algorithms::Search.kmp_search(string, "ABCDEF").should be_nil
20
+ Algorithms::Search.kmp_search(string, nil).should be_nil
21
+ Algorithms::Search.kmp_search(string, "").should be_nil
22
+ Algorithms::Search.kmp_search(nil, "ABCD").should be_nil
23
+ end
24
+
25
+ it "should let you include Search in String to enable instance methods" do
26
+ "ABC ABCDAB ABCDABCDABDE".kmp_search("ABCDABD").should eql(15)
27
+ end
28
+ end
@@ -0,0 +1,28 @@
1
+ $: << File.join(File.expand_path(File.dirname(__FILE__)), '..', 'lib')
2
+ require 'algorithms'
3
+ include Algorithms
4
+
5
+ describe "sort algorithms" do
6
+ before(:each) do
7
+ @sorts = %w(bubble_sort comb_sort selection_sort heapsort insertion_sort shell_sort quicksort mergesort)
8
+ end
9
+
10
+ it "should work for empty containers" do
11
+ empty_array = []
12
+ @sorts.each { |sort| Sort.send(sort, empty_array).should eql([]) }
13
+ end
14
+
15
+ it "should work for a container of size 1" do
16
+ one_array = [1]
17
+ @sorts.each { |sort| Sort.send(sort, one_array).should eql(one_array) }
18
+ end
19
+
20
+ it "should work for random arrays of numbers" do
21
+ n = 500
22
+ rand_array = Array.new(n) { rand(n) }
23
+ sorted_array = rand_array.sort
24
+
25
+ @sorts.each { |sort| Sort.send(sort, rand_array.dup).should eql(sorted_array) }
26
+ end
27
+
28
+ end
@@ -0,0 +1,102 @@
1
+ $: << File.join(File.expand_path(File.dirname(__FILE__)), '..', 'lib')
2
+ require 'algorithms'
3
+
4
+ describe "(empty splay)", :shared => true do
5
+ it "should let you push stuff in" do
6
+ 100.times { |x| @tree[x] = x }
7
+ @tree.size.should eql(100)
8
+ end
9
+
10
+ it "should return 0 for size" do
11
+ @tree.size.should eql(0)
12
+ end
13
+
14
+ it "should return nil for #min and #max" do
15
+ @tree.min.should be_nil
16
+ @tree.max.should be_nil
17
+ end
18
+
19
+ it "should return nil for #delete" do
20
+ @tree.delete(:non_existing).should be_nil
21
+ end
22
+ end
23
+
24
+ describe "(non-empty splay)", :shared => true do
25
+ before(:each) do
26
+ @num_items = 100
27
+ @random_array = []
28
+ @num_items.times { @random_array << rand(@num_items) }
29
+ @random_array.each { |x| @tree[x] = x }
30
+ end
31
+
32
+ it "should return correct size (uniqify items first)" do
33
+ @tree.size.should eql(@random_array.uniq.size)
34
+ end
35
+
36
+ it "should have correct height (worst case is when items are inserted in order, and height = num items inserted)" do
37
+ @tree.clear
38
+ 10.times { |x| @tree[x] = x }
39
+ @tree.height.should eql(10)
40
+ end
41
+
42
+ it "should return correct max and min keys" do
43
+ @tree.min[0].should eql(@random_array.min)
44
+ @tree.max[0].should eql(@random_array.max)
45
+ end
46
+
47
+ it "should not #has_key? keys it doesn't have" do
48
+ @tree.has_key?(10000).should be_false
49
+ end
50
+
51
+ it "should #has_key? keys it does have" do
52
+ @tree.has_key?(@random_array[0]).should be_true
53
+ end
54
+
55
+ it "should remove any key" do
56
+ random_key = @random_array[rand(@num_items)]
57
+ @tree.has_key?(random_key).should be_true
58
+ @tree.delete(random_key).should eql(random_key)
59
+ @tree.has_key?(random_key).should be_false
60
+ end
61
+
62
+ it "should let you iterate with #each" do
63
+ counter = 0
64
+ sorted_array = @random_array.uniq.sort
65
+ @tree.each do |key, val|
66
+ key.should eql(sorted_array[counter])
67
+ counter += 1
68
+ end
69
+ end
70
+ end
71
+
72
+ # describe Containers::CRBTreeMap do
73
+ # describe "empty" do
74
+ # before(:each) do
75
+ # @tree = Containers::CRBTreeMap.new
76
+ # end
77
+ # it_should_behave_like "(empty)"
78
+ # end
79
+ #
80
+ # describe "full" do
81
+ # before(:each) do
82
+ # @tree = Containers::CRBTreeMap.new
83
+ # end
84
+ # it_should_behave_like "(non-empty)"
85
+ # end
86
+ # end
87
+
88
+ # describe Containers::SplayTreeMap do
89
+ describe "empty splaytreemap" do
90
+ before(:each) do
91
+ @tree = Containers::SplayTreeMap.new
92
+ end
93
+ it_should_behave_like "(empty splay)"
94
+ end
95
+
96
+ describe "full splaytreemap" do
97
+ before(:each) do
98
+ @tree = Containers::SplayTreeMap.new
99
+ end
100
+ it_should_behave_like "(non-empty splay)"
101
+ end
102
+ # end
@@ -1,53 +1,60 @@
1
- require 'lib/algorithms'
1
+ $: << File.join(File.expand_path(File.dirname(__FILE__)), '..', 'lib')
2
+ require 'algorithms'
2
3
 
3
- describe Containers::Stack do
4
+ describe "empty stack" do
4
5
  before(:each) do
5
6
  @stack = Containers::Stack.new
6
7
  end
7
-
8
- describe "(empty)" do
9
- it "should return nil when sent #pop" do
10
- @stack.pop.should eql(nil)
11
- end
12
-
13
- it "should return a size of 1 when sent #push" do
14
- @stack.push(1).size.should eql(1)
15
- end
16
-
17
- it "should return nil when peeked" do
18
- @stack.peek.should eql(nil)
19
- end
20
-
21
- it "should return empty?" do
22
- @stack.empty?.should eql(true)
23
- end
24
- end
25
-
26
- describe "(non-empty)" do
27
- before(:each) do
28
- @stack.push(10)
29
- @stack.push("10")
30
- end
31
-
32
- it "should return last pushed object" do
33
- @stack.pop.should eql("10")
34
- end
35
-
36
- it "should return the size" do
37
- @stack.size.should eql(2)
38
- end
39
-
40
- it "should not return empty?" do
41
- @stack.empty?.should eql(false)
42
- end
43
-
44
- it "should return nil after all pops" do
45
- @stack.pop
46
- @stack.pop
47
- @stack.pop.should eql(nil)
48
- @stack.peek.should eql(nil)
49
- end
50
-
51
- end
52
-
53
- end
8
+
9
+ it "should return nil when sent #pop" do
10
+ @stack.pop.should be_nil
11
+ end
12
+
13
+ it "should return a size of 1 when sent #push" do
14
+ @stack.push(1)
15
+ @stack.size.should eql(1)
16
+ end
17
+
18
+ it "should return nil when sent #next" do
19
+ @stack.next.should be_nil
20
+ end
21
+
22
+ it "should return empty?" do
23
+ @stack.empty?.should be_true
24
+ end
25
+ end
26
+
27
+ describe "non-empty stack" do
28
+ before(:each) do
29
+ @stack = Containers::Stack.new
30
+ @stack.push(10)
31
+ @stack.push("10")
32
+ end
33
+
34
+ it "should return last pushed object" do
35
+ @stack.pop.should eql("10")
36
+ end
37
+
38
+ it "should return the size" do
39
+ @stack.size.should eql(2)
40
+ end
41
+
42
+ it "should not return empty?" do
43
+ @stack.empty?.should be_false
44
+ end
45
+
46
+
47
+ it "should iterate in LIFO order" do
48
+ arr = []
49
+ @stack.each { |obj| arr << obj }
50
+ arr.should eql(["10", 10])
51
+ end
52
+
53
+ it "should return nil after all pops" do
54
+ @stack.pop
55
+ @stack.pop
56
+ @stack.pop.should be_nil
57
+ @stack.next.should be_nil
58
+ end
59
+
60
+ end