rambling-trie 0.8.1 → 0.9.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.
- checksums.yaml +4 -4
- data/Rakefile +1 -1
- data/lib/rambling/trie.rb +21 -9
- data/lib/rambling/trie/compressed_node.rb +112 -0
- data/lib/rambling/trie/compression.rb +13 -0
- data/lib/rambling/trie/compressor.rb +30 -31
- data/lib/rambling/trie/{root.rb → container.rb} +41 -38
- data/lib/rambling/trie/enumerable.rb +11 -7
- data/lib/rambling/trie/missing_node.rb +1 -1
- data/lib/rambling/trie/node.rb +25 -22
- data/lib/rambling/trie/plain_text_reader.rb +1 -1
- data/lib/rambling/trie/raw_node.rb +90 -0
- data/lib/rambling/trie/tasks/helpers/path.rb +13 -0
- data/lib/rambling/trie/tasks/helpers/time.rb +7 -0
- data/lib/rambling/trie/tasks/performance.rb +10 -91
- data/lib/rambling/trie/tasks/performance/all.rb +4 -0
- data/lib/rambling/trie/tasks/performance/benchmark.rb +172 -0
- data/lib/rambling/trie/tasks/performance/directory.rb +11 -0
- data/lib/rambling/trie/tasks/performance/profile/call_tree.rb +132 -0
- data/lib/rambling/trie/tasks/performance/profile/memory.rb +116 -0
- data/lib/rambling/trie/version.rb +1 -1
- data/rambling-trie.gemspec +6 -4
- data/spec/integration/rambling/trie_spec.rb +63 -9
- data/spec/lib/rambling/trie/compressed_node_spec.rb +35 -0
- data/spec/lib/rambling/trie/compressor_spec.rb +31 -0
- data/spec/lib/rambling/trie/container_spec.rb +470 -0
- data/spec/lib/rambling/trie/enumerable_spec.rb +2 -2
- data/spec/lib/rambling/trie/inspector_spec.rb +21 -14
- data/spec/lib/rambling/trie/node_spec.rb +72 -209
- data/spec/lib/rambling/trie/raw_node_spec.rb +377 -0
- data/spec/lib/rambling/trie_spec.rb +46 -25
- metadata +57 -16
- data/lib/rambling/trie/branches.rb +0 -149
- data/spec/lib/rambling/trie/branches_spec.rb +0 -52
- data/spec/lib/rambling/trie/root_spec.rb +0 -376
@@ -1,376 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
module Rambling
|
4
|
-
module Trie
|
5
|
-
describe Root do
|
6
|
-
describe '#root?' do
|
7
|
-
it 'returns true' do
|
8
|
-
expect(subject).to be_root
|
9
|
-
end
|
10
|
-
end
|
11
|
-
|
12
|
-
describe '.new' do
|
13
|
-
it 'has no children' do
|
14
|
-
expect(subject.children.size).to eq 0
|
15
|
-
end
|
16
|
-
|
17
|
-
it 'has no letter' do
|
18
|
-
expect(subject.letter).to be_nil
|
19
|
-
end
|
20
|
-
|
21
|
-
it 'is not a terminal node' do
|
22
|
-
expect(subject).not_to be_terminal
|
23
|
-
end
|
24
|
-
|
25
|
-
it 'is not a word' do
|
26
|
-
expect(subject).not_to be_word
|
27
|
-
end
|
28
|
-
|
29
|
-
context 'with a block' do
|
30
|
-
subject { Root.new { |root| root << 'test' } }
|
31
|
-
|
32
|
-
it 'has no letter' do
|
33
|
-
expect(subject.letter).to be_nil
|
34
|
-
end
|
35
|
-
|
36
|
-
it 'is not a terminal node' do
|
37
|
-
expect(subject).not_to be_terminal
|
38
|
-
end
|
39
|
-
|
40
|
-
it 'is not a word' do
|
41
|
-
expect(subject).not_to be_word
|
42
|
-
end
|
43
|
-
|
44
|
-
it 'executes the block' do
|
45
|
-
expect(subject.children.size).to eq 1
|
46
|
-
expect(subject.word? 'test').to be true
|
47
|
-
end
|
48
|
-
end
|
49
|
-
end
|
50
|
-
|
51
|
-
describe '#compress!' do
|
52
|
-
let(:compressed_root) { subject.compress! }
|
53
|
-
|
54
|
-
it 'returns itself marked as compressed' do
|
55
|
-
expect(compressed_root).to eq subject
|
56
|
-
expect(compressed_root).to be_compressed
|
57
|
-
end
|
58
|
-
|
59
|
-
context 'after calling #compress! once' do
|
60
|
-
let(:recompressed_root) { compressed_root.compress! }
|
61
|
-
|
62
|
-
it 'keeps returning itself' do
|
63
|
-
expect(recompressed_root).to eq subject
|
64
|
-
expect(recompressed_root).to be_compressed
|
65
|
-
end
|
66
|
-
end
|
67
|
-
|
68
|
-
context 'with at least one word' do
|
69
|
-
it 'keeps the root letter nil' do
|
70
|
-
subject << 'all'
|
71
|
-
subject.compress!
|
72
|
-
|
73
|
-
expect(subject.letter).to be_nil
|
74
|
-
end
|
75
|
-
end
|
76
|
-
|
77
|
-
context 'with a single word' do
|
78
|
-
before do
|
79
|
-
subject << 'all'
|
80
|
-
subject.compress!
|
81
|
-
end
|
82
|
-
|
83
|
-
it 'compresses into a single node without children' do
|
84
|
-
expect(subject[:all].letter).to eq :all
|
85
|
-
expect(subject[:all].children.size).to eq 0
|
86
|
-
expect(subject[:all]).to be_terminal
|
87
|
-
expect(subject[:all]).to be_compressed
|
88
|
-
end
|
89
|
-
end
|
90
|
-
|
91
|
-
context 'with two words' do
|
92
|
-
before do
|
93
|
-
subject << 'all'
|
94
|
-
subject << 'ask'
|
95
|
-
subject.compress!
|
96
|
-
end
|
97
|
-
|
98
|
-
it 'compresses into corresponding three nodes' do
|
99
|
-
expect(subject[:a].letter).to eq :a
|
100
|
-
expect(subject[:a].children.size).to eq 2
|
101
|
-
|
102
|
-
expect(subject[:a][:ll].letter).to eq :ll
|
103
|
-
expect(subject[:a][:sk].letter).to eq :sk
|
104
|
-
|
105
|
-
expect(subject[:a][:ll].children.size).to eq 0
|
106
|
-
expect(subject[:a][:sk].children.size).to eq 0
|
107
|
-
|
108
|
-
expect(subject[:a][:ll]).to be_terminal
|
109
|
-
expect(subject[:a][:sk]).to be_terminal
|
110
|
-
|
111
|
-
expect(subject[:a][:ll]).to be_compressed
|
112
|
-
expect(subject[:a][:sk]).to be_compressed
|
113
|
-
end
|
114
|
-
end
|
115
|
-
|
116
|
-
it 'reassigns the parent nodes correctly' do
|
117
|
-
subject << 'repay'
|
118
|
-
subject << 'rest'
|
119
|
-
subject << 'repaint'
|
120
|
-
subject.compress!
|
121
|
-
|
122
|
-
expect(subject[:re].letter).to eq :re
|
123
|
-
expect(subject[:re].children.size).to eq 2
|
124
|
-
|
125
|
-
expect(subject[:re][:pa].letter).to eq :pa
|
126
|
-
expect(subject[:re][:st].letter).to eq :st
|
127
|
-
|
128
|
-
expect(subject[:re][:pa].children.size).to eq 2
|
129
|
-
expect(subject[:re][:st].children.size).to eq 0
|
130
|
-
|
131
|
-
expect(subject[:re][:pa][:y].letter).to eq :y
|
132
|
-
expect(subject[:re][:pa][:int].letter).to eq :int
|
133
|
-
|
134
|
-
expect(subject[:re][:pa][:y].children.size).to eq 0
|
135
|
-
expect(subject[:re][:pa][:int].children.size).to eq 0
|
136
|
-
|
137
|
-
expect(subject[:re][:pa][:y].parent).to eq subject[:re][:pa]
|
138
|
-
expect(subject[:re][:pa][:int].parent).to eq subject[:re][:pa]
|
139
|
-
end
|
140
|
-
|
141
|
-
it 'does not compress terminal nodes' do
|
142
|
-
subject << 'you'
|
143
|
-
subject << 'your'
|
144
|
-
subject << 'yours'
|
145
|
-
|
146
|
-
subject.compress!
|
147
|
-
|
148
|
-
expect(subject[:you].letter).to eq :you
|
149
|
-
|
150
|
-
expect(subject[:you][:r].letter).to eq :r
|
151
|
-
expect(subject[:you][:r]).to be_compressed
|
152
|
-
|
153
|
-
expect(subject[:you][:r][:s].letter).to eq :s
|
154
|
-
expect(subject[:you][:r][:s]).to be_compressed
|
155
|
-
end
|
156
|
-
|
157
|
-
describe 'and trying to add a word' do
|
158
|
-
it 'raises an error' do
|
159
|
-
subject << 'repay'
|
160
|
-
subject << 'rest'
|
161
|
-
subject << 'repaint'
|
162
|
-
subject.compress!
|
163
|
-
|
164
|
-
expect { subject << 'restaurant' }.to raise_error InvalidOperation
|
165
|
-
end
|
166
|
-
end
|
167
|
-
end
|
168
|
-
|
169
|
-
describe '#word?' do
|
170
|
-
context 'word is contained' do
|
171
|
-
before do
|
172
|
-
subject << 'hello'
|
173
|
-
subject << 'high'
|
174
|
-
end
|
175
|
-
|
176
|
-
it 'matches the whole word' do
|
177
|
-
expect(subject.word? 'hello').to be true
|
178
|
-
expect(subject.word? 'high').to be true
|
179
|
-
end
|
180
|
-
|
181
|
-
it 'is aliased as #include?' do
|
182
|
-
expect(subject).to include 'hello'
|
183
|
-
expect(subject).to include 'high'
|
184
|
-
end
|
185
|
-
|
186
|
-
context 'and the root has been compressed' do
|
187
|
-
before do
|
188
|
-
subject.compress!
|
189
|
-
end
|
190
|
-
|
191
|
-
it 'matches the whole word' do
|
192
|
-
expect(subject.word? 'hello').to be true
|
193
|
-
expect(subject.word? 'high').to be true
|
194
|
-
end
|
195
|
-
end
|
196
|
-
end
|
197
|
-
|
198
|
-
context 'word is not contained' do
|
199
|
-
before do
|
200
|
-
subject << 'hello'
|
201
|
-
end
|
202
|
-
|
203
|
-
it 'does not match the whole word' do
|
204
|
-
expect(subject.word? 'halt').to be false
|
205
|
-
expect(subject.word? 'al').to be false
|
206
|
-
end
|
207
|
-
|
208
|
-
it 'is aliased as #include?' do
|
209
|
-
expect(subject).not_to include 'high'
|
210
|
-
end
|
211
|
-
|
212
|
-
context 'and the root has been compressed' do
|
213
|
-
before do
|
214
|
-
subject.compress!
|
215
|
-
end
|
216
|
-
|
217
|
-
it 'does not match the whole word' do
|
218
|
-
expect(subject.word? 'halt').to be false
|
219
|
-
expect(subject.word? 'al').to be false
|
220
|
-
end
|
221
|
-
end
|
222
|
-
end
|
223
|
-
end
|
224
|
-
|
225
|
-
describe '#partial_word?' do
|
226
|
-
it 'is aliased as #match?' do
|
227
|
-
subject << 'hello'
|
228
|
-
subject << 'high'
|
229
|
-
expect(subject.match? 'hel').to be true
|
230
|
-
expect(subject.match? 'hig').to be true
|
231
|
-
end
|
232
|
-
|
233
|
-
context 'word is contained' do
|
234
|
-
before do
|
235
|
-
subject << 'hello'
|
236
|
-
subject << 'high'
|
237
|
-
end
|
238
|
-
|
239
|
-
it 'matches part of the word' do
|
240
|
-
expect(subject.partial_word? 'hell').to be true
|
241
|
-
expect(subject.partial_word? 'hig').to be true
|
242
|
-
end
|
243
|
-
|
244
|
-
context 'and the root has been compressed' do
|
245
|
-
before do
|
246
|
-
subject.compress!
|
247
|
-
end
|
248
|
-
|
249
|
-
it 'matches part of the word' do
|
250
|
-
expect(subject.partial_word? 'h').to be true
|
251
|
-
expect(subject.partial_word? 'he').to be true
|
252
|
-
expect(subject.partial_word? 'hell').to be true
|
253
|
-
expect(subject.partial_word? 'hello').to be true
|
254
|
-
expect(subject.partial_word? 'hi').to be true
|
255
|
-
expect(subject.partial_word? 'hig').to be true
|
256
|
-
expect(subject.partial_word? 'high').to be true
|
257
|
-
end
|
258
|
-
end
|
259
|
-
end
|
260
|
-
|
261
|
-
context 'word is not contained' do
|
262
|
-
before do
|
263
|
-
subject << 'hello'
|
264
|
-
end
|
265
|
-
|
266
|
-
it 'does not match any part of the word' do
|
267
|
-
expect(subject.partial_word? 'ha').to be false
|
268
|
-
expect(subject.partial_word? 'hal').to be false
|
269
|
-
expect(subject.partial_word? 'al').to be false
|
270
|
-
end
|
271
|
-
|
272
|
-
context 'and the root has been compressed' do
|
273
|
-
before do
|
274
|
-
subject.compress!
|
275
|
-
end
|
276
|
-
|
277
|
-
it 'does not match any part of the word' do
|
278
|
-
expect(subject.partial_word? 'ha').to be false
|
279
|
-
expect(subject.partial_word? 'hal').to be false
|
280
|
-
expect(subject.partial_word? 'al').to be false
|
281
|
-
end
|
282
|
-
end
|
283
|
-
end
|
284
|
-
end
|
285
|
-
|
286
|
-
describe '#scan' do
|
287
|
-
context 'words that match are not contained' do
|
288
|
-
before do
|
289
|
-
subject << 'hi'
|
290
|
-
subject << 'hello'
|
291
|
-
subject << 'high'
|
292
|
-
subject << 'hell'
|
293
|
-
subject << 'highlight'
|
294
|
-
subject << 'histerical'
|
295
|
-
end
|
296
|
-
|
297
|
-
it 'returns an array with the words that match' do
|
298
|
-
expect(subject.scan 'hi').to eq [
|
299
|
-
'hi',
|
300
|
-
'high',
|
301
|
-
'highlight',
|
302
|
-
'histerical'
|
303
|
-
]
|
304
|
-
|
305
|
-
expect(subject.scan 'hig').to eq [
|
306
|
-
'high',
|
307
|
-
'highlight'
|
308
|
-
]
|
309
|
-
end
|
310
|
-
|
311
|
-
context 'and the root has been compressed' do
|
312
|
-
before do
|
313
|
-
subject.compress!
|
314
|
-
end
|
315
|
-
|
316
|
-
it 'returns an array with the words that match' do
|
317
|
-
expect(subject.scan 'hi').to eq [
|
318
|
-
'hi',
|
319
|
-
'high',
|
320
|
-
'highlight',
|
321
|
-
'histerical'
|
322
|
-
]
|
323
|
-
|
324
|
-
expect(subject.scan 'hig').to eq [
|
325
|
-
'high',
|
326
|
-
'highlight'
|
327
|
-
]
|
328
|
-
end
|
329
|
-
|
330
|
-
it 'is aliased as #words' do
|
331
|
-
expect(subject.words 'hig').to eq [
|
332
|
-
'high',
|
333
|
-
'highlight'
|
334
|
-
]
|
335
|
-
end
|
336
|
-
end
|
337
|
-
end
|
338
|
-
|
339
|
-
context 'words that match are not contained' do
|
340
|
-
before do
|
341
|
-
subject << 'hello'
|
342
|
-
end
|
343
|
-
|
344
|
-
it 'returns an empty array' do
|
345
|
-
expect(subject.scan 'hi').to eq []
|
346
|
-
end
|
347
|
-
|
348
|
-
context 'and the root has been compressed' do
|
349
|
-
before do
|
350
|
-
subject.compress!
|
351
|
-
end
|
352
|
-
|
353
|
-
it 'returns an empty array' do
|
354
|
-
expect(subject.scan 'hi').to eq []
|
355
|
-
end
|
356
|
-
end
|
357
|
-
end
|
358
|
-
end
|
359
|
-
|
360
|
-
describe '#add' do
|
361
|
-
let(:original_word) { 'word' }
|
362
|
-
let(:word) { original_word.clone }
|
363
|
-
|
364
|
-
it 'does not change the original word' do
|
365
|
-
subject.add word
|
366
|
-
expect(word).to eq original_word
|
367
|
-
end
|
368
|
-
|
369
|
-
it 'is still aliased as #<<' do
|
370
|
-
subject << word
|
371
|
-
expect(word).to eq original_word
|
372
|
-
end
|
373
|
-
end
|
374
|
-
end
|
375
|
-
end
|
376
|
-
end
|