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
@@ -0,0 +1,25 @@
1
+ class Graph
2
+ def initialize(string=nil, &block)
3
+ p block if block
4
+ @nodes = []
5
+ end
6
+
7
+ def -(other)
8
+ @nodes << other
9
+ end
10
+
11
+ def >(other)
12
+ @nodes << other
13
+ end
14
+ end
15
+ a = Graph.new
16
+ b = []
17
+ d = []
18
+
19
+ a - b
20
+ a > d
21
+
22
+ Graph.new do
23
+ d - c
24
+ g - s
25
+ end
@@ -0,0 +1,31 @@
1
+ $: << File.join(File.expand_path(File.dirname(__FILE__)), '..', 'lib')
2
+ require "algorithms"
3
+
4
+ begin
5
+ Containers::CBst
6
+ describe "binary search tree" do
7
+ it "should let user insert new elements with key" do
8
+ @bst = Containers::CBst.new
9
+ 100.times { |x| @bst.insert(x, "hello : #{x}") }
10
+ @bst.size.should eql(100)
11
+ end
12
+
13
+ it "should allow users to delete elements" do
14
+ @bst = Containers::CBst.new
15
+ @bst.insert(10, "hello world")
16
+ @bst.insert(11, "hello world")
17
+ @bst.delete(11)
18
+ @bst.size.should eql(1)
19
+ @bst.delete(10)
20
+ @bst.size.should eql(0)
21
+ end
22
+
23
+ it "should throw exception on invalid key delete" do
24
+ @bst = Containers::CBst.new
25
+ @bst.insert(10,"Hello world")
26
+ lambda { @bst.delete(20) }.should raise_error(ArgumentError)
27
+ @bst.size.should eql(1)
28
+ end
29
+ end
30
+ rescue Exception
31
+ end
@@ -0,0 +1,108 @@
1
+ $: << File.join(File.expand_path(File.dirname(__FILE__)), '..', 'lib')
2
+ require 'algorithms'
3
+
4
+ describe "(empty deque)", :shared => true do
5
+ it "should return nil when popping objects" do
6
+ @deque.pop_front.should be_nil
7
+ @deque.pop_back.should be_nil
8
+ end
9
+
10
+ it "should return a size of 1 when sent #push_front" do
11
+ @deque.push_front(1)
12
+ @deque.size.should eql(1)
13
+ end
14
+
15
+ it "should return a size of 1 when sent #push_back" do
16
+ @deque.push_back(1)
17
+ @deque.size.should eql(1)
18
+ end
19
+
20
+ it "should return nil when sent #front and #back" do
21
+ @deque.front.should be_nil
22
+ @deque.back.should be_nil
23
+ end
24
+
25
+ it "should be empty" do
26
+ @deque.should be_empty
27
+ end
28
+
29
+ it "should raise ArgumentError if passed more than one argument" do
30
+ lambda { @deque.class.send("new", Time.now, []) }.should raise_error
31
+ end
32
+ end
33
+
34
+ describe "(non-empty deque)", :shared => true do
35
+ before(:each) do
36
+ @deque.push_back(10)
37
+ @deque.push_back("10")
38
+ end
39
+
40
+ it "should return last pushed object with pop_back" do
41
+ @deque.pop_back.should eql("10")
42
+ @deque.pop_back.should eql(10)
43
+ end
44
+
45
+ it "should return first pushed object with pop_front" do
46
+ @deque.pop_front.should eql(10)
47
+ @deque.pop_front.should eql("10")
48
+ end
49
+
50
+ it "should return a size greater than 0" do
51
+ @deque.size.should eql(2)
52
+ end
53
+
54
+ it "should not be empty" do
55
+ @deque.should_not be_empty
56
+ end
57
+
58
+ it "should iterate in LIFO order with #each_backward" do
59
+ arr = []
60
+ @deque.each_backward { |obj| arr << obj }
61
+ arr.should eql(["10", 10])
62
+ end
63
+
64
+ it "should iterate in FIFO order with #each_forward" do
65
+ arr = []
66
+ @deque.each_forward { |obj| arr << obj }
67
+ arr.should eql([10, "10"])
68
+ end
69
+
70
+ it "should return nil after everything's popped" do
71
+ @deque.pop_back
72
+ @deque.pop_back
73
+ @deque.pop_back.should be_nil
74
+ @deque.front.should be_nil
75
+ end
76
+ end
77
+
78
+ describe "empty rubydeque" do
79
+ before(:each) do
80
+ @deque = Containers::RubyDeque.new
81
+ end
82
+ it_should_behave_like "(empty deque)"
83
+ end
84
+
85
+ describe "full rubydeque" do
86
+ before(:each) do
87
+ @deque = Containers::RubyDeque.new
88
+ end
89
+ it_should_behave_like "(non-empty deque)"
90
+ end
91
+
92
+ begin
93
+ Containers::CDeque
94
+ describe "empty cdeque" do
95
+ before(:each) do
96
+ @deque = Containers::CDeque.new
97
+ end
98
+ it_should_behave_like "(empty deque)"
99
+ end
100
+
101
+ describe "full cdeque" do
102
+ before(:each) do
103
+ @deque = Containers::CDeque.new
104
+ end
105
+ it_should_behave_like "(non-empty deque)"
106
+ end
107
+ rescue Exception
108
+ end
@@ -1,74 +1,119 @@
1
- require 'lib/algorithms'
1
+ $: << File.join(File.expand_path(File.dirname(__FILE__)), '..', 'lib')
2
+ require 'algorithms'
2
3
 
3
- describe Containers::Heap do
4
+ describe "empty heap" do
4
5
  before(:each) do
5
6
  @heap = Containers::MaxHeap.new
6
7
  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
8
 
9
+ it "should not let you merge with non-heaps" do
10
+ lambda { @heap.merge!(nil) }.should raise_error
11
+ lambda { @heap.merge!([]) }.should raise_error
29
12
  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
13
+
14
+ it "should return nil when getting the maximum" do
15
+ @heap.max!.should be_nil
16
+ end
17
+
18
+ it "should let you insert and remove one item" do
19
+ @heap.size.should eql(0)
20
+
21
+ @heap.push(1)
22
+ @heap.size.should eql(1)
23
+
24
+ @heap.max!.should eql(1)
25
+ @heap.size.should eql(0)
26
+ end
27
+
28
+ it "should let you initialize with an array" do
29
+ @heap = Containers::MaxHeap.new([1,2,3])
30
+ @heap.size.should eql(3)
31
+ end
32
+
33
+ end
34
+
35
+ describe "non-empty heap" do
36
+ before(:each) do
37
+ @random_array = []
38
+ @num_items = 100
39
+ @num_items.times { |x| @random_array << rand(@num_items) }
40
+ @heap = Containers::MaxHeap.new(@random_array)
41
+ end
42
+
43
+ it "should display the correct size" do
44
+ @heap.size.should eql(@num_items)
45
+ end
46
+
47
+ it "should delete random keys" do
48
+ @heap.delete(@random_array[0]).should eql(@random_array[0])
49
+ @heap.delete(@random_array[1]).should eql(@random_array[1])
50
+ ordered = []
51
+ ordered << @heap.max! until @heap.empty?
52
+ ordered.should eql( @random_array[2..-1].sort.reverse )
53
+ end
54
+
55
+ it "should delete all keys" do
56
+ ordered = []
57
+ @random_array.size.times do |t|
58
+ ordered << @heap.delete(@random_array[t])
70
59
  end
71
-
60
+ @heap.should be_empty
61
+ ordered.should eql( @random_array )
62
+ end
63
+
64
+ it "should be in max->min order" do
65
+ ordered = []
66
+ ordered << @heap.max! until @heap.empty?
67
+
68
+ ordered.should eql(@random_array.sort.reverse)
69
+ end
70
+
71
+ it "should change certain keys" do
72
+ numbers = [1,2,3,4,5,6,7,8,9,10,100,101]
73
+ heap = Containers::MinHeap.new(numbers)
74
+ heap.change_key(101, 50)
75
+ heap.pop
76
+ heap.pop
77
+ heap.change_key(8, 0)
78
+ ordered = []
79
+ ordered << heap.min! until heap.empty?
80
+ ordered.should eql( [8,3,4,5,6,7,9,10,101,100] )
81
+ end
82
+
83
+ it "should not delete keys it doesn't have" do
84
+ @heap.delete(:nonexisting).should be_nil
85
+ @heap.size.should eql(@num_items)
86
+ end
87
+
88
+ it "should delete certain keys" do
89
+ numbers = [1,2,3,4,5,6,7,8,9,10,100,101]
90
+ heap = Containers::MinHeap.new(numbers)
91
+ heap.delete(5)
92
+ heap.pop
93
+ heap.pop
94
+ heap.delete(100)
95
+ ordered = []
96
+ ordered << heap.min! until heap.empty?
97
+ ordered.should eql( [3,4,6,7,8,9,10,101] )
98
+ end
99
+
100
+ it "should let you merge with another heap" do
101
+ numbers = [1,2,3,4,5,6,7,8]
102
+ otherheap = Containers::MaxHeap.new(numbers)
103
+ otherheap.size.should eql(8)
104
+ @heap.merge!(otherheap)
105
+
106
+ ordered = []
107
+ ordered << @heap.max! until @heap.empty?
108
+
109
+ ordered.should eql( (@random_array + numbers).sort.reverse)
110
+ end
111
+
112
+ it "min-heap should be in min->max order" do
113
+ @heap = Containers::MinHeap.new(@random_array)
114
+ ordered = []
115
+ ordered << @heap.min! until @heap.empty?
116
+
117
+ ordered.should eql(@random_array.sort)
72
118
  end
73
-
74
- end
119
+ end
@@ -0,0 +1,89 @@
1
+ $: << File.join(File.expand_path(File.dirname(__FILE__)), '..', 'lib')
2
+ require 'algorithms'
3
+
4
+ #!/usr/bin/ruby
5
+ # Small world puzzle
6
+ # Kanwei Li, 2009
7
+
8
+ # Make sure input file exists and read from it
9
+ filename = ARGV[0]
10
+ unless filename && File.exist?(filename)
11
+ puts "error: must specify a valid input file"
12
+ exit
13
+ end
14
+ input = File.open(filename)
15
+
16
+ $points = [] # Store array of points as a global so we don't have to pass it around
17
+
18
+ # Populate points array
19
+ # while line = input.gets do
20
+ # break if line.empty?
21
+ # n, x, y = line.split(/\s+/)
22
+ # $points << [n.to_i, [x.to_f, y.to_f]]
23
+ # end
24
+
25
+ tree = Containers::KDTree.new($points)
26
+ p tree
27
+
28
+ $points.sort { |a, b| a[0] <=> b[0] }.each do |point|
29
+ nearest_4 = tree.find_nearest(point[1], 4)
30
+ puts "#{point[0]} #{nearest_4[1..-1].collect{ |n| n[1] }.join(',')}\n"
31
+ end
32
+
33
+
34
+ # describe "empty trie" do
35
+ # before(:each) do
36
+ # @trie = Containers::Trie.new
37
+ # end
38
+ #
39
+ # it "should not get or has_key?" do
40
+ # @trie.get("anything").should be_nil
41
+ # @trie.has_key?("anything").should be_false
42
+ # end
43
+ #
44
+ # it "should not have longest_prefix or match wildcards" do
45
+ # @trie.wildcard("an*thing").should eql([])
46
+ # @trie.longest_prefix("an*thing").should eql("")
47
+ # end
48
+ # end
49
+ #
50
+ # describe "non-empty trie" do
51
+ # before(:each) do
52
+ # @trie = Containers::Trie.new
53
+ # @trie.push("Hello", "World")
54
+ # @trie.push("Hilly", "World")
55
+ # @trie.push("Hello, brother", "World")
56
+ # @trie.push("Hello, bob", "World")
57
+ # end
58
+ #
59
+ # it "should has_key? keys it has" do
60
+ # @trie.has_key?("Hello").should be_true
61
+ # @trie.has_key?("Hello, brother").should be_true
62
+ # @trie.has_key?("Hello, bob").should be_true
63
+ # end
64
+ #
65
+ # it "should not has_key? keys it doesn't have" do
66
+ # @trie.has_key?("Nope").should be_false
67
+ # end
68
+ #
69
+ # it "should get values" do
70
+ # @trie.get("Hello").should eql("World")
71
+ # end
72
+ #
73
+ # it "should overwrite values" do
74
+ # @trie.push("Hello", "John")
75
+ # @trie.get("Hello").should eql("John")
76
+ # end
77
+ #
78
+ # it "should return longest prefix" do
79
+ # @trie.longest_prefix("Hello, brandon").should eql("Hello")
80
+ # @trie.longest_prefix("Hel").should eql("")
81
+ # @trie.longest_prefix("Hello").should eql("Hello")
82
+ # @trie.longest_prefix("Hello, bob").should eql("Hello, bob")
83
+ # end
84
+ #
85
+ # it "should match wildcards" do
86
+ # @trie.wildcard("H*ll.").should eql(["Hello", "Hilly"])
87
+ # @trie.wildcard("Hel").should eql([])
88
+ # end
89
+ # end
@@ -1,31 +1,75 @@
1
- require 'lib/algorithms'
1
+ $: << File.join(File.expand_path(File.dirname(__FILE__)), '..', 'lib')
2
+ require 'algorithms'
2
3
 
3
- describe Containers::RubyPriorityQueue do
4
+ describe "empty priority queue" do
4
5
  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)
6
+ @q = Containers::PriorityQueue.new
7
+ end
8
+
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 = Containers::PriorityQueue.new
42
+ @q.push("Alaska", 50)
43
+ @q.push("Delaware", 30)
44
+ @q.push("Georgia", 35)
45
+ end
46
+
47
+ it "should next/pop the highest priority" do
48
+ @q.next.should eql("Alaska")
49
+ @q.size.should eql(3)
50
+ @q.pop.should eql("Alaska")
51
+ @q.size.should eql(2)
52
+ end
53
+
54
+ it "should not be empty" do
55
+ @q.should_not be_empty
56
+ end
57
+
58
+ it "should has_priority? priorities it has" do
59
+ @q.has_priority?(50).should be_true
60
+ @q.has_priority?(10).should be_false
61
+ end
62
+
63
+ it "should return nil after popping everything" do
64
+ 3.times do
65
+ @q.pop
28
66
  end
67
+ @q.pop.should be_nil
29
68
  end
30
-
31
- end
69
+
70
+ it "should delete things it has and not things it doesn't" do
71
+ @q.delete(50).should eql("Alaska")
72
+ @q.delete(10).should eql(nil)
73
+ end
74
+
75
+ end