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