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.
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