rambling-trie 2.5.0 → 2.5.1
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/Dockerfile +28 -0
- data/Gemfile +18 -9
- data/Guardfile +16 -5
- data/README.md +23 -23
- data/Rakefile +6 -0
- data/Steepfile +35 -0
- data/lib/rambling/trie/comparable.rb +2 -2
- data/lib/rambling/trie/compressible.rb +1 -1
- data/lib/rambling/trie/compressor.rb +22 -21
- data/lib/rambling/trie/configuration/properties.rb +5 -4
- data/lib/rambling/trie/configuration/provider_collection.rb +12 -7
- data/lib/rambling/trie/configuration.rb +2 -3
- data/lib/rambling/trie/container.rb +20 -23
- data/lib/rambling/trie/enumerable.rb +4 -5
- data/lib/rambling/trie/nodes/compressed.rb +26 -16
- data/lib/rambling/trie/nodes/node.rb +31 -8
- data/lib/rambling/trie/nodes/raw.rb +16 -19
- data/lib/rambling/trie/nodes.rb +2 -3
- data/lib/rambling/trie/readers/plain_text.rb +2 -2
- data/lib/rambling/trie/readers.rb +2 -3
- data/lib/rambling/trie/serializers/marshal.rb +1 -1
- data/lib/rambling/trie/serializers/yaml.rb +1 -1
- data/lib/rambling/trie/serializers/zip.rb +12 -6
- data/lib/rambling/trie/serializers.rb +2 -3
- data/lib/rambling/trie/stringifyable.rb +1 -1
- data/lib/rambling/trie/version.rb +1 -1
- data/lib/rambling/trie.rb +11 -14
- data/rambling-trie.gemspec +1 -1
- data/sig/lib/rambling/trie/comparable.rbs +17 -0
- data/sig/lib/rambling/trie/compressible.rbs +17 -0
- data/sig/lib/rambling/trie/compressor.rbs +17 -0
- data/sig/lib/rambling/trie/configuration/properties.rbs +28 -0
- data/sig/lib/rambling/trie/configuration/provider_collection.rbs +47 -0
- data/sig/lib/rambling/trie/container.rbs +69 -0
- data/sig/lib/rambling/trie/enumerable.rbs +23 -0
- data/sig/lib/rambling/trie/inspectable.rbs +27 -0
- data/sig/lib/rambling/trie/invalid_operation.rbs +7 -0
- data/sig/lib/rambling/trie/nodes/compressed.rbs +25 -0
- data/sig/lib/rambling/trie/nodes/missing.rbs +9 -0
- data/sig/lib/rambling/trie/nodes/node.rbs +69 -0
- data/sig/lib/rambling/trie/nodes/raw.rbs +27 -0
- data/sig/lib/rambling/trie/readers/plain_text.rbs +9 -0
- data/sig/lib/rambling/trie/readers/reader.rbs +9 -0
- data/sig/lib/rambling/trie/serializers/file.rbs +8 -0
- data/sig/lib/rambling/trie/serializers/marshal.rbs +13 -0
- data/sig/lib/rambling/trie/serializers/serializer.rbs +10 -0
- data/sig/lib/rambling/trie/serializers/yaml.rbs +13 -0
- data/sig/lib/rambling/trie/serializers/zip.rbs +21 -0
- data/sig/lib/rambling/trie/stringifyable.rbs +21 -0
- data/sig/lib/rambling/trie.rbs +27 -0
- data/sig/lib/zip/entry.rbs +11 -0
- data/sig/lib/zip/file.rbs +11 -0
- metadata +29 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4c38f152f6ffdb5b7c3f5abde873ae3024651a52a7697fa4e706d01e28fe504e
|
4
|
+
data.tar.gz: 8cdec337b99995019a24d702b48dce2ee3e9a9e6acde298cd5cfef8086e93bc9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6bbadda2f93e7efdae19f0db8749e304be56b288d62095a269904c4d6e3b6e2f7723acba618fd4e8e8de416108ca9e6249c7a6c9ce5a70e70036e6ad287cb7e2
|
7
|
+
data.tar.gz: b60a49628ba61bca14d5a92573df83203feb0346d306adbc628ab7dfad54da82574902ee1f4985a365582a6c5a285b788a108ee7e7d2c22b0ce3f06dc5eccf78
|
data/Dockerfile
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
FROM ruby:3.3.6
|
2
|
+
|
3
|
+
RUN bundle config --global frozen 1
|
4
|
+
|
5
|
+
WORKDIR /usr/rambling-trie
|
6
|
+
RUN git init
|
7
|
+
|
8
|
+
# Copy strictly what is necessary to install dependencies
|
9
|
+
COPY Gemfile Gemfile.lock rambling-trie.gemspec ./
|
10
|
+
COPY lib ./lib
|
11
|
+
|
12
|
+
# Install dependencies
|
13
|
+
RUN bundle install
|
14
|
+
|
15
|
+
# Copy rest of Ruby and Markdown files
|
16
|
+
COPY Rakefile ./
|
17
|
+
COPY *.md ./
|
18
|
+
COPY assets ./assets
|
19
|
+
COPY sig ./sig
|
20
|
+
COPY spec ./spec
|
21
|
+
COPY tasks ./tasks
|
22
|
+
COPY scripts ./scripts
|
23
|
+
|
24
|
+
# Copy rest of configuration files
|
25
|
+
COPY *file ./
|
26
|
+
COPY *.yml ./
|
27
|
+
COPY .mdl* ./
|
28
|
+
COPY .yardopts ./
|
data/Gemfile
CHANGED
@@ -7,29 +7,38 @@ gemspec
|
|
7
7
|
gem 'rubyzip'
|
8
8
|
|
9
9
|
group :development do
|
10
|
-
gem 'benchmark-ips'
|
11
|
-
gem 'flamegraph'
|
12
|
-
gem 'memory_profiler'
|
13
|
-
gem 'pry'
|
14
10
|
gem 'rake'
|
15
11
|
gem 'rspec'
|
16
|
-
gem 'ruby-prof'
|
17
|
-
gem 'stackprof'
|
18
|
-
gem 'yard'
|
19
12
|
end
|
20
13
|
|
21
14
|
group :test do
|
22
|
-
gem 'coveralls_reborn',
|
15
|
+
gem 'coveralls_reborn', require: false
|
23
16
|
gem 'rspec_junit_formatter'
|
24
17
|
gem 'simplecov', require: false
|
25
18
|
end
|
26
19
|
|
27
20
|
group :local do
|
21
|
+
gem 'benchmark-ips', require: false
|
22
|
+
gem 'flamegraph', require: false
|
28
23
|
gem 'flog', require: false
|
29
|
-
gem 'guard
|
24
|
+
gem 'guard', require: false
|
25
|
+
gem 'guard-reek', require: false
|
26
|
+
gem 'guard-rspec', require: false
|
27
|
+
gem 'guard-rubocop', require: false
|
28
|
+
gem 'guard-yard', require: false
|
30
29
|
gem 'mdl', require: false
|
30
|
+
gem 'memory_profiler', require: false
|
31
|
+
gem 'pry', require: false
|
32
|
+
gem 'racc', require: false
|
33
|
+
gem 'rbs', require: false
|
34
|
+
gem 'redcarpet', require: false
|
35
|
+
gem 'reek', require: false
|
31
36
|
gem 'rubocop', require: false
|
32
37
|
gem 'rubocop-performance', require: false
|
33
38
|
gem 'rubocop-rake', require: false
|
34
39
|
gem 'rubocop-rspec', require: false
|
40
|
+
gem 'ruby-prof', require: false
|
41
|
+
gem 'stackprof', require: false
|
42
|
+
gem 'steep', require: false
|
43
|
+
gem 'yard', require: false
|
35
44
|
end
|
data/Guardfile
CHANGED
@@ -1,10 +1,21 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
4
|
-
# More info at https://github.com/guard/guard#readme
|
3
|
+
LIB_REGEX = %r{^lib/(.+)\.rb$}
|
5
4
|
|
6
|
-
guard
|
5
|
+
guard :reek, all_on_start: true, run_all: true do
|
6
|
+
watch(LIB_REGEX)
|
7
|
+
end
|
8
|
+
|
9
|
+
guard :rspec, cmd: 'rspec', all_on_start: true, all_after_pass: false do
|
7
10
|
watch(%r{^spec/.+_spec\.rb$})
|
8
|
-
watch(
|
9
|
-
watch('spec/spec_helper.rb')
|
11
|
+
watch(LIB_REGEX) { |m| "spec/lib/#{m[1]}_spec.rb" }
|
12
|
+
watch('spec/spec_helper.rb') { 'spec' }
|
13
|
+
end
|
14
|
+
|
15
|
+
guard :rubocop, all_on_start: true do
|
16
|
+
watch(LIB_REGEX)
|
17
|
+
end
|
18
|
+
|
19
|
+
guard :yard, server: false do
|
20
|
+
watch(LIB_REGEX)
|
10
21
|
end
|
data/README.md
CHANGED
@@ -30,13 +30,13 @@ See [RVM][rvm], [rbenv][rbenv] or [chruby][chruby] for more information on how t
|
|
30
30
|
|
31
31
|
You can either install it manually with:
|
32
32
|
|
33
|
-
```
|
33
|
+
```shell
|
34
34
|
gem install rambling-trie
|
35
35
|
```
|
36
36
|
|
37
37
|
Or, include it in your `Gemfile` and bundle it:
|
38
38
|
|
39
|
-
```
|
39
|
+
```ruby
|
40
40
|
gem 'rambling-trie'
|
41
41
|
```
|
42
42
|
|
@@ -46,13 +46,13 @@ gem 'rambling-trie'
|
|
46
46
|
|
47
47
|
To create a new trie, initialize it like this:
|
48
48
|
|
49
|
-
```
|
49
|
+
```ruby
|
50
50
|
trie = Rambling::Trie.create
|
51
51
|
```
|
52
52
|
|
53
53
|
You can also provide a block and the created trie instance will be yielded for you to perform any operation on it:
|
54
54
|
|
55
|
-
```
|
55
|
+
```ruby
|
56
56
|
Rambling::Trie.create do |trie|
|
57
57
|
trie << 'word'
|
58
58
|
end
|
@@ -61,13 +61,13 @@ end
|
|
61
61
|
Additionally, you can provide the path to a file that contains all the words to be added to the trie, and it will read
|
62
62
|
the file and create the complete structure for you, like this:
|
63
63
|
|
64
|
-
```
|
64
|
+
```ruby
|
65
65
|
trie = Rambling::Trie.create '/path/to/file'
|
66
66
|
```
|
67
67
|
|
68
68
|
By default, a plain text file with the following format will be expected:
|
69
69
|
|
70
|
-
```
|
70
|
+
```text
|
71
71
|
some
|
72
72
|
words
|
73
73
|
to
|
@@ -85,14 +85,14 @@ readers.
|
|
85
85
|
|
86
86
|
To add new words to the trie, use `#add` or its alias `#<<`:
|
87
87
|
|
88
|
-
```
|
88
|
+
```ruby
|
89
89
|
trie.add 'word'
|
90
90
|
trie << 'word'
|
91
91
|
```
|
92
92
|
|
93
93
|
Or if you have multiple words to add, you can use `#concat` or `#push`:
|
94
94
|
|
95
|
-
```
|
95
|
+
```ruby
|
96
96
|
trie.concat %w(a collection of words)
|
97
97
|
trie.push 'a', 'collection', 'of', 'words'
|
98
98
|
|
@@ -104,7 +104,7 @@ trie.push *words
|
|
104
104
|
|
105
105
|
And to find out if a word already exists in the trie, use `#word?` or its alias `#include?`:
|
106
106
|
|
107
|
-
```
|
107
|
+
```ruby
|
108
108
|
trie.word? 'word'
|
109
109
|
trie.include? 'word'
|
110
110
|
```
|
@@ -112,21 +112,21 @@ trie.include? 'word'
|
|
112
112
|
If you wish to find if part of a word exists in the trie instance, you should call `#partial_word?` or its
|
113
113
|
alias `#match?`:
|
114
114
|
|
115
|
-
```
|
115
|
+
```ruby
|
116
116
|
trie.partial_word? 'partial_word'
|
117
117
|
trie.match? 'partial_word'
|
118
118
|
```
|
119
119
|
|
120
120
|
To get all the words that start with a particular string, you can use `#scan` or its alias `#words`:
|
121
121
|
|
122
|
-
```
|
122
|
+
```ruby
|
123
123
|
trie.scan 'hi' # => ['hi', 'high', 'highlight', ...]
|
124
124
|
trie.words 'hi' # => ['hi', 'high', 'highlight', ...]
|
125
125
|
```
|
126
126
|
|
127
127
|
To get all the words within a given string, you can use `#words_within`:
|
128
128
|
|
129
|
-
```
|
129
|
+
```ruby
|
130
130
|
trie.words_within 'ifdxawesome45someword3' # => ['if', 'aw', 'awe', ...]
|
131
131
|
trie.words_within 'tktktktk' # => []
|
132
132
|
```
|
@@ -134,7 +134,7 @@ trie.words_within 'tktktktk' # => []
|
|
134
134
|
Or, if you're just interested in knowing whether a given string contains any valid words or not, you can
|
135
135
|
use `#words_within?`:
|
136
136
|
|
137
|
-
```
|
137
|
+
```ruby
|
138
138
|
trie.words_within? 'ifdxawesome45someword3' # => true
|
139
139
|
trie.words_within? 'tktktktk' # => false
|
140
140
|
```
|
@@ -144,7 +144,7 @@ trie.words_within? 'tktktktk' # => false
|
|
144
144
|
By default, the Rambling Trie works as a standard trie. Starting from version 0.1.0, you can obtain a compressed trie
|
145
145
|
from the standard one, by using the compression feature. Just call the `#compress!` method on the trie instance:
|
146
146
|
|
147
|
-
```
|
147
|
+
```ruby
|
148
148
|
trie.compress!
|
149
149
|
```
|
150
150
|
|
@@ -157,13 +157,13 @@ non-terminal nodes).
|
|
157
157
|
|
158
158
|
If you want, you can also create a new compressed trie and leave the existing one intact. Just use `#compress` instead:
|
159
159
|
|
160
|
-
```
|
160
|
+
```ruby
|
161
161
|
compressed_trie = trie.compress
|
162
162
|
```
|
163
163
|
|
164
164
|
You can find out if a trie instance is compressed by calling the `#compressed?` method. From the `#compress` example:
|
165
165
|
|
166
|
-
```
|
166
|
+
```ruby
|
167
167
|
trie.compressed? # => false
|
168
168
|
compressed_trie.compressed? # => true
|
169
169
|
```
|
@@ -173,7 +173,7 @@ compressed_trie.compressed? # => true
|
|
173
173
|
Starting from version 0.4.2, you can use any `Enumerable` method over a trie instance, and it will iterate over each
|
174
174
|
word contained in the trie. You can now do things like:
|
175
175
|
|
176
|
-
```
|
176
|
+
```ruby
|
177
177
|
trie.each { |word| puts word }
|
178
178
|
trie.any? { |word| word.include? 'x' }
|
179
179
|
trie.all? { |word| word.include? 'x' }
|
@@ -189,14 +189,14 @@ change with little frequency.
|
|
189
189
|
|
190
190
|
To store a trie on disk, you can use `.dump` like this:
|
191
191
|
|
192
|
-
```
|
192
|
+
```ruby
|
193
193
|
Rambling::Trie.dump trie, '/path/to/file'
|
194
194
|
```
|
195
195
|
|
196
196
|
Then, when you need to use a trie next time, you don't have to create a new one with all the necessary words. Rather,
|
197
197
|
you can retrieve a previously stored one with `.load` like this:
|
198
198
|
|
199
|
-
```
|
199
|
+
```ruby
|
200
200
|
trie = Rambling::Trie.load '/path/to/file'
|
201
201
|
```
|
202
202
|
|
@@ -214,19 +214,19 @@ Currently, these formats are supported to store tries on disk:
|
|
214
214
|
Optionally, you can use a `.zip` version of the supported formats. In order to do so, you'll have to install
|
215
215
|
the [`rubyzip`][rubyzip] gem:
|
216
216
|
|
217
|
-
```
|
217
|
+
```shell
|
218
218
|
gem install rubyzip
|
219
219
|
```
|
220
220
|
|
221
221
|
Or, include it in your `Gemfile` and bundle it:
|
222
222
|
|
223
|
-
```
|
223
|
+
```ruby
|
224
224
|
gem 'rubyzip'
|
225
225
|
```
|
226
226
|
|
227
227
|
Then, you can load contents form a `.zip` file like this:
|
228
228
|
|
229
|
-
```
|
229
|
+
```ruby
|
230
230
|
require 'zip'
|
231
231
|
trie = Rambling::Trie.load '/path/to/file.zip'
|
232
232
|
```
|
@@ -316,7 +316,7 @@ WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEM
|
|
316
316
|
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
317
317
|
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
318
318
|
|
319
|
-
[badge_fury_badge]: https://badge.fury.io/rb/rambling-trie.svg?version=2.5.
|
319
|
+
[badge_fury_badge]: https://badge.fury.io/rb/rambling-trie.svg?version=2.5.1
|
320
320
|
[badge_fury_link]: https://badge.fury.io/rb/rambling-trie
|
321
321
|
[chruby]: https://github.com/postmodern/chruby
|
322
322
|
[code_climate_grade_badge]: https://codeclimate.com/github/gonzedge/rambling-trie/badges/gpa.svg
|
data/Rakefile
CHANGED
@@ -1,8 +1,11 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require 'bundler/gem_tasks'
|
4
|
+
require 'reek/rake/task'
|
4
5
|
require 'rspec/core/rake_task'
|
5
6
|
require 'rubocop/rake_task'
|
7
|
+
require 'steep/rake_task'
|
8
|
+
require 'yard'
|
6
9
|
|
7
10
|
require 'rambling-trie'
|
8
11
|
require_relative 'tasks/performance'
|
@@ -10,6 +13,9 @@ require_relative 'tasks/serialization'
|
|
10
13
|
require_relative 'tasks/ips'
|
11
14
|
|
12
15
|
RSpec::Core::RakeTask.new :spec
|
16
|
+
Reek::Rake::Task.new :reek
|
13
17
|
RuboCop::RakeTask.new :rubocop
|
18
|
+
Steep::RakeTask.new :steep
|
19
|
+
YARD::Rake::YardocTask.new :yard
|
14
20
|
|
15
21
|
task default: :spec
|
data/Steepfile
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# D = Steep::Diagnostic
|
4
|
+
#
|
5
|
+
target :lib do
|
6
|
+
signature 'sig'
|
7
|
+
|
8
|
+
check 'lib'
|
9
|
+
# check 'tasks'
|
10
|
+
|
11
|
+
# check 'Gemfile'
|
12
|
+
# check 'Guardfile'
|
13
|
+
# check 'Rakefile'
|
14
|
+
# check 'Steepfile'
|
15
|
+
|
16
|
+
# library 'rubyzip'
|
17
|
+
library 'yaml'
|
18
|
+
library 'securerandom'
|
19
|
+
|
20
|
+
# configure_code_diagnostics(D::Ruby.default) # `default` diagnostics setting (applies by default)
|
21
|
+
# configure_code_diagnostics(D::Ruby.strict) # `strict` diagnostics setting
|
22
|
+
# configure_code_diagnostics(D::Ruby.lenient) # `lenient` diagnostics setting
|
23
|
+
# configure_code_diagnostics(D::Ruby.silent) # `silent` diagnostics setting
|
24
|
+
# configure_code_diagnostics do |hash| # You can setup everything yourself
|
25
|
+
# hash[D::Ruby::NoMethod] = :information
|
26
|
+
# end
|
27
|
+
end
|
28
|
+
|
29
|
+
# target :test do
|
30
|
+
# signature 'sig', 'sig-private'
|
31
|
+
#
|
32
|
+
# check 'test'
|
33
|
+
#
|
34
|
+
# # library 'pathname' # Standard libraries
|
35
|
+
# end
|
@@ -6,8 +6,8 @@ module Rambling
|
|
6
6
|
module Comparable
|
7
7
|
# Compares two nodes.
|
8
8
|
# @param [Nodes::Node] other the node to compare against.
|
9
|
-
# @return [Boolean]
|
10
|
-
# {Nodes::Node#children_tree #children_tree} are equal,
|
9
|
+
# @return [Boolean] `true` if the nodes' {Nodes::Node#letter #letter} and
|
10
|
+
# {Nodes::Node#children_tree #children_tree} are equal, `false` otherwise.
|
11
11
|
def == other
|
12
12
|
letter == other.letter &&
|
13
13
|
terminal? == other.terminal? &&
|
@@ -5,7 +5,7 @@ module Rambling
|
|
5
5
|
# Provides the compressible behavior for the trie data structure.
|
6
6
|
module Compressible
|
7
7
|
# Indicates if the current {Rambling::Trie::Nodes::Node Node} can be compressed or not.
|
8
|
-
# @return [Boolean]
|
8
|
+
# @return [Boolean] `true` for non-{Nodes::Node#terminal? terminal} nodes with one child, `false` otherwise.
|
9
9
|
def compressible?
|
10
10
|
!(root? || terminal?) && 1 == children_tree.size
|
11
11
|
end
|
@@ -5,11 +5,13 @@ module Rambling
|
|
5
5
|
# Responsible for the compression process of a trie data structure.
|
6
6
|
class Compressor
|
7
7
|
# Compresses a {Nodes::Node Node} from a trie data structure.
|
8
|
-
# @param [Nodes::
|
9
|
-
# @return [Nodes::Compressed] node the compressed version of the node.
|
8
|
+
# @param [Nodes::Node, nil] node the node to compress.
|
9
|
+
# @return [Nodes::Compressed, nil] node the compressed version of the node.
|
10
10
|
def compress node
|
11
|
+
return unless node
|
12
|
+
|
11
13
|
if node.compressible?
|
12
|
-
|
14
|
+
compress_only_child_and_merge node
|
13
15
|
else
|
14
16
|
compress_children_and_copy node
|
15
17
|
end
|
@@ -17,40 +19,39 @@ module Rambling
|
|
17
19
|
|
18
20
|
private
|
19
21
|
|
20
|
-
|
21
|
-
|
22
|
+
# Compresses a {Nodes::Node Node} with an only child from a trie data structure.
|
23
|
+
# By this point we already know the node is not nil and that it has an only child,
|
24
|
+
# so we use the type annotation because compressed_child will always have a value.
|
25
|
+
# @see Rambling::Trie::Compressible#compressible? Compressible#compressible?
|
26
|
+
# @param [Nodes::Node] node the node to compress.
|
27
|
+
# @return [Nodes::Compressed] node the compressed version of the node.
|
28
|
+
def compress_only_child_and_merge node
|
29
|
+
compressed_child = compress(node.first_child) # : Nodes::Compressed
|
30
|
+
merge node, compressed_child
|
22
31
|
end
|
23
32
|
|
24
33
|
def merge node, other
|
25
|
-
return new_compressed_node node.letter, node.parent, node.children_tree, node.terminal? if other.nil?
|
26
|
-
|
27
34
|
letter = node.letter.to_s << other.letter.to_s
|
28
35
|
|
29
|
-
|
36
|
+
compressed = Rambling::Trie::Nodes::Compressed.new letter.to_sym, node.parent, other.children_tree
|
37
|
+
compressed.terminal! if other.terminal?
|
38
|
+
compressed
|
30
39
|
end
|
31
40
|
|
32
41
|
def compress_children_and_copy node
|
33
|
-
|
42
|
+
children_tree = compress_children(node.children_tree)
|
43
|
+
compressed = Rambling::Trie::Nodes::Compressed.new node.letter, node.parent, children_tree
|
44
|
+
compressed.terminal! if node.terminal?
|
45
|
+
compressed
|
34
46
|
end
|
35
47
|
|
36
48
|
def compress_children tree
|
37
49
|
new_tree = {}
|
38
50
|
|
39
|
-
tree.each
|
40
|
-
compressed_child = compress child
|
41
|
-
new_tree[letter] = compressed_child
|
42
|
-
end
|
51
|
+
tree.each { |letter, child| new_tree[letter] = compress child }
|
43
52
|
|
44
53
|
new_tree
|
45
54
|
end
|
46
|
-
|
47
|
-
def new_compressed_node letter, parent, tree, terminal
|
48
|
-
node = Rambling::Trie::Nodes::Compressed.new letter, parent, tree
|
49
|
-
node.terminal! if terminal
|
50
|
-
|
51
|
-
tree.each_value { |child| child.parent = node }
|
52
|
-
node
|
53
|
-
end
|
54
55
|
end
|
55
56
|
end
|
56
57
|
end
|
@@ -4,6 +4,7 @@ module Rambling
|
|
4
4
|
module Trie
|
5
5
|
module Configuration
|
6
6
|
# Provides configurable properties for Rambling::Trie.
|
7
|
+
# :reek:TooManyInstanceVariables { max_instance_variables: 5 }
|
7
8
|
class Properties
|
8
9
|
# The configured {Readers Readers}.
|
9
10
|
# @return [ProviderCollection<Readers::Reader>] the mapping of configured {Readers Readers}.
|
@@ -17,12 +18,12 @@ module Rambling
|
|
17
18
|
# @return [Compressor] the configured compressor.
|
18
19
|
attr_accessor :compressor
|
19
20
|
|
20
|
-
# The configured
|
21
|
-
# @return [Proc<Nodes::Node>] the configured
|
21
|
+
# The configured `root_builder`, which returns a {Nodes::Node Node} when called.
|
22
|
+
# @return [Proc<Nodes::Node>] the configured `root_builder`.
|
22
23
|
attr_accessor :root_builder
|
23
24
|
|
24
|
-
# The configured
|
25
|
-
# @return [String] the configured
|
25
|
+
# The configured `tmp_path`, which will be used for throwaway files.
|
26
|
+
# @return [String] the configured `tmp_path`.
|
26
27
|
attr_accessor :tmp_path
|
27
28
|
|
28
29
|
# Returns a new properties instance.
|
@@ -17,7 +17,7 @@ module Rambling
|
|
17
17
|
# providers.
|
18
18
|
# @param [TProvider] provider the provider to use as default.
|
19
19
|
# @raise [ArgumentError] when the given provider is not in the provider collection.
|
20
|
-
# @note If no providers have been configured,
|
20
|
+
# @note If no providers have been configured, `nil` will be assigned.
|
21
21
|
# @return [TProvider, nil] the default provider to use when a provider cannot be resolved in
|
22
22
|
# {ProviderCollection#resolve #resolve}.
|
23
23
|
attr_reader :default
|
@@ -58,14 +58,19 @@ module Rambling
|
|
58
58
|
# @param [String] filepath the filepath to resolve into a provider.
|
59
59
|
# @return [TProvider, nil] the provider for the given file's extension. {#default} if not found.
|
60
60
|
def resolve filepath
|
61
|
-
|
61
|
+
extension = file_format filepath
|
62
|
+
if providers.key? extension
|
63
|
+
providers[extension]
|
64
|
+
else
|
65
|
+
default
|
66
|
+
end
|
62
67
|
end
|
63
68
|
|
64
69
|
# Resets the provider collection to the initial values.
|
65
70
|
# @return [void]
|
66
71
|
def reset
|
67
72
|
providers.clear
|
68
|
-
configured_providers.each { |
|
73
|
+
configured_providers.each { |extension, provider| self[extension] = provider }
|
69
74
|
self.default = configured_default
|
70
75
|
end
|
71
76
|
|
@@ -98,13 +103,13 @@ module Rambling
|
|
98
103
|
end
|
99
104
|
|
100
105
|
def file_format filepath
|
101
|
-
|
102
|
-
format.slice! 0
|
103
|
-
format.to_sym
|
106
|
+
File.extname(filepath).sub(%r{^\.}, '').to_sym
|
104
107
|
end
|
105
108
|
|
106
109
|
def contains? provider
|
107
|
-
|
110
|
+
return true if provider.nil?
|
111
|
+
|
112
|
+
providers.any? && provider_instances.include?(provider || raise)
|
108
113
|
end
|
109
114
|
|
110
115
|
alias_method :provider_instances, :values
|
@@ -1,8 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
end
|
3
|
+
path = File.join 'rambling', 'trie', 'configuration'
|
4
|
+
%w(properties provider_collection).each { |file| require File.join(path, file) }
|
6
5
|
|
7
6
|
module Rambling
|
8
7
|
module Trie
|
@@ -28,7 +28,7 @@ module Rambling
|
|
28
28
|
# @see Nodes::Raw#add
|
29
29
|
# @see Nodes::Compressed#add
|
30
30
|
def add word
|
31
|
-
root.add
|
31
|
+
root.add reversed_char_symbols word
|
32
32
|
end
|
33
33
|
|
34
34
|
# Adds all provided words to the trie.
|
@@ -62,7 +62,7 @@ module Rambling
|
|
62
62
|
|
63
63
|
# Checks if a path for a word or partial word exists in the trie.
|
64
64
|
# @param [String] word the word or partial word to look for in the trie.
|
65
|
-
# @return [Boolean]
|
65
|
+
# @return [Boolean] `true` if the word or partial word is found, `false` otherwise.
|
66
66
|
# @see Nodes::Node#partial_word?
|
67
67
|
def partial_word? word = ''
|
68
68
|
root.partial_word? word.chars
|
@@ -81,8 +81,8 @@ module Rambling
|
|
81
81
|
|
82
82
|
# Checks if a whole word exists in the trie.
|
83
83
|
# @param [String] word the word to look for in the trie.
|
84
|
-
# @return [Boolean]
|
85
|
-
#
|
84
|
+
# @return [Boolean] `true` only if the word is found and the last character corresponds to a terminal node,
|
85
|
+
# `false` otherwise.
|
86
86
|
# @see Nodes::Node#word?
|
87
87
|
def word? word = ''
|
88
88
|
root.word? word.chars
|
@@ -98,7 +98,7 @@ module Rambling
|
|
98
98
|
|
99
99
|
# Returns all words within a string that match a word contained in the trie.
|
100
100
|
# @param [String] phrase the string to look for matching words in.
|
101
|
-
# @return [
|
101
|
+
# @return [Array<String>] all the words in the given string that match a word in the trie.
|
102
102
|
# @yield [String] each word found in phrase.
|
103
103
|
def words_within phrase
|
104
104
|
words_within_root(phrase).to_a
|
@@ -106,7 +106,7 @@ module Rambling
|
|
106
106
|
|
107
107
|
# Checks if there are any valid words in a given string.
|
108
108
|
# @param [String] phrase the string to look for matching words in.
|
109
|
-
# @return [Boolean]
|
109
|
+
# @return [Boolean] `true` if any word within phrase is contained in the trie, `false` otherwise.
|
110
110
|
# @see Container#words_within
|
111
111
|
def words_within? phrase
|
112
112
|
words_within_root(phrase).any?
|
@@ -114,7 +114,7 @@ module Rambling
|
|
114
114
|
|
115
115
|
# Compares two trie data structures.
|
116
116
|
# @param [Container] other the trie to compare against.
|
117
|
-
# @return [Boolean]
|
117
|
+
# @return [Boolean] `true` if the tries are equal, `false` otherwise.
|
118
118
|
def == other
|
119
119
|
root == other.root
|
120
120
|
end
|
@@ -125,9 +125,7 @@ module Rambling
|
|
125
125
|
def each
|
126
126
|
return enum_for :each unless block_given?
|
127
127
|
|
128
|
-
root.each
|
129
|
-
yield word
|
130
|
-
end
|
128
|
+
root.each { |word| yield word }
|
131
129
|
end
|
132
130
|
|
133
131
|
# @return [String] a string representation of the container.
|
@@ -152,14 +150,14 @@ module Rambling
|
|
152
150
|
|
153
151
|
# Root node's children tree.
|
154
152
|
# @return [Hash<Symbol, Nodes::Node>] the children tree hash contained in the root node, consisting of
|
155
|
-
#
|
153
|
+
# `:letter => node`.
|
156
154
|
# @see Nodes::Node#children_tree
|
157
155
|
def children_tree
|
158
156
|
root.children_tree
|
159
157
|
end
|
160
158
|
|
161
159
|
# Indicates if the root {Nodes::Node Node} can be compressed or not.
|
162
|
-
# @return [Boolean]
|
160
|
+
# @return [Boolean] `true` for non-{Nodes::Node#terminal? terminal} nodes with one child, `false` otherwise.
|
163
161
|
def compressed?
|
164
162
|
root.compressed?
|
165
163
|
end
|
@@ -201,22 +199,21 @@ module Rambling
|
|
201
199
|
return enum_for :words_within_root, phrase unless block_given?
|
202
200
|
|
203
201
|
chars = phrase.chars
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
end
|
202
|
+
size = chars.length
|
203
|
+
# rubocop:disable Style/CommentedKeyword
|
204
|
+
0.upto(size - 1).each do |starting_index|
|
205
|
+
new_phrase = chars.slice starting_index, size # : Array[String]
|
206
|
+
root.match_prefix(new_phrase) { |word| yield word }
|
207
|
+
end # : Enumerator[String, void]
|
208
|
+
# rubocop:enable Style/CommentedKeyword
|
210
209
|
end
|
211
210
|
|
212
211
|
def compress_root
|
213
|
-
compressor.compress root
|
212
|
+
compressor.compress root # : Nodes::Compressed
|
214
213
|
end
|
215
214
|
|
216
|
-
def
|
217
|
-
|
218
|
-
word.reverse.each_char { |c| symbols << c.to_sym }
|
219
|
-
symbols
|
215
|
+
def reversed_char_symbols word
|
216
|
+
word.reverse.chars.map(&:to_sym).to_a
|
220
217
|
end
|
221
218
|
end
|
222
219
|
end
|