algorithms 0.1.0 → 0.2.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.
@@ -45,11 +45,12 @@
45
45
  =end
46
46
 
47
47
  module Algorithms; end
48
- module Containers
49
- dir = File.dirname(__FILE__)
50
- autoload :CBst, File.join(dir,"..","ext","containers","bst","CBst")
51
- autoload :CDeque, File.join(dir,"..","ext","containers","deque","CDeque")
52
- autoload :CRBTreeMap, File.join(dir,"..","ext","containers","tree_map","CRBTreeMap")
48
+ module Containers; end
49
+
50
+ begin
51
+ require 'CBst'
52
+ Containers::Bst = Containers::CBst
53
+ rescue LoadError # C Version could not be found
53
54
  end
54
55
 
55
56
  require 'algorithms/search'
@@ -6,6 +6,9 @@
6
6
  =end
7
7
  class Containers::RubyDeque
8
8
  include Enumerable
9
+
10
+ Node = Struct.new(:left, :right, :obj)
11
+
9
12
  # Create a new Deque. Takes an optional array argument to initialize the Deque.
10
13
  #
11
14
  # d = Containers::Deque.new([1, 2, 3])
@@ -64,7 +67,7 @@ class Containers::RubyDeque
64
67
  # d.push_front(0)
65
68
  # d.pop_front #=> 0
66
69
  def push_front(obj)
67
- node = Node.new(obj)
70
+ node = Node.new(nil, nil, obj)
68
71
  if @front
69
72
  node.right = @front
70
73
  @front.left = node
@@ -82,7 +85,7 @@ class Containers::RubyDeque
82
85
  # d.push_back(4)
83
86
  # d.pop_back #=> 4
84
87
  def push_back(obj)
85
- node = Node.new(obj)
88
+ node = Node.new(nil, nil, obj)
86
89
  if @back
87
90
  node.left = @back
88
91
  @back.right = node
@@ -158,14 +161,6 @@ class Containers::RubyDeque
158
161
  end
159
162
  alias_method :reverse_each, :each_backward
160
163
 
161
- class Node # :nodoc: all
162
- attr_accessor :left, :right, :obj
163
-
164
- def initialize(obj)
165
- @left = @right = nil
166
- @obj = obj
167
- end
168
- end
169
164
  end
170
165
 
171
166
  begin
@@ -13,11 +13,14 @@ require 'containers/stack'
13
13
  when keys are added in sorted order, causing the tree to have a height of the number of items added.
14
14
 
15
15
  =end
16
- class Containers::SplayTreeMap
16
+ class Containers::RubySplayTreeMap
17
17
  include Enumerable
18
18
 
19
+ Node = Struct.new(:key, :value, :left, :right)
20
+
19
21
  # Create and initialize a new empty SplayTreeMap.
20
22
  def initialize
23
+ @size = 0
21
24
  clear
22
25
  end
23
26
 
@@ -30,7 +33,7 @@ class Containers::SplayTreeMap
30
33
  # map.get("MA") #=> "Massachusetts"
31
34
  def push(key, value)
32
35
  if @root.nil?
33
- @root = Node.new(key, value)
36
+ @root = Node.new(key, value, nil, nil)
34
37
  @size = 1
35
38
  return value
36
39
  end
@@ -41,7 +44,7 @@ class Containers::SplayTreeMap
41
44
  @root.value = value
42
45
  return value
43
46
  end
44
- node = Node.new(key, value)
47
+ node = Node.new(key, value, nil, nil)
45
48
  if cmp < 1
46
49
  node.left = @root.left
47
50
  node.right = @root
@@ -74,7 +77,7 @@ class Containers::SplayTreeMap
74
77
  def clear
75
78
  @root = nil
76
79
  @size = 0
77
- @header = Node.new(nil, nil)
80
+ @header = Node.new(nil, nil, nil, nil)
78
81
  end
79
82
 
80
83
  # Return the height of the tree structure in the SplayTreeMap.
@@ -203,20 +206,6 @@ class Containers::SplayTreeMap
203
206
  end
204
207
  end
205
208
 
206
- class Node # :nodoc: all
207
- attr_accessor :key, :value, :left, :right
208
- def initialize(key, value)
209
- @key = key
210
- @value = value
211
- @left = nil
212
- @right = nil
213
- end
214
-
215
- def size
216
- self.num_nodes
217
- end
218
- end
219
-
220
209
  # Moves a key to the root, updating the structure in each step.
221
210
  def splay(key)
222
211
  l, r = @header, @header
@@ -270,5 +259,11 @@ class Containers::SplayTreeMap
270
259
  left_height > right_height ? left_height : right_height
271
260
  end
272
261
  private :height_recursive
262
+ end
273
263
 
274
- end
264
+ begin
265
+ require 'CSplayTreeMap'
266
+ Containers::SplayTreeMap = Containers::CSplayTreeMap
267
+ rescue LoadError # C Version could not be found, try ruby version
268
+ Containers::SplayTreeMap = Containers::RubySplayTreeMap
269
+ end
@@ -0,0 +1,18 @@
1
+ $: << File.join(File.expand_path(File.dirname(__FILE__)), '..', 'lib')
2
+ require 'algorithms'
3
+
4
+ if defined? Containers::CDeque
5
+ describe "CDeque" do
6
+ it "should mark ruby object references" do
7
+ anon_class = Class.new
8
+ @deque = Containers::CDeque.new
9
+ 100.times { @deque.push_front(anon_class.new) }
10
+ # Mark and sweep
11
+ ObjectSpace.garbage_collect
12
+ # Check if any instances were swept
13
+ count = 0
14
+ ObjectSpace.each_object(anon_class) { |x| count += 1 }
15
+ count.should eql(100)
16
+ end
17
+ end
18
+ end
@@ -1,119 +1,126 @@
1
1
  $: << File.join(File.expand_path(File.dirname(__FILE__)), '..', 'lib')
2
2
  require 'algorithms'
3
3
 
4
- describe "empty heap" do
4
+ describe Containers::Heap do
5
5
  before(:each) do
6
6
  @heap = Containers::MaxHeap.new
7
7
  end
8
-
8
+
9
9
  it "should not let you merge with non-heaps" do
10
10
  lambda { @heap.merge!(nil) }.should raise_error
11
11
  lambda { @heap.merge!([]) }.should raise_error
12
12
  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])
13
+
14
+ describe "(empty)" do
15
+
16
+ it "should return nil when getting the maximum" do
17
+ @heap.max!.should be_nil
18
+ end
19
+
20
+ it "should let you insert and remove one item" do
21
+ @heap.size.should eql(0)
22
+
23
+ @heap.push(1)
24
+ @heap.size.should eql(1)
25
+
26
+ @heap.max!.should eql(1)
27
+ @heap.size.should eql(0)
28
+ end
29
+
30
+ it "should let you initialize with an array" do
31
+ @heap = Containers::MaxHeap.new([1,2,3])
32
+ @heap.size.should eql(3)
59
33
  end
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
34
 
109
- ordered.should eql( (@random_array + numbers).sort.reverse)
110
35
  end
36
+
37
+ describe "(non-empty)" do
38
+ before(:each) do
39
+ @random_array = []
40
+ @num_items = 100
41
+ @num_items.times { |x| @random_array << rand(@num_items) }
42
+ @heap = Containers::MaxHeap.new(@random_array)
43
+ end
44
+
45
+ it "should display the correct size" do
46
+ @heap.size.should eql(@num_items)
47
+ end
48
+
49
+ it "should delete random keys" do
50
+ @heap.delete(@random_array[0]).should eql(@random_array[0])
51
+ @heap.delete(@random_array[1]).should eql(@random_array[1])
52
+ ordered = []
53
+ ordered << @heap.max! until @heap.empty?
54
+ ordered.should eql( @random_array[2..-1].sort.reverse )
55
+ end
56
+
57
+ it "should delete all keys" do
58
+ ordered = []
59
+ @random_array.size.times do |t|
60
+ ordered << @heap.delete(@random_array[t])
61
+ end
62
+ @heap.should be_empty
63
+ ordered.should eql( @random_array )
64
+ end
111
65
 
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)
66
+ it "should be in max->min order" do
67
+ ordered = []
68
+ ordered << @heap.max! until @heap.empty?
69
+
70
+ ordered.should eql(@random_array.sort.reverse)
71
+ end
72
+
73
+ it "should change certain keys" do
74
+ numbers = [1,2,3,4,5,6,7,8,9,10,100,101]
75
+ heap = Containers::MinHeap.new(numbers)
76
+ heap.change_key(101, 50)
77
+ heap.pop
78
+ heap.pop
79
+ heap.change_key(8, 0)
80
+ ordered = []
81
+ ordered << heap.min! until heap.empty?
82
+ ordered.should eql( [8,3,4,5,6,7,9,10,101,100] )
83
+ end
84
+
85
+ it "should not delete keys it doesn't have" do
86
+ @heap.delete(:nonexisting).should be_nil
87
+ @heap.size.should eql(@num_items)
88
+ end
89
+
90
+ it "should delete certain keys" do
91
+ numbers = [1,2,3,4,5,6,7,8,9,10,100,101]
92
+ heap = Containers::MinHeap.new(numbers)
93
+ heap.delete(5)
94
+ heap.pop
95
+ heap.pop
96
+ heap.delete(100)
97
+ ordered = []
98
+ ordered << heap.min! until heap.empty?
99
+ ordered.should eql( [3,4,6,7,8,9,10,101] )
100
+ end
101
+
102
+ it "should let you merge with another heap" do
103
+ numbers = [1,2,3,4,5,6,7,8]
104
+ otherheap = Containers::MaxHeap.new(numbers)
105
+ otherheap.size.should eql(8)
106
+ @heap.merge!(otherheap)
107
+
108
+ ordered = []
109
+ ordered << @heap.max! until @heap.empty?
110
+
111
+ ordered.should eql( (@random_array + numbers).sort.reverse)
112
+ end
113
+
114
+ describe "min-heap" do
115
+ it "should be in min->max order" do
116
+ @heap = Containers::MinHeap.new(@random_array)
117
+ ordered = []
118
+ ordered << @heap.min! until @heap.empty?
119
+
120
+ ordered.should eql(@random_array.sort)
121
+ end
122
+ end
123
+
118
124
  end
125
+
119
126
  end
@@ -1,89 +1,4 @@
1
1
  $: << File.join(File.expand_path(File.dirname(__FILE__)), '..', 'lib')
2
2
  require 'algorithms'
3
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
4
+ # TODO: KD Tree Spec