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,40 +1,61 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
|
-
|
4
|
-
describe
|
5
|
-
|
6
|
-
|
3
|
+
describe Rambling::Trie do
|
4
|
+
describe '.create' do
|
5
|
+
let(:container) { double :container }
|
6
|
+
|
7
|
+
before do
|
8
|
+
allow(Rambling::Trie::Container).to receive(:new)
|
9
|
+
.and_yield(container)
|
10
|
+
.and_return container
|
11
|
+
end
|
7
12
|
|
8
|
-
|
13
|
+
it 'returns a new instance of the trie container' do
|
14
|
+
expect(Rambling::Trie.create).to eq container
|
15
|
+
end
|
9
16
|
|
10
|
-
|
11
|
-
|
17
|
+
context 'with a block' do
|
18
|
+
it 'yields the new container' do
|
19
|
+
yielded_trie = nil
|
20
|
+
Rambling::Trie.create { |trie| yielded_trie = trie }
|
21
|
+
expect(yielded_trie).to eq container
|
12
22
|
end
|
23
|
+
end
|
13
24
|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
25
|
+
context 'with a filepath' do
|
26
|
+
let(:filepath) { 'test_words.txt' }
|
27
|
+
let(:reader) { double :reader }
|
28
|
+
let(:words) { %w(a couple of test words over here) }
|
29
|
+
|
30
|
+
before do
|
31
|
+
receive_and_yield = receive(:each_word)
|
32
|
+
words.inject(receive_and_yield) { |yielder, word| yielder.and_yield word }
|
33
|
+
allow(reader).to receive_and_yield
|
34
|
+
allow(container).to receive :<<
|
20
35
|
end
|
21
36
|
|
22
|
-
|
23
|
-
|
24
|
-
let(:reader) { double :reader }
|
25
|
-
let(:words) { %w(a couple of test words over here) }
|
37
|
+
it 'loads every word' do
|
38
|
+
Rambling::Trie.create filepath, reader
|
26
39
|
|
27
|
-
|
28
|
-
|
29
|
-
words.inject(receive_and_yield) { |yielder, word| yielder.and_yield word }
|
30
|
-
allow(reader).to receive_and_yield
|
40
|
+
words.each do |word|
|
41
|
+
expect(container).to have_received(:<<).with(word)
|
31
42
|
end
|
43
|
+
end
|
44
|
+
end
|
32
45
|
|
33
|
-
|
34
|
-
|
46
|
+
context 'without any reader' do
|
47
|
+
let(:filepath) { 'test_words.txt' }
|
48
|
+
let(:reader) { double :reader, each_word: nil }
|
35
49
|
|
36
|
-
|
37
|
-
|
50
|
+
before do
|
51
|
+
allow(Rambling::Trie::PlainTextReader).to receive(:new)
|
52
|
+
.and_return reader
|
53
|
+
end
|
54
|
+
|
55
|
+
it 'defaults to the PlainTextReader' do
|
56
|
+
Rambling::Trie.create filepath, nil
|
57
|
+
|
58
|
+
expect(reader).to have_received(:each_word).with filepath
|
38
59
|
end
|
39
60
|
end
|
40
61
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rambling-trie
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.9.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Edgar Gonzalez
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2016-12-
|
12
|
+
date: 2016-12-25 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rspec
|
@@ -17,56 +17,84 @@ dependencies:
|
|
17
17
|
requirements:
|
18
18
|
- - "~>"
|
19
19
|
- !ruby/object:Gem::Version
|
20
|
-
version: '3.
|
20
|
+
version: '3.5'
|
21
21
|
type: :development
|
22
22
|
prerelease: false
|
23
23
|
version_requirements: !ruby/object:Gem::Requirement
|
24
24
|
requirements:
|
25
25
|
- - "~>"
|
26
26
|
- !ruby/object:Gem::Version
|
27
|
-
version: '3.
|
27
|
+
version: '3.5'
|
28
28
|
- !ruby/object:Gem::Dependency
|
29
29
|
name: rake
|
30
30
|
requirement: !ruby/object:Gem::Requirement
|
31
31
|
requirements:
|
32
32
|
- - "~>"
|
33
33
|
- !ruby/object:Gem::Version
|
34
|
-
version: '
|
34
|
+
version: '12.0'
|
35
35
|
type: :development
|
36
36
|
prerelease: false
|
37
37
|
version_requirements: !ruby/object:Gem::Requirement
|
38
38
|
requirements:
|
39
39
|
- - "~>"
|
40
40
|
- !ruby/object:Gem::Version
|
41
|
-
version: '
|
41
|
+
version: '12.0'
|
42
42
|
- !ruby/object:Gem::Dependency
|
43
43
|
name: ruby-prof
|
44
44
|
requirement: !ruby/object:Gem::Requirement
|
45
45
|
requirements:
|
46
46
|
- - "~>"
|
47
47
|
- !ruby/object:Gem::Version
|
48
|
-
version: 0.
|
48
|
+
version: 0.16.2
|
49
49
|
type: :development
|
50
50
|
prerelease: false
|
51
51
|
version_requirements: !ruby/object:Gem::Requirement
|
52
52
|
requirements:
|
53
53
|
- - "~>"
|
54
54
|
- !ruby/object:Gem::Version
|
55
|
-
version: 0.
|
55
|
+
version: 0.16.2
|
56
|
+
- !ruby/object:Gem::Dependency
|
57
|
+
name: memory_profiler
|
58
|
+
requirement: !ruby/object:Gem::Requirement
|
59
|
+
requirements:
|
60
|
+
- - "~>"
|
61
|
+
- !ruby/object:Gem::Version
|
62
|
+
version: 0.9.7
|
63
|
+
type: :development
|
64
|
+
prerelease: false
|
65
|
+
version_requirements: !ruby/object:Gem::Requirement
|
66
|
+
requirements:
|
67
|
+
- - "~>"
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: 0.9.7
|
70
|
+
- !ruby/object:Gem::Dependency
|
71
|
+
name: benchmark-ips
|
72
|
+
requirement: !ruby/object:Gem::Requirement
|
73
|
+
requirements:
|
74
|
+
- - "~>"
|
75
|
+
- !ruby/object:Gem::Version
|
76
|
+
version: 2.7.2
|
77
|
+
type: :development
|
78
|
+
prerelease: false
|
79
|
+
version_requirements: !ruby/object:Gem::Requirement
|
80
|
+
requirements:
|
81
|
+
- - "~>"
|
82
|
+
- !ruby/object:Gem::Version
|
83
|
+
version: 2.7.2
|
56
84
|
- !ruby/object:Gem::Dependency
|
57
85
|
name: yard
|
58
86
|
requirement: !ruby/object:Gem::Requirement
|
59
87
|
requirements:
|
60
88
|
- - "~>"
|
61
89
|
- !ruby/object:Gem::Version
|
62
|
-
version: 0.
|
90
|
+
version: 0.9.5
|
63
91
|
type: :development
|
64
92
|
prerelease: false
|
65
93
|
version_requirements: !ruby/object:Gem::Requirement
|
66
94
|
requirements:
|
67
95
|
- - "~>"
|
68
96
|
- !ruby/object:Gem::Version
|
69
|
-
version: 0.
|
97
|
+
version: 0.9.5
|
70
98
|
- !ruby/object:Gem::Dependency
|
71
99
|
name: redcarpet
|
72
100
|
requirement: !ruby/object:Gem::Requirement
|
@@ -103,28 +131,39 @@ files:
|
|
103
131
|
- assets/dictionaries/words_with_friends.txt
|
104
132
|
- lib/rambling-trie.rb
|
105
133
|
- lib/rambling/trie.rb
|
106
|
-
- lib/rambling/trie/
|
134
|
+
- lib/rambling/trie/compressed_node.rb
|
135
|
+
- lib/rambling/trie/compression.rb
|
107
136
|
- lib/rambling/trie/compressor.rb
|
137
|
+
- lib/rambling/trie/container.rb
|
108
138
|
- lib/rambling/trie/enumerable.rb
|
109
139
|
- lib/rambling/trie/inspector.rb
|
110
140
|
- lib/rambling/trie/invalid_operation.rb
|
111
141
|
- lib/rambling/trie/missing_node.rb
|
112
142
|
- lib/rambling/trie/node.rb
|
113
143
|
- lib/rambling/trie/plain_text_reader.rb
|
114
|
-
- lib/rambling/trie/
|
144
|
+
- lib/rambling/trie/raw_node.rb
|
115
145
|
- lib/rambling/trie/tasks/gem.rb
|
146
|
+
- lib/rambling/trie/tasks/helpers/path.rb
|
147
|
+
- lib/rambling/trie/tasks/helpers/time.rb
|
116
148
|
- lib/rambling/trie/tasks/performance.rb
|
149
|
+
- lib/rambling/trie/tasks/performance/all.rb
|
150
|
+
- lib/rambling/trie/tasks/performance/benchmark.rb
|
151
|
+
- lib/rambling/trie/tasks/performance/directory.rb
|
152
|
+
- lib/rambling/trie/tasks/performance/profile/call_tree.rb
|
153
|
+
- lib/rambling/trie/tasks/performance/profile/memory.rb
|
117
154
|
- lib/rambling/trie/version.rb
|
118
155
|
- rambling-trie.gemspec
|
119
156
|
- reports/performance
|
120
157
|
- spec/assets/test_words.txt
|
121
158
|
- spec/integration/rambling/trie_spec.rb
|
122
|
-
- spec/lib/rambling/trie/
|
159
|
+
- spec/lib/rambling/trie/compressed_node_spec.rb
|
160
|
+
- spec/lib/rambling/trie/compressor_spec.rb
|
161
|
+
- spec/lib/rambling/trie/container_spec.rb
|
123
162
|
- spec/lib/rambling/trie/enumerable_spec.rb
|
124
163
|
- spec/lib/rambling/trie/inspector_spec.rb
|
125
164
|
- spec/lib/rambling/trie/node_spec.rb
|
126
165
|
- spec/lib/rambling/trie/plain_text_reader_spec.rb
|
127
|
-
- spec/lib/rambling/trie/
|
166
|
+
- spec/lib/rambling/trie/raw_node_spec.rb
|
128
167
|
- spec/lib/rambling/trie_spec.rb
|
129
168
|
- spec/spec_helper.rb
|
130
169
|
homepage: http://github.com/gonzedge/rambling-trie
|
@@ -154,11 +193,13 @@ summary: A custom implementation of the trie data structure.
|
|
154
193
|
test_files:
|
155
194
|
- spec/assets/test_words.txt
|
156
195
|
- spec/integration/rambling/trie_spec.rb
|
157
|
-
- spec/lib/rambling/trie/
|
196
|
+
- spec/lib/rambling/trie/compressed_node_spec.rb
|
197
|
+
- spec/lib/rambling/trie/compressor_spec.rb
|
198
|
+
- spec/lib/rambling/trie/container_spec.rb
|
158
199
|
- spec/lib/rambling/trie/enumerable_spec.rb
|
159
200
|
- spec/lib/rambling/trie/inspector_spec.rb
|
160
201
|
- spec/lib/rambling/trie/node_spec.rb
|
161
202
|
- spec/lib/rambling/trie/plain_text_reader_spec.rb
|
162
|
-
- spec/lib/rambling/trie/
|
203
|
+
- spec/lib/rambling/trie/raw_node_spec.rb
|
163
204
|
- spec/lib/rambling/trie_spec.rb
|
164
205
|
- spec/spec_helper.rb
|
@@ -1,149 +0,0 @@
|
|
1
|
-
module Rambling
|
2
|
-
module Trie
|
3
|
-
# Provides the branching behavior for the Trie data structure.
|
4
|
-
module Branches
|
5
|
-
# Adds a branch to the current trie node based on the word
|
6
|
-
# @param [String] word the word to add the branch from.
|
7
|
-
# @return [Node] the just added branch's root node.
|
8
|
-
# @raise [InvalidOperation] if the trie is already compressed.
|
9
|
-
# @note This method clears the contents of the word variable.
|
10
|
-
def add word
|
11
|
-
raise InvalidOperation, 'Cannot add branch to compressed trie' if compressed?
|
12
|
-
if word.empty?
|
13
|
-
self.terminal = true
|
14
|
-
else
|
15
|
-
add_to_children_tree word
|
16
|
-
end
|
17
|
-
end
|
18
|
-
|
19
|
-
# Alias for #add
|
20
|
-
# @param [String] word the word to add the branch from.
|
21
|
-
# @return [Node] the just added branch's root node.
|
22
|
-
# @raise [InvalidOperation] if the trie is already compressed.
|
23
|
-
# @see Branches#add
|
24
|
-
def << word
|
25
|
-
add word
|
26
|
-
end
|
27
|
-
|
28
|
-
protected
|
29
|
-
|
30
|
-
def partial_word_when_uncompressed? chars
|
31
|
-
chars.empty? || fulfills_uncompressed_condition?(:partial_word_when_uncompressed?, chars)
|
32
|
-
end
|
33
|
-
|
34
|
-
def partial_word_when_compressed? chars
|
35
|
-
chars.empty? || compressed_trie_has_partial_word?(chars)
|
36
|
-
end
|
37
|
-
|
38
|
-
def word_when_uncompressed? chars
|
39
|
-
if chars.empty?
|
40
|
-
terminal?
|
41
|
-
else
|
42
|
-
fulfills_uncompressed_condition? :word_when_uncompressed?, chars
|
43
|
-
end
|
44
|
-
end
|
45
|
-
|
46
|
-
def word_when_compressed? chars
|
47
|
-
if chars.empty?
|
48
|
-
terminal?
|
49
|
-
else
|
50
|
-
compressed_trie_has_word? chars
|
51
|
-
end
|
52
|
-
end
|
53
|
-
|
54
|
-
def closest_node_when_uncompressed chars
|
55
|
-
if chars.empty?
|
56
|
-
self
|
57
|
-
else
|
58
|
-
first_letter_sym = chars.slice!(0).to_sym
|
59
|
-
if children_tree.has_key? first_letter_sym
|
60
|
-
children_tree[first_letter_sym].closest_node_when_uncompressed chars
|
61
|
-
else
|
62
|
-
Rambling::Trie::MissingNode.new
|
63
|
-
end
|
64
|
-
end
|
65
|
-
end
|
66
|
-
|
67
|
-
def closest_node_when_compressed chars
|
68
|
-
if chars.empty?
|
69
|
-
self
|
70
|
-
else
|
71
|
-
current_length = 0
|
72
|
-
current_key, current_key_string = current_key chars.slice!(0)
|
73
|
-
|
74
|
-
begin
|
75
|
-
current_length += 1
|
76
|
-
|
77
|
-
if current_key_string.length == current_length || chars.empty?
|
78
|
-
return children_tree[current_key].closest_node_when_compressed chars
|
79
|
-
end
|
80
|
-
end while current_key_string[current_length] == chars.slice!(0)
|
81
|
-
|
82
|
-
Rambling::Trie::MissingNode.new
|
83
|
-
end
|
84
|
-
end
|
85
|
-
|
86
|
-
private
|
87
|
-
|
88
|
-
def add_to_children_tree word
|
89
|
-
first_letter = word.slice(0).to_sym
|
90
|
-
|
91
|
-
if children_tree.has_key? first_letter
|
92
|
-
word.slice! 0
|
93
|
-
child = children_tree[first_letter]
|
94
|
-
child << word
|
95
|
-
child
|
96
|
-
else
|
97
|
-
children_tree[first_letter] = Node.new word, self
|
98
|
-
end
|
99
|
-
end
|
100
|
-
|
101
|
-
def compressed_trie_has_partial_word? chars
|
102
|
-
current_length = 0
|
103
|
-
current_key, current_key_string = current_key chars.slice!(0)
|
104
|
-
|
105
|
-
begin
|
106
|
-
current_length += 1
|
107
|
-
|
108
|
-
if current_key_string.length == current_length || chars.empty?
|
109
|
-
return children_tree[current_key].partial_word_when_compressed? chars
|
110
|
-
end
|
111
|
-
end while current_key_string[current_length] == chars.slice!(0)
|
112
|
-
|
113
|
-
false
|
114
|
-
end
|
115
|
-
|
116
|
-
def compressed_trie_has_word? chars
|
117
|
-
current_key_string = ''
|
118
|
-
|
119
|
-
while !chars.empty?
|
120
|
-
current_key_string << chars.slice!(0)
|
121
|
-
current_key = current_key_string.to_sym
|
122
|
-
return children_tree[current_key].word_when_compressed? chars if children_tree.has_key? current_key
|
123
|
-
end
|
124
|
-
|
125
|
-
false
|
126
|
-
end
|
127
|
-
|
128
|
-
def current_key letter
|
129
|
-
current_key_string = current_key = ''
|
130
|
-
|
131
|
-
children_tree.keys.each do |key|
|
132
|
-
key_string = key.to_s
|
133
|
-
if key_string.start_with? letter
|
134
|
-
current_key = key
|
135
|
-
current_key_string = key_string
|
136
|
-
break
|
137
|
-
end
|
138
|
-
end
|
139
|
-
|
140
|
-
[current_key, current_key_string]
|
141
|
-
end
|
142
|
-
|
143
|
-
def fulfills_uncompressed_condition? method, chars
|
144
|
-
first_letter_sym = chars.slice!(0).to_sym
|
145
|
-
children_tree.has_key?(first_letter_sym) && children_tree[first_letter_sym].send(method, chars)
|
146
|
-
end
|
147
|
-
end
|
148
|
-
end
|
149
|
-
end
|
@@ -1,52 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
module Rambling
|
4
|
-
module Trie
|
5
|
-
describe Branches do
|
6
|
-
describe '#add' do
|
7
|
-
context 'new word for existing branch' do
|
8
|
-
let(:node) { Node.new 'back' }
|
9
|
-
|
10
|
-
before do
|
11
|
-
node.add 'a'
|
12
|
-
end
|
13
|
-
|
14
|
-
it 'does not increment the child count' do
|
15
|
-
expect(node.children.size).to eq 1
|
16
|
-
end
|
17
|
-
|
18
|
-
it 'marks it as terminal' do
|
19
|
-
expect(node[:a]).to be_terminal
|
20
|
-
end
|
21
|
-
|
22
|
-
it 'returns the added node' do
|
23
|
-
expect(node.add('a').letter).to eq :a
|
24
|
-
end
|
25
|
-
end
|
26
|
-
|
27
|
-
context 'old word for existing branch' do
|
28
|
-
let(:node) { Node.new 'back' }
|
29
|
-
|
30
|
-
before do
|
31
|
-
node.add 'ack'
|
32
|
-
end
|
33
|
-
|
34
|
-
it 'does not increment any child count' do
|
35
|
-
expect(node.children.size).to eq 1
|
36
|
-
expect(node[:a].children.size).to eq 1
|
37
|
-
expect(node[:a][:c].children.size).to eq 1
|
38
|
-
expect(node[:a][:c][:k].children.size).to eq 0
|
39
|
-
end
|
40
|
-
end
|
41
|
-
end
|
42
|
-
|
43
|
-
describe '#<<' do
|
44
|
-
let(:node) { Node.new }
|
45
|
-
|
46
|
-
it 'delegates to #add' do
|
47
|
-
expect((node << 'a').letter).to eq :a
|
48
|
-
end
|
49
|
-
end
|
50
|
-
end
|
51
|
-
end
|
52
|
-
end
|