codders-trie 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (9) hide show
  1. data/COPYING +340 -0
  2. data/INSTALL +232 -0
  3. data/MANIFEST +8 -0
  4. data/README +6 -0
  5. data/lib/trie.rb +437 -0
  6. data/setup.rb +1551 -0
  7. data/test/tests.rb +275 -0
  8. data/trie.gemspec +14 -0
  9. metadata +54 -0
data/test/tests.rb ADDED
@@ -0,0 +1,275 @@
1
+ #!/usr/bin/ruby -w
2
+ #
3
+ # = Name
4
+ # TestTrie
5
+ #
6
+ # == Description
7
+ # This file contains unit tests for the Trie class.
8
+ #
9
+ # == Author
10
+ # Daniel Erat <dan-ruby@erat.org>
11
+ #
12
+ # == Copyright
13
+ # Copyright 2005 Daniel Erat
14
+ #
15
+ # == License
16
+ # GNU GPL; see COPYING
17
+
18
+ $:.unshift File.join(File.dirname(__FILE__), "..", "lib")
19
+
20
+ require 'test/unit'
21
+ require 'trie'
22
+
23
+ # Unit tests for the Trie class.
24
+ class TestTrie < Test::Unit::TestCase
25
+ # Test a compressed key with a single value at the root.
26
+ def test_find_compressed_key_single_value_at_root
27
+ t = Trie.new.insert('abc', 1)
28
+ assert_equal([1], t.find('abc').values)
29
+ assert_equal([1], t.find('abc').find('').values)
30
+ assert_equal([], t.find('a').values)
31
+ assert_equal([], t.find('').values)
32
+ assert_equal([], t.find('b').values)
33
+ assert_equal([1], t.find_prefix('abc').values)
34
+ assert_equal([1], t.find_prefix('abc').find_prefix('').values)
35
+ assert_equal([1], t.find_prefix('ab').values)
36
+ assert_equal([1], t.find_prefix('a').values)
37
+ assert_equal([1], t.find_prefix('').values)
38
+ assert_equal([], t.find_prefix('b').values)
39
+ end
40
+
41
+ # Test a compressed key with multiple values at the root.
42
+ def test_find_compressed_key_multiple_values_at_root
43
+ t = Trie.new.insert('ab', 1).insert('ab', 2).insert('ab', 3)
44
+ assert_equal([1, 2, 3], t.find('ab').values.sort)
45
+ assert_equal([], t.find('a').values)
46
+ assert_equal([], t.find('').values)
47
+ assert_equal([1, 2, 3], t.find_prefix('ab').values.sort)
48
+ assert_equal([1, 2, 3], t.find_prefix('a').values.sort)
49
+ assert_equal([1, 2, 3], t.find_prefix('').values.sort)
50
+ end
51
+
52
+ # Test a more complex Trie that contains a few compressed keys.
53
+ def test_find_complex
54
+ t = Trie.new.insert('a', 1).insert('ab', 2).insert('abcdef', 3).
55
+ insert('b', 4).insert('bcd', 5).insert('b', 6).insert('bcd', 7)
56
+ assert_equal([1], t.find('a').values)
57
+ assert_equal([2], t.find('ab').values)
58
+ assert_equal([3], t.find('abcdef').values)
59
+ assert_equal([4, 6], t.find('b').values.sort)
60
+ assert_equal([5, 7], t.find('bcd').values.sort)
61
+ assert_equal([], t.find('bcde').values)
62
+ assert_equal([], t.find('').values)
63
+ assert_equal([1, 2, 3], t.find_prefix('a').values)
64
+ assert_equal([2, 3], t.find_prefix('ab').values)
65
+ assert_equal([3], t.find_prefix('abcdef').values)
66
+ assert_equal([4, 5, 6, 7], t.find_prefix('b').values.sort)
67
+ assert_equal([5, 7], t.find_prefix('bcd').values.sort)
68
+ assert_equal([], t.find_prefix('bcde').values)
69
+ assert_equal([1, 2, 3, 4, 5, 6, 7], t.find_prefix('').values.sort)
70
+ end
71
+
72
+ # We have a compressed key at the root and then do one-or
73
+ # two-characters-at-a-time searches against it.
74
+ def test_find_multiple_lookups_compressed_key
75
+ t = Trie.new.insert('alphabet', 1)
76
+ t2 = t.find_prefix('')
77
+ assert_equal([1], t2.values)
78
+ t2 = t2.find_prefix('al')
79
+ assert_equal([1], t2.values)
80
+ t2 = t2.find_prefix('p')
81
+ assert_equal([1], t2.values)
82
+ t2 = t2.find_prefix('ha')
83
+ assert_equal([1], t2.values)
84
+ t2 = t2.find_prefix('bet')
85
+ assert_equal([1], t2.values)
86
+ t2 = t2.find_prefix('')
87
+ assert_equal([1], t2.values)
88
+ t2 = t2.find_prefix('a')
89
+ assert_equal([], t2.values)
90
+ end
91
+
92
+ # We construct a trie with multiple values and then walk down it,
93
+ # searching for one or two characters at a time.
94
+ def test_find_multiple_lookups
95
+ t = Trie.new.insert('happy', 1).insert('hop', 2).insert('hey', 3).
96
+ insert('hello!', 4).insert('help', 5).insert('foo', 6)
97
+ assert_equal([6], t.find_prefix('fo').values)
98
+ t2 = t.find_prefix('h')
99
+ assert_equal([1, 2, 3, 4, 5], t2.values.sort)
100
+ t2 = t2.find_prefix('e')
101
+ assert_equal([3, 4, 5], t2.values.sort)
102
+ assert_equal([3], t2.find_prefix('y').values)
103
+ t2 = t2.find_prefix('l')
104
+ assert_equal([4, 5], t2.values.sort)
105
+ t2 = t2.find_prefix('lo')
106
+ assert_equal([4], t2.values)
107
+ t2 = t2.find_prefix('!')
108
+ assert_equal([4], t2.values)
109
+ t2 = t2.find_prefix('')
110
+ assert_equal([4], t2.values)
111
+ t2 = t2.find_prefix('!')
112
+ assert_equal([], t2.values)
113
+ end
114
+
115
+ # We construct a trie with multiple elements and test the size
116
+ # method.
117
+ def test_size
118
+ t = Trie.new.insert('ha', 1).insert('hat', 2).insert('hate', 3).
119
+ insert('hated', 4).insert('test', 5)
120
+ assert_equal(5, t.size)
121
+ assert_equal(4, t.find_prefix('ha').size)
122
+ assert_equal(2, t.find_prefix('hate').size)
123
+ assert_equal(1, t.find_prefix('test').size)
124
+ assert_equal(0, t.find_prefix('testing').size)
125
+ end
126
+
127
+ # We build a trie and test the empty? method.
128
+ def test_empty
129
+ t = Trie.new.insert('foo', 1).insert('bar', 2).insert('food', 3)
130
+ assert_equal(false, t.empty?)
131
+ assert_equal(false, t.find('foo').empty?)
132
+ assert_equal(false, t.find_prefix('foo').empty?)
133
+ assert_equal(true, t.find('fool').empty?)
134
+ end
135
+
136
+ # We insert keys that are actually lists containing objects of varying
137
+ # classes.
138
+ def test_mixed_classes_in_keys
139
+ t = Trie.new.insert([0, 1, 2], 0).insert([0, 'a'], 1).insert([1000], 2).
140
+ insert([0, 'a'], 3).insert('blah', 4)
141
+ assert_equal([0, 1, 3], t.find_prefix([0]).values.sort)
142
+ assert_equal([0], t.find_prefix([0, 1]).values)
143
+ assert_equal([1, 3], t.find_prefix([0, 'a']).values.sort)
144
+ assert_equal([2], t.find_prefix([1000]).values)
145
+ assert_equal([], t.find([0]).values)
146
+ assert_equal([1, 3], t.find([0, 'a']).values.sort)
147
+ assert_equal([4], t.find('blah').values)
148
+ end
149
+
150
+ # Test delete.
151
+ def test_delete
152
+ t = Trie.new.insert('a', 1).insert('a', 2).insert('a', 3).
153
+ insert('ab', 4).insert('ab', 5).insert('abc', 6)
154
+ assert_equal([1, 2, 3, 4, 5, 6], t.values.sort)
155
+ t.delete('a')
156
+ assert_equal([4, 5, 6], t.values.sort)
157
+ t.delete('abc')
158
+ assert_equal([4, 5], t.values.sort)
159
+ t.delete('ab')
160
+ assert_equal([], t.values)
161
+ end
162
+
163
+ # Test delete_pair.
164
+ def test_delete_pair
165
+ t = Trie.new.insert('apple', 1).insert('apples', 2)
166
+ assert_equal([1], t.find('apple').values)
167
+ assert_equal([1, 2], t.find_prefix('apple').values.sort)
168
+ t.delete_pair('apple', 1)
169
+ assert_equal([], t.find('apple').values)
170
+ assert_equal([2], t.find('apples').values)
171
+ assert_equal([2], t.find_prefix('apple').values)
172
+ t.delete_pair('apples', 1) # key/value pair isn't in trie
173
+ assert_equal([2], t.find('apples').values)
174
+ t.delete_pair('apples', 2)
175
+ assert_equal([], t.find('apples').values)
176
+ end
177
+
178
+ # Test delete_value.
179
+ def test_delete_value
180
+ t = Trie.new.insert('a', 1).insert('ab', 1).insert('abc', 2).
181
+ insert('a', 2).insert('b', 1).insert('c', 1)
182
+ assert_equal(6, t.size)
183
+ t.delete_value(1)
184
+ assert_equal(2, t.size)
185
+ t.delete_value(2)
186
+ assert_equal(true, t.empty?)
187
+ end
188
+
189
+ # Test delete_prefix.
190
+ def test_delete_prefix
191
+ t = Trie.new.insert('a', 1).insert('a', 2).insert('a', 3).
192
+ insert('ab', 4).insert('ab', 5).insert('abc', 6)
193
+ assert_equal([1, 2, 3, 4, 5, 6], t.values.sort)
194
+ t.delete_prefix('ab')
195
+ assert_equal([1, 2, 3], t.values.sort)
196
+ t.delete_prefix('a')
197
+ assert_equal(true, t.empty?)
198
+ end
199
+
200
+ # Test clear.
201
+ def test_clear
202
+ t = Trie.new.insert('a', 1).insert('ab', 2)
203
+ assert_equal(2, t.size)
204
+ t.clear
205
+ assert_equal(true, t.empty?)
206
+ end
207
+
208
+ # Test each_key.
209
+ def test_each_key
210
+ t = Trie.new.insert('a', 1).insert('a', 2).insert('b', 3).insert('ab', 4)
211
+ keys = []
212
+ t.each_key {|k| keys.push(k.join) }
213
+ assert_equal(['a', 'ab', 'b'], keys.sort)
214
+ end
215
+
216
+ # Test each_value.
217
+ def test_each_value
218
+ t = Trie.new.insert('a', 1).insert('a', 2).insert('b', 1)
219
+ values = []
220
+ t.each_value {|v| values.push(v) }
221
+ assert_equal([1, 1, 2], values.sort)
222
+ end
223
+
224
+ # Test each.
225
+ def test_each
226
+ t = Trie.new.insert('a', 1).insert('a', 2).insert('b', 3).insert('ab', 4)
227
+ pairs = []
228
+ t.each {|k, v| pairs.push([k.join, v]) }
229
+ assert_equal([['a', 1], ['a', 2], ['ab', 4], ['b', 3]], pairs.sort)
230
+ end
231
+
232
+ # Test keys.
233
+ def test_keys
234
+ t = Trie.new.insert('a', 1).insert('a', 2).insert('abc', 3).insert('b', 4)
235
+ keys = t.keys.collect {|k| k.join }.sort
236
+ assert_equal(['a', 'abc', 'b'], keys)
237
+ end
238
+
239
+ # Test the composition of the tries by using the num_nodes method.
240
+ def test_composition
241
+ t = Trie.new.insert('a', 1)
242
+ assert_equal(1, t.num_nodes) # a
243
+ t.insert('a', 2)
244
+ assert_equal(1, t.num_nodes) # a
245
+ t.insert('abc', 3)
246
+ assert_equal(3, t.num_nodes) # '' -> a -> bc
247
+ t.insert('ab', 4)
248
+ assert_equal(4, t.num_nodes) # '' -> a -> b -> c
249
+ t.insert('b', 5)
250
+ assert_equal(5, t.num_nodes) # '' -> (a -> b -> c | b)
251
+ t.insert('b', 6)
252
+ assert_equal(5, t.num_nodes) # '' -> (a -> b -> c | b)
253
+ t.insert('abcdef', 7)
254
+ assert_equal(6, t.num_nodes) # '' -> (a -> b -> c -> def | b)
255
+ t.insert('abcdeg', 8)
256
+ # '' -> (a -> b -> c -> d -> e -> (f | g) | b)
257
+ assert_equal(9, t.num_nodes)
258
+ end
259
+
260
+ def test_marshalling
261
+ t = Trie.new.insert('a', 1).insert('a', 13).insert('at', 2).insert('b', 3)
262
+ t2 = Marshal.load(Marshal.dump(t))
263
+ assert_equal(t.size, t2.size)
264
+ %w(a at b x).each do |k|
265
+ assert_equal(t[k], t2[k])
266
+ end
267
+ end
268
+
269
+ def test_to_a
270
+ t = Trie.new.insert('a', 1).insert('a', 13).insert('at', 2).insert('b', 3)
271
+ assert_equal([['a', 1], ['a', 13], ['at', 2], ['b', 3]],
272
+ t.to_a.map{|k,v| [k.join(''), v]})
273
+ end
274
+
275
+ end
data/trie.gemspec ADDED
@@ -0,0 +1,14 @@
1
+ SPEC = Gem::Specification.new do |s|
2
+ s.name = "codders-trie"
3
+ s.version = "0.0.3"
4
+ s.author = "Daniel Erat"
5
+ s.email = "dan-ruby@erat.org"
6
+ s.homepage = "http://www.erat.org/ruby/"
7
+ s.platform = Gem::Platform::RUBY
8
+ s.summary = "Implemention of a trie data structure"
9
+ candidates = %w(COPYING INSTALL MANIFEST README setup.rb trie.gemspec lib/trie.rb test/tests.rb)
10
+ s.files = candidates.delete_if {|i| i =~ /CVS/ }
11
+ s.require_path = "lib"
12
+ s.test_file = "test/tests.rb"
13
+ s.has_rdoc = true
14
+ end
metadata ADDED
@@ -0,0 +1,54 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: codders-trie
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.3
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Daniel Erat
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-08-22 00:00:00.000000000 Z
13
+ dependencies: []
14
+ description:
15
+ email: dan-ruby@erat.org
16
+ executables: []
17
+ extensions: []
18
+ extra_rdoc_files: []
19
+ files:
20
+ - COPYING
21
+ - INSTALL
22
+ - MANIFEST
23
+ - README
24
+ - setup.rb
25
+ - trie.gemspec
26
+ - lib/trie.rb
27
+ - test/tests.rb
28
+ homepage: http://www.erat.org/ruby/
29
+ licenses: []
30
+ post_install_message:
31
+ rdoc_options: []
32
+ require_paths:
33
+ - lib
34
+ required_ruby_version: !ruby/object:Gem::Requirement
35
+ none: false
36
+ requirements:
37
+ - - ! '>='
38
+ - !ruby/object:Gem::Version
39
+ version: '0'
40
+ required_rubygems_version: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ requirements: []
47
+ rubyforge_project:
48
+ rubygems_version: 1.8.24
49
+ signing_key:
50
+ specification_version: 3
51
+ summary: Implemention of a trie data structure
52
+ test_files:
53
+ - test/tests.rb
54
+ has_rdoc: true