stakach-algorithms 1.0.6 → 1.0.7

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 (48) hide show
  1. data/README.markdown +99 -97
  2. data/Rakefile +15 -27
  3. data/ext/algorithms/string/extconf.rb +4 -4
  4. data/ext/algorithms/string/string.c +68 -70
  5. data/ext/containers/bst/bst.c +249 -249
  6. data/ext/containers/bst/extconf.rb +4 -4
  7. data/ext/containers/deque/deque.c +248 -248
  8. data/ext/containers/deque/extconf.rb +4 -4
  9. data/ext/containers/rbtree_map/extconf.rb +4 -4
  10. data/ext/containers/rbtree_map/rbtree.c +500 -500
  11. data/ext/containers/splaytree_map/extconf.rb +4 -4
  12. data/ext/containers/splaytree_map/splaytree.c +421 -421
  13. data/lib/algorithms.rb +69 -69
  14. data/lib/algorithms/search.rb +85 -85
  15. data/lib/algorithms/sort.rb +242 -242
  16. data/lib/algorithms/string.rb +10 -10
  17. data/lib/algorithms/version.rb +3 -3
  18. data/lib/containers/deque.rb +176 -176
  19. data/lib/containers/heap.rb +501 -506
  20. data/lib/containers/kd_tree.rb +112 -112
  21. data/lib/containers/priority_queue.rb +116 -116
  22. data/lib/containers/queue.rb +71 -71
  23. data/lib/containers/rb_tree_map.rb +402 -402
  24. data/lib/containers/splay_tree_map.rb +273 -273
  25. data/lib/containers/stack.rb +70 -70
  26. data/lib/containers/suffix_array.rb +71 -71
  27. data/lib/containers/trie.rb +187 -187
  28. data/spec/bst_gc_mark_spec.rb +25 -0
  29. data/spec/bst_spec.rb +25 -0
  30. data/spec/deque_gc_mark_spec.rb +17 -0
  31. data/spec/deque_spec.rb +107 -0
  32. data/spec/heap_spec.rb +130 -0
  33. data/spec/helper.rb +4 -0
  34. data/spec/kd_expected_out.txt +10000 -0
  35. data/spec/kd_test_in.txt +10000 -0
  36. data/spec/kd_tree_spec.rb +33 -0
  37. data/spec/map_gc_mark_spec.rb +28 -0
  38. data/spec/priority_queue_spec.rb +74 -0
  39. data/spec/queue_spec.rb +60 -0
  40. data/spec/rb_tree_map_spec.rb +122 -0
  41. data/spec/search_spec.rb +27 -0
  42. data/spec/sort_spec.rb +26 -0
  43. data/spec/splay_tree_map_spec.rb +105 -0
  44. data/spec/stack_spec.rb +59 -0
  45. data/spec/string_spec.rb +12 -0
  46. data/spec/suffix_array_spec.rb +39 -0
  47. data/spec/trie_spec.rb +58 -0
  48. metadata +60 -4
@@ -0,0 +1,33 @@
1
+ require 'helper'
2
+
3
+ describe Algorithms::Containers::KDTree do
4
+ it "should work for a documented example" do
5
+ kdtree = Algorithms::Containers::KDTree.new( {0 => [4, 3], 1 => [3, 0], 2 => [-1, 2], 3 => [6, 4],
6
+ 4 => [3, -5], 5 => [-2, -5] })
7
+ closest_2 = kdtree.find_nearest([0, 0], 2)
8
+ closest_2.should eql([[5, 2], [9, 1]])
9
+ end
10
+
11
+ it "should work for real-life example from facebook puzzle" do
12
+ points = {}
13
+ input = File.open(File.join(File.dirname(__FILE__), 'kd_test_in.txt'), 'r')
14
+
15
+ # Populate points hash
16
+ input.each_line do |line|
17
+ break if line.empty?
18
+ n, x, y = line.split(/\s+/)
19
+ points[n.to_i] = [x.to_f, y.to_f]
20
+ end
21
+
22
+ out = ""
23
+ kdtree = Algorithms::Containers::KDTree.new(points)
24
+ points.sort{ |(k1, v1), (k2, v2)| k1 <=> k2 }.each { |id, point|
25
+ nearest_4 = kdtree.find_nearest(point, 4)
26
+ out << "#{id} #{nearest_4[1..-1].collect{ |n| n[1] }.join(',')}\n"
27
+ }
28
+
29
+ expected = File.read(File.join(File.dirname(__FILE__), 'kd_expected_out.txt'))
30
+ expected.should eql(out)
31
+ end
32
+
33
+ end
@@ -0,0 +1,28 @@
1
+ require 'helper'
2
+
3
+ if RUBY_VERSION < "1.9"
4
+ describe "map gc mark test" do
5
+ it "should mark ruby object references" do
6
+ anon_key_class = Class.new do
7
+ attr :value
8
+ def initialize(x); @value = x; end
9
+ def <=>(other); value <=> other.value; end
10
+ end
11
+ anon_val_class = Class.new
12
+ @rbtree = Algorithms::Containers::CRBTreeMap.new
13
+ @splaytree = Algorithms::Containers::CSplayTreeMap.new
14
+ 100.times { |x|
15
+ @rbtree[anon_key_class.new(x)] = anon_val_class.new
16
+ @splaytree[anon_key_class.new(x)] = anon_val_class.new
17
+ }
18
+ # Mark and sweep
19
+ ObjectSpace.garbage_collect
20
+ # Check if any instances were swept
21
+ count = 0
22
+ ObjectSpace.each_object(anon_key_class) { |x| count += 1 }
23
+ count.should eql(200)
24
+ ObjectSpace.each_object(anon_val_class) { |x| count += 1 }
25
+ count.should eql(400)
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,74 @@
1
+ require 'helper'
2
+
3
+ describe Algorithms::Containers::PriorityQueue do
4
+ before(:each) do
5
+ @q = Algorithms::Containers::PriorityQueue.new
6
+ end
7
+
8
+ describe "(empty priority queue)" do
9
+ it "should return 0 for size and be empty" do
10
+ @q.size.should eql(0)
11
+ @q.should be_empty
12
+ end
13
+
14
+ it "should not return anything" do
15
+ @q.next.should be_nil
16
+ @q.pop.should be_nil
17
+ @q.delete(1).should be_nil
18
+ @q.has_priority?(1).should be_false
19
+ end
20
+
21
+ it "should give the correct size when adding items" do
22
+ 20.times do |i|
23
+ @q.size.should eql(i)
24
+ @q.push(i, i)
25
+ end
26
+ 10.times do |i|
27
+ @q.size.should eql(20-i)
28
+ @q.pop
29
+ end
30
+ 10.times do |i|
31
+ @q.size.should eql(i+10)
32
+ @q.push(i, i)
33
+ end
34
+ @q.delete(5)
35
+ @q.size.should eql(19)
36
+ end
37
+ end
38
+
39
+ describe "(non-empty priority queue)" do
40
+ before(:each) do
41
+ @q.push("Alaska", 50)
42
+ @q.push("Delaware", 30)
43
+ @q.push("Georgia", 35)
44
+ end
45
+
46
+ it "should next/pop the highest priority" do
47
+ @q.next.should eql("Alaska")
48
+ @q.size.should eql(3)
49
+ @q.pop.should eql("Alaska")
50
+ @q.size.should eql(2)
51
+ end
52
+
53
+ it "should not be empty" do
54
+ @q.should_not be_empty
55
+ end
56
+
57
+ it "should has_priority? priorities it has" do
58
+ @q.has_priority?(50).should be_true
59
+ @q.has_priority?(10).should be_false
60
+ end
61
+
62
+ it "should return nil after popping everything" do
63
+ 3.times do
64
+ @q.pop
65
+ end
66
+ @q.pop.should be_nil
67
+ end
68
+
69
+ it "should delete things it has and not things it doesn't" do
70
+ @q.delete(50).should eql("Alaska")
71
+ @q.delete(10).should eql(nil)
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,60 @@
1
+ require 'helper'
2
+
3
+ describe "empty queue" do
4
+ before(:each) do
5
+ @queue = Algorithms::Containers::Queue.new
6
+ end
7
+
8
+
9
+ it "should return nil when sent #pop" do
10
+ @queue.pop.should be_nil
11
+ end
12
+
13
+ it "should return a size of 1 when sent #push" do
14
+ @queue.push(1)
15
+ @queue.size.should eql(1)
16
+ end
17
+
18
+ it "should return nil when sent #next" do
19
+ @queue.next.should be_nil
20
+ end
21
+
22
+ it "should return empty?" do
23
+ @queue.empty?.should be_true
24
+ end
25
+ end
26
+
27
+ describe "non-empty queue" do
28
+ before(:each) do
29
+ @queue = Algorithms::Containers::Queue.new
30
+ @queue.push(10)
31
+ @queue.push("10")
32
+ end
33
+
34
+ it "should return first pushed object" do
35
+ @queue.pop.should eql(10)
36
+ end
37
+
38
+ it "should return the size" do
39
+ @queue.size.should eql(2)
40
+ end
41
+
42
+ it "should not return empty?" do
43
+ @queue.empty?.should be_false
44
+ end
45
+
46
+ it "should iterate in FIFO order" do
47
+ arr = []
48
+ @queue.each { |obj| arr << obj }
49
+ arr.should eql([10, "10"])
50
+ end
51
+
52
+ it "should return nil after all gets" do
53
+ 2.times do
54
+ @queue.pop
55
+ end
56
+ @queue.pop.should be_nil
57
+ @queue.next.should be_nil
58
+ end
59
+
60
+ end
@@ -0,0 +1,122 @@
1
+ require 'helper'
2
+
3
+ shared_examples "empty rbtree" do
4
+ it "should let you push stuff in" do
5
+ 100.times { |x| @tree[x] = x }
6
+ @tree.size.should eql(100)
7
+ end
8
+
9
+ it "should be empty?" do
10
+ @tree.empty?.should be_true
11
+ end
12
+
13
+ it "should return 0 for height" do
14
+ @tree.height.should eql(0)
15
+ end
16
+
17
+ it "should return 0 for size" do
18
+ @tree.size.should eql(0)
19
+ end
20
+
21
+ it "should return nil for max and min" do
22
+ @tree.min.should be_nil
23
+ @tree.max.should be_nil
24
+ @tree.min_key.should be_nil
25
+ @tree.max_key.should be_nil
26
+ end
27
+
28
+ it "should not delete" do
29
+ @tree.delete(:non_existing).should be_nil
30
+ end
31
+ end
32
+
33
+ shared_examples "non-empty rbtree" do
34
+ before(:each) do
35
+ @num_items = 1000
36
+ @random_array = Array.new(@num_items) { rand(@num_items) }
37
+ @random_array.each { |x| @tree[x] = x }
38
+ end
39
+
40
+ it "should return correct size (uniqify items first)" do
41
+ @tree.should_not be_empty
42
+ @tree.size.should eql(@random_array.uniq.size)
43
+ end
44
+
45
+ it "should return correct max and min" do
46
+ @tree.min_key.should eql(@random_array.min)
47
+ @tree.max_key.should eql(@random_array.max)
48
+ @tree.min[0].should eql(@random_array.min)
49
+ @tree.max[0].should eql(@random_array.max)
50
+ end
51
+
52
+ it "should not #has_key? keys it doesn't have" do
53
+ @tree.has_key?(100000).should be_false
54
+ end
55
+
56
+ it "should #has_key? keys it does have" do
57
+ @tree.has_key?(@random_array[0]).should be_true
58
+ end
59
+
60
+ it "should remove all keys" do
61
+ ordered = []
62
+ @random_array.uniq.each do |key|
63
+ @tree.has_key?(key).should eql(true)
64
+ ordered << @tree.delete(key)
65
+ @tree.has_key?(key).should eql(false)
66
+ end
67
+ ordered.should eql(@random_array.uniq)
68
+ end
69
+
70
+ it "should delete_min keys correctly" do
71
+ ascending = []
72
+ ascending << @tree.delete_min until @tree.empty?
73
+ ascending.should eql(@random_array.uniq.sort)
74
+ end
75
+
76
+ it "should delete_max keys correctly" do
77
+ descending = []
78
+ descending << @tree.delete_max until @tree.empty?
79
+ descending.should eql(@random_array.uniq.sort.reverse)
80
+ end
81
+
82
+ it "should let you iterate with #each" do
83
+ counter = 0
84
+ sorted_array = @random_array.uniq.sort
85
+ @tree.each do |key, val|
86
+ key.should eql(sorted_array[counter])
87
+ counter += 1
88
+ end
89
+ end
90
+ end
91
+
92
+ describe "empty rbtreemap" do
93
+ before(:each) do
94
+ @tree = Containers::RubyRBTreeMap.new
95
+ end
96
+ it_should_behave_like "empty rbtree"
97
+ end
98
+
99
+ describe "full rbtreemap" do
100
+ before(:each) do
101
+ @tree = Containers::RubyRBTreeMap.new
102
+ end
103
+ it_should_behave_like "non-empty rbtree"
104
+ end
105
+
106
+ begin
107
+ Containers::CRBTreeMap
108
+ describe "empty crbtreemap" do
109
+ before(:each) do
110
+ @tree = Containers::CRBTreeMap.new
111
+ end
112
+ it_should_behave_like "empty rbtree"
113
+ end
114
+
115
+ describe "full crbtreemap" do
116
+ before(:each) do
117
+ @tree = Containers::CRBTreeMap.new
118
+ end
119
+ it_should_behave_like "non-empty rbtree"
120
+ end
121
+ rescue Exception
122
+ end
@@ -0,0 +1,27 @@
1
+ require 'helper'
2
+
3
+ class String; include Algorithms::Algorithms::Search; end
4
+
5
+ describe "search algorithms" do
6
+ it "should binary search sorted arrays" do
7
+ n = 1000
8
+ @rand_array = Array.new(n) { rand(n) }.sort
9
+
10
+ Algorithms::Algorithms::Search.binary_search(@rand_array, @rand_array.first).should eql(@rand_array.first)
11
+ Algorithms::Algorithms::Search.binary_search(@rand_array, 999999).should be_nil
12
+ Algorithms::Algorithms::Search.binary_search(@rand_array, nil).should be_nil
13
+ end
14
+
15
+ it "should use kmp_search to find substrings it has" do
16
+ string = "ABC ABCDAB ABCDABCDABDE"
17
+ Algorithms::Algorithms::Search.kmp_search(string, "ABCDABD").should eql(15)
18
+ Algorithms::Algorithms::Search.kmp_search(string, "ABCDEF").should be_nil
19
+ Algorithms::Algorithms::Search.kmp_search(string, nil).should be_nil
20
+ Algorithms::Algorithms::Search.kmp_search(string, "").should be_nil
21
+ Algorithms::Algorithms::Search.kmp_search(nil, "ABCD").should be_nil
22
+ end
23
+
24
+ it "should let you include Search in String to enable instance methods" do
25
+ "ABC ABCDAB ABCDABCDABDE".kmp_search("ABCDABD").should eql(15)
26
+ end
27
+ end
data/spec/sort_spec.rb ADDED
@@ -0,0 +1,26 @@
1
+ require 'helper'
2
+
3
+ describe "sort algorithms" do
4
+ before(:each) do
5
+ @sorts = %w(bubble_sort comb_sort selection_sort heapsort insertion_sort shell_sort quicksort mergesort)
6
+ end
7
+
8
+ it "should work for empty containers" do
9
+ empty_array = []
10
+ @sorts.each { |sort| Algorithms::Algorithms::Sort.send(sort, empty_array).should eql([]) }
11
+ end
12
+
13
+ it "should work for a container of size 1" do
14
+ one_array = [1]
15
+ @sorts.each { |sort| Algorithms::Algorithms::Sort.send(sort, one_array).should eql(one_array) }
16
+ end
17
+
18
+ it "should work for random arrays of numbers" do
19
+ n = 500
20
+ rand_array = Array.new(n) { rand(n) }
21
+ sorted_array = rand_array.sort
22
+
23
+ @sorts.each { |sort| Algorithms::Algorithms::Sort.send(sort, rand_array.dup).should eql(sorted_array) }
24
+ end
25
+
26
+ end
@@ -0,0 +1,105 @@
1
+ require 'helper'
2
+
3
+ shared_examples "empty splaytree" do
4
+ it "should let you push stuff in" do
5
+ 100.times { |x| @tree[x] = x }
6
+ @tree.size.should eql(100)
7
+ end
8
+
9
+ it "should return 0 for size" do
10
+ @tree.size.should eql(0)
11
+ end
12
+
13
+ it "should return nil for #min and #max" do
14
+ @tree.min.should be_nil
15
+ @tree.max.should be_nil
16
+ end
17
+
18
+ it "should return nil for #delete" do
19
+ @tree.delete(:non_existing).should be_nil
20
+ end
21
+
22
+ it "should return nil for #get" do
23
+ @tree[4235].should be_nil
24
+ end
25
+ end
26
+
27
+ shared_examples "non-empty splaytree" do
28
+ before(:each) do
29
+ @num_items = 100
30
+ @random_array = []
31
+ @num_items.times { @random_array << rand(@num_items) }
32
+ @random_array.each { |x| @tree[x] = x }
33
+ end
34
+
35
+ it "should return correct size (uniqify items first)" do
36
+ @tree.size.should eql(@random_array.uniq.size)
37
+ end
38
+
39
+ it "should have correct height (worst case is when items are inserted in order, and height = num items inserted)" do
40
+ @tree.clear
41
+ 10.times { |x| @tree[x] = x }
42
+ @tree.height.should eql(10)
43
+ end
44
+
45
+ it "should return correct max and min keys" do
46
+ @tree.min[0].should eql(@random_array.min)
47
+ @tree.max[0].should eql(@random_array.max)
48
+ end
49
+
50
+ it "should not #has_key? keys it doesn't have" do
51
+ @tree.has_key?(10000).should be_false
52
+ end
53
+
54
+ it "should #has_key? keys it does have" do
55
+ @tree.has_key?(@random_array[0]).should be_true
56
+ end
57
+
58
+ it "should remove any key" do
59
+ random_key = @random_array[rand(@num_items)]
60
+ @tree.has_key?(random_key).should be_true
61
+ @tree.delete(random_key).should eql(random_key)
62
+ @tree.has_key?(random_key).should be_false
63
+ end
64
+
65
+ it "should let you iterate with #each" do
66
+ counter = 0
67
+ sorted_array = @random_array.uniq.sort
68
+ @tree.each do |key, val|
69
+ key.should eql(sorted_array[counter])
70
+ counter += 1
71
+ end
72
+ end
73
+ end
74
+
75
+ describe "empty splaytreemap" do
76
+ before(:each) do
77
+ @tree = Containers::RubySplayTreeMap.new
78
+ end
79
+ it_should_behave_like "empty splaytree"
80
+ end
81
+
82
+ describe "full splaytreemap" do
83
+ before(:each) do
84
+ @tree = Containers::RubySplayTreeMap.new
85
+ end
86
+ it_should_behave_like "non-empty splaytree"
87
+ end
88
+
89
+ begin
90
+ Containers::CSplayTreeMap
91
+ describe "empty csplaytreemap" do
92
+ before(:each) do
93
+ @tree = Containers::CSplayTreeMap.new
94
+ end
95
+ it_should_behave_like "empty splaytree"
96
+ end
97
+
98
+ describe "full csplaytreemap" do
99
+ before(:each) do
100
+ @tree = Containers::CSplayTreeMap.new
101
+ end
102
+ it_should_behave_like "non-empty splaytree"
103
+ end
104
+ rescue Exception
105
+ end