stakach-algorithms 1.0.6 → 1.0.7

Sign up to get free protection for your applications and to get access to all the features.
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