algorithms 0.1.0 → 0.2.0

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