rambling-trie 0.8.1 → 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (35) hide show
  1. checksums.yaml +4 -4
  2. data/Rakefile +1 -1
  3. data/lib/rambling/trie.rb +21 -9
  4. data/lib/rambling/trie/compressed_node.rb +112 -0
  5. data/lib/rambling/trie/compression.rb +13 -0
  6. data/lib/rambling/trie/compressor.rb +30 -31
  7. data/lib/rambling/trie/{root.rb → container.rb} +41 -38
  8. data/lib/rambling/trie/enumerable.rb +11 -7
  9. data/lib/rambling/trie/missing_node.rb +1 -1
  10. data/lib/rambling/trie/node.rb +25 -22
  11. data/lib/rambling/trie/plain_text_reader.rb +1 -1
  12. data/lib/rambling/trie/raw_node.rb +90 -0
  13. data/lib/rambling/trie/tasks/helpers/path.rb +13 -0
  14. data/lib/rambling/trie/tasks/helpers/time.rb +7 -0
  15. data/lib/rambling/trie/tasks/performance.rb +10 -91
  16. data/lib/rambling/trie/tasks/performance/all.rb +4 -0
  17. data/lib/rambling/trie/tasks/performance/benchmark.rb +172 -0
  18. data/lib/rambling/trie/tasks/performance/directory.rb +11 -0
  19. data/lib/rambling/trie/tasks/performance/profile/call_tree.rb +132 -0
  20. data/lib/rambling/trie/tasks/performance/profile/memory.rb +116 -0
  21. data/lib/rambling/trie/version.rb +1 -1
  22. data/rambling-trie.gemspec +6 -4
  23. data/spec/integration/rambling/trie_spec.rb +63 -9
  24. data/spec/lib/rambling/trie/compressed_node_spec.rb +35 -0
  25. data/spec/lib/rambling/trie/compressor_spec.rb +31 -0
  26. data/spec/lib/rambling/trie/container_spec.rb +470 -0
  27. data/spec/lib/rambling/trie/enumerable_spec.rb +2 -2
  28. data/spec/lib/rambling/trie/inspector_spec.rb +21 -14
  29. data/spec/lib/rambling/trie/node_spec.rb +72 -209
  30. data/spec/lib/rambling/trie/raw_node_spec.rb +377 -0
  31. data/spec/lib/rambling/trie_spec.rb +46 -25
  32. metadata +57 -16
  33. data/lib/rambling/trie/branches.rb +0 -149
  34. data/spec/lib/rambling/trie/branches_spec.rb +0 -52
  35. 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