rambling-trie 2.5.0 → 2.5.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|