rambling-trie 1.0.3 → 2.0.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 +5 -5
- data/Gemfile +6 -4
- data/Guardfile +3 -1
- data/README.md +4 -4
- data/Rakefile +4 -0
- data/lib/rambling-trie.rb +2 -0
- data/lib/rambling/trie.rb +25 -9
- data/lib/rambling/trie/comparable.rb +4 -1
- data/lib/rambling/trie/compressible.rb +6 -4
- data/lib/rambling/trie/compressor.rb +12 -10
- data/lib/rambling/trie/configuration.rb +3 -1
- data/lib/rambling/trie/configuration/properties.rb +15 -8
- data/lib/rambling/trie/configuration/provider_collection.rb +4 -1
- data/lib/rambling/trie/container.rb +7 -40
- data/lib/rambling/trie/enumerable.rb +2 -0
- data/lib/rambling/trie/inspectable.rb +2 -0
- data/lib/rambling/trie/invalid_operation.rb +3 -1
- data/lib/rambling/trie/nodes.rb +3 -1
- data/lib/rambling/trie/nodes/compressed.rb +53 -70
- data/lib/rambling/trie/nodes/missing.rb +2 -0
- data/lib/rambling/trie/nodes/node.rb +38 -6
- data/lib/rambling/trie/nodes/raw.rb +19 -26
- data/lib/rambling/trie/readers.rb +3 -1
- data/lib/rambling/trie/readers/plain_text.rb +2 -0
- data/lib/rambling/trie/serializers.rb +3 -1
- data/lib/rambling/trie/serializers/file.rb +2 -0
- data/lib/rambling/trie/serializers/marshal.rb +12 -2
- data/lib/rambling/trie/serializers/yaml.rb +18 -2
- data/lib/rambling/trie/serializers/zip.rb +6 -0
- data/lib/rambling/trie/stringifyable.rb +7 -1
- data/lib/rambling/trie/version.rb +3 -1
- data/rambling-trie.gemspec +21 -10
- data/spec/integration/rambling/trie_spec.rb +8 -4
- data/spec/lib/rambling/trie/comparable_spec.rb +2 -0
- data/spec/lib/rambling/trie/compressor_spec.rb +35 -33
- data/spec/lib/rambling/trie/configuration/properties_spec.rb +17 -9
- data/spec/lib/rambling/trie/configuration/provider_collection_spec.rb +10 -14
- data/spec/lib/rambling/trie/container_spec.rb +28 -53
- data/spec/lib/rambling/trie/enumerable_spec.rb +2 -0
- data/spec/lib/rambling/trie/inspectable_spec.rb +32 -7
- data/spec/lib/rambling/trie/nodes/compressed_spec.rb +2 -0
- data/spec/lib/rambling/trie/nodes/node_spec.rb +2 -0
- data/spec/lib/rambling/trie/nodes/raw_spec.rb +2 -0
- data/spec/lib/rambling/trie/readers/plain_text_spec.rb +3 -1
- data/spec/lib/rambling/trie/serializers/file_spec.rb +2 -0
- data/spec/lib/rambling/trie/serializers/marshal_spec.rb +2 -0
- data/spec/lib/rambling/trie/serializers/yaml_spec.rb +2 -0
- data/spec/lib/rambling/trie/serializers/zip_spec.rb +6 -4
- data/spec/lib/rambling/trie/stringifyable_spec.rb +7 -3
- data/spec/lib/rambling/trie_spec.rb +16 -9
- data/spec/spec_helper.rb +10 -7
- data/spec/support/config.rb +6 -0
- data/spec/support/helpers/add_word.rb +2 -0
- data/spec/support/helpers/one_line_heredoc.rb +11 -0
- data/spec/support/shared_examples/a_compressible_trie.rb +7 -3
- data/spec/support/shared_examples/a_serializable_trie.rb +2 -0
- data/spec/support/shared_examples/a_serializer.rb +2 -0
- data/spec/support/shared_examples/a_trie_data_structure.rb +2 -0
- data/spec/support/shared_examples/a_trie_node.rb +15 -5
- data/spec/support/shared_examples/a_trie_node_implementation.rb +10 -6
- metadata +17 -15
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: fd802cb55bb14531c22c64b10e3c278ef20bb828b0680e9e6bea6e275ac2be0c
|
4
|
+
data.tar.gz: 0b6b81b55ce916632604bd3b932b7b67f403cf26f4e655c00fc3fb1f9b362bdd
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: cf9c2b2d7d2af2801483b50bc0daec751c7a14b0694b46c769aa06e800c29069574446f434a941a416a90356bd6b10882c21ec94b6be55e807e45b1e0efefb49
|
7
|
+
data.tar.gz: 7072801a3d3d3debbac169dca5ac73f921d2416e664554be77d2dc1d94e4f82b5104752ed90715ed18d4879834ff1af56c1a23f940da3ef64bd63b1079c72753
|
data/Gemfile
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
source 'https://rubygems.org'
|
3
4
|
|
4
5
|
gemspec
|
@@ -6,19 +7,20 @@ gemspec
|
|
6
7
|
gem 'rubyzip'
|
7
8
|
|
8
9
|
group :development do
|
9
|
-
gem 'ruby-prof'
|
10
|
-
gem 'memory_profiler'
|
11
10
|
gem 'benchmark-ips'
|
12
11
|
gem 'flamegraph'
|
13
|
-
gem '
|
12
|
+
gem 'memory_profiler'
|
14
13
|
gem 'pry'
|
14
|
+
gem 'ruby-prof'
|
15
|
+
gem 'stackprof'
|
15
16
|
end
|
16
17
|
|
17
18
|
group :test do
|
18
|
-
gem 'simplecov', require: false
|
19
19
|
gem 'coveralls', '~>0.8.21', require: false
|
20
|
+
gem 'simplecov', require: false
|
20
21
|
end
|
21
22
|
|
22
23
|
group :local do
|
23
24
|
gem 'guard-rspec'
|
25
|
+
gem 'rubocop', require: false
|
24
26
|
end
|
data/Guardfile
CHANGED
@@ -1,8 +1,10 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
# A sample Guardfile
|
2
4
|
# More info at https://github.com/guard/guard#readme
|
3
5
|
|
4
6
|
guard 'rspec', cmd: 'rspec', all_on_start: true, all_after_pass: false do
|
5
7
|
watch(%r{^spec/.+_spec\.rb$})
|
6
8
|
watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
|
7
|
-
watch('spec/spec_helper.rb') {
|
9
|
+
watch('spec/spec_helper.rb') { 'spec' }
|
8
10
|
end
|
data/README.md
CHANGED
@@ -10,7 +10,7 @@ The Rambling Trie is a Ruby implementation of the [trie data structure][trie_wik
|
|
10
10
|
|
11
11
|
You will need:
|
12
12
|
|
13
|
-
* Ruby 2.
|
13
|
+
* Ruby 2.3.0 or up
|
14
14
|
* RubyGems
|
15
15
|
|
16
16
|
See [RVM][rvm], [rbenv][rbenv] or [chruby][chruby] for more information on how to manage Ruby versions.
|
@@ -245,12 +245,12 @@ The Rambling Trie has been tested with the following Ruby versions:
|
|
245
245
|
* 2.5.x
|
246
246
|
* 2.4.x
|
247
247
|
* 2.3.x
|
248
|
-
* 2.2.x
|
249
248
|
|
250
249
|
**No longer supported**:
|
251
250
|
|
252
|
-
* 2.
|
253
|
-
* 2.
|
251
|
+
* 2.2.x
|
252
|
+
* 2.1.x
|
253
|
+
* 2.0.x
|
254
254
|
* 1.9.x
|
255
255
|
* 1.8.x
|
256
256
|
|
data/Rakefile
CHANGED
@@ -1,5 +1,8 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'bundler/gem_tasks'
|
2
4
|
require 'rspec/core/rake_task'
|
5
|
+
require 'rubocop/rake_task'
|
3
6
|
|
4
7
|
require 'rambling-trie'
|
5
8
|
require_relative 'tasks/performance'
|
@@ -7,5 +10,6 @@ require_relative 'tasks/serialization'
|
|
7
10
|
require_relative 'tasks/ips'
|
8
11
|
|
9
12
|
RSpec::Core::RakeTask.new :spec
|
13
|
+
RuboCop::RakeTask.new :rubocop
|
10
14
|
|
11
15
|
task default: :spec
|
data/lib/rambling-trie.rb
CHANGED
data/lib/rambling/trie.rb
CHANGED
@@ -1,8 +1,10 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
%w(
|
2
4
|
comparable compressible compressor configuration container enumerable
|
3
5
|
inspectable invalid_operation readers serializers stringifyable nodes
|
4
6
|
version
|
5
|
-
|
7
|
+
).each do |file|
|
6
8
|
require File.join('rambling', 'trie', file)
|
7
9
|
end
|
8
10
|
|
@@ -18,7 +20,9 @@ module Rambling
|
|
18
20
|
# @yield [Container] the trie just created.
|
19
21
|
# @see Rambling::Trie::Readers Readers.
|
20
22
|
def create filepath = nil, reader = nil
|
21
|
-
|
23
|
+
root = root_builder.call
|
24
|
+
|
25
|
+
Rambling::Trie::Container.new root, compressor do |container|
|
22
26
|
if filepath
|
23
27
|
reader ||= readers.resolve filepath
|
24
28
|
reader.each_word filepath do |word|
|
@@ -30,13 +34,20 @@ module Rambling
|
|
30
34
|
end
|
31
35
|
end
|
32
36
|
|
33
|
-
# Loads an existing trie from disk into memory.
|
37
|
+
# Loads an existing trie from disk into memory. By default, it will
|
38
|
+
# deduce the correct way to deserialize based on the file extension.
|
39
|
+
# Available formats are `yml`, `marshal`, and `zip` versions of all the
|
40
|
+
# previous formats. You can also define your own.
|
34
41
|
# @param [String] filepath the file to load the words from.
|
35
|
-
# @param [Serializer, nil] serializer the object responsible of loading
|
36
|
-
# from disk
|
42
|
+
# @param [Serializer, nil] serializer the object responsible of loading
|
43
|
+
# the trie from disk
|
37
44
|
# @return [Container] the trie just loaded.
|
38
45
|
# @yield [Container] the trie just loaded.
|
39
46
|
# @see Rambling::Trie::Serializers Serializers.
|
47
|
+
# @note Use of
|
48
|
+
# {https://ruby-doc.org/core-2.5.0/Marshal.html#method-c-load
|
49
|
+
# Marshal.load} is generally discouraged. Only use the `.marshal`
|
50
|
+
# format with trusted input.
|
40
51
|
def load filepath, serializer = nil
|
41
52
|
serializer ||= serializers.resolve filepath
|
42
53
|
root = serializer.load filepath
|
@@ -45,7 +56,10 @@ module Rambling
|
|
45
56
|
end
|
46
57
|
end
|
47
58
|
|
48
|
-
# Dumps an existing trie from memory into disk.
|
59
|
+
# Dumps an existing trie from memory into disk. By default, it will
|
60
|
+
# deduce the correct way to serialize based on the file extension.
|
61
|
+
# Available formats are `yml`, `marshal`, and `zip` versions of all the
|
62
|
+
# previous formats. You can also define your own.
|
49
63
|
# @param [Container] trie the trie to dump into disk.
|
50
64
|
# @param [String] filepath the file to dump to serialized trie into.
|
51
65
|
# @param [Serializer, nil] serializer the object responsible of
|
@@ -57,8 +71,10 @@ module Rambling
|
|
57
71
|
end
|
58
72
|
|
59
73
|
# Provides configuration properties for the Rambling::Trie gem.
|
60
|
-
# @return [Configuration::Properties] the configured properties of the
|
61
|
-
#
|
74
|
+
# @return [Configuration::Properties] the configured properties of the
|
75
|
+
# gem.
|
76
|
+
# @yield [Configuration::Properties] the configured properties of the
|
77
|
+
# gem.
|
62
78
|
def config
|
63
79
|
yield properties if block_given?
|
64
80
|
properties
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Rambling
|
2
4
|
module Trie
|
3
5
|
# Provides the comparable behavior for the trie data structure.
|
@@ -5,7 +7,8 @@ module Rambling
|
|
5
7
|
# Compares two nodes.
|
6
8
|
# @param [Nodes::Node] other the node to compare against.
|
7
9
|
# @return [Boolean] `true` if the nodes' {Nodes::Node#letter #letter} and
|
8
|
-
# {Nodes::Node#children_tree #children_tree} are equal, `false`
|
10
|
+
# {Nodes::Node#children_tree #children_tree} are equal, `false`
|
11
|
+
# otherwise.
|
9
12
|
def == other
|
10
13
|
letter == other.letter &&
|
11
14
|
terminal? == other.terminal? &&
|
@@ -1,11 +1,13 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Rambling
|
2
4
|
module Trie
|
3
5
|
# Provides the compressible behavior for the trie data structure.
|
4
6
|
module Compressible
|
5
|
-
# Indicates if the current {Rambling::Trie::Nodes::Node Node} can be
|
6
|
-
# or not.
|
7
|
-
# @return [Boolean] `true` for non-{Nodes::Node#terminal? terminal} nodes
|
8
|
-
# one child, `false` otherwise.
|
7
|
+
# Indicates if the current {Rambling::Trie::Nodes::Node Node} can be
|
8
|
+
# compressed or not.
|
9
|
+
# @return [Boolean] `true` for non-{Nodes::Node#terminal? terminal} nodes
|
10
|
+
# with one child, `false` otherwise.
|
9
11
|
def compressible?
|
10
12
|
!(root? || terminal?) && children_tree.size == 1
|
11
13
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Rambling
|
2
4
|
module Trie
|
3
5
|
# Responsible for the compression process of a trie data structure.
|
@@ -26,7 +28,7 @@ module Rambling
|
|
26
28
|
letter.to_sym,
|
27
29
|
node.parent,
|
28
30
|
other.children_tree,
|
29
|
-
other.terminal
|
31
|
+
other.terminal?,
|
30
32
|
)
|
31
33
|
end
|
32
34
|
|
@@ -35,26 +37,26 @@ module Rambling
|
|
35
37
|
node.letter,
|
36
38
|
node.parent,
|
37
39
|
compress_children(node.children_tree),
|
38
|
-
node.terminal
|
40
|
+
node.terminal?,
|
39
41
|
)
|
40
42
|
end
|
41
43
|
|
42
|
-
def compress_children
|
43
|
-
|
44
|
+
def compress_children tree
|
45
|
+
new_tree = {}
|
44
46
|
|
45
|
-
|
47
|
+
tree.each do |letter, child|
|
46
48
|
compressed_child = compress child
|
47
|
-
|
49
|
+
new_tree[letter] = compressed_child
|
48
50
|
end
|
49
51
|
|
50
|
-
|
52
|
+
new_tree
|
51
53
|
end
|
52
54
|
|
53
|
-
def new_compressed_node letter, parent,
|
54
|
-
node = Rambling::Trie::Nodes::Compressed.new letter, parent,
|
55
|
+
def new_compressed_node letter, parent, tree, terminal
|
56
|
+
node = Rambling::Trie::Nodes::Compressed.new letter, parent, tree
|
55
57
|
node.terminal! if terminal
|
56
58
|
|
57
|
-
|
59
|
+
tree.each_value { |child| child.parent = node }
|
58
60
|
node
|
59
61
|
end
|
60
62
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Rambling
|
2
4
|
module Trie
|
3
5
|
module Configuration
|
@@ -17,8 +19,8 @@ module Rambling
|
|
17
19
|
# @return [Compressor] the configured compressor.
|
18
20
|
attr_accessor :compressor
|
19
21
|
|
20
|
-
# The configured root_builder, which should return a {Nodes::Node Node}
|
21
|
-
# called.
|
22
|
+
# The configured root_builder, which should return a {Nodes::Node Node}
|
23
|
+
# when called.
|
22
24
|
# @return [Proc<Nodes::Node>] the configured root_builder.
|
23
25
|
attr_accessor :root_builder
|
24
26
|
|
@@ -36,9 +38,9 @@ module Rambling
|
|
36
38
|
reset_readers
|
37
39
|
reset_serializers
|
38
40
|
|
39
|
-
|
40
|
-
|
41
|
-
|
41
|
+
@compressor = Rambling::Trie::Compressor.new
|
42
|
+
@root_builder = -> { Rambling::Trie::Nodes::Raw.new }
|
43
|
+
@tmp_path = '/tmp'
|
42
44
|
end
|
43
45
|
|
44
46
|
private
|
@@ -48,7 +50,10 @@ module Rambling
|
|
48
50
|
def reset_readers
|
49
51
|
plain_text_reader = Rambling::Trie::Readers::PlainText.new
|
50
52
|
|
51
|
-
|
53
|
+
@readers = Rambling::Trie::Configuration::ProviderCollection.new(
|
54
|
+
:reader,
|
55
|
+
txt: plain_text_reader,
|
56
|
+
)
|
52
57
|
end
|
53
58
|
|
54
59
|
def reset_serializers
|
@@ -56,11 +61,13 @@ module Rambling
|
|
56
61
|
yaml_serializer = Rambling::Trie::Serializers::Yaml.new
|
57
62
|
zip_serializer = Rambling::Trie::Serializers::Zip.new self
|
58
63
|
|
59
|
-
|
64
|
+
@serializers = Rambling::Trie::Configuration::ProviderCollection.new(
|
65
|
+
:serializer,
|
60
66
|
marshal: marshal_serializer,
|
61
67
|
yml: yaml_serializer,
|
62
68
|
yaml: yaml_serializer,
|
63
|
-
zip: zip_serializer
|
69
|
+
zip: zip_serializer,
|
70
|
+
)
|
64
71
|
end
|
65
72
|
end
|
66
73
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Rambling
|
2
4
|
module Trie
|
3
5
|
module Configuration
|
@@ -44,7 +46,8 @@ module Rambling
|
|
44
46
|
|
45
47
|
def default= provider
|
46
48
|
unless contains? provider
|
47
|
-
raise ArgumentError,
|
49
|
+
raise ArgumentError,
|
50
|
+
"default #{name} should be part of configured #{name}s"
|
48
51
|
end
|
49
52
|
|
50
53
|
@default = provider
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Rambling
|
2
4
|
module Trie
|
3
5
|
# Wrapper on top of trie data structure.
|
@@ -175,9 +177,9 @@ module Rambling
|
|
175
177
|
# Check if a letter is part of the root {Nodes::Node}'s children tree.
|
176
178
|
# @param [Symbol] letter the letter to search for in the root node.
|
177
179
|
# @return [Boolean] whether the letter is contained or not.
|
178
|
-
# @see Nodes::Node#
|
179
|
-
def
|
180
|
-
root.
|
180
|
+
# @see Nodes::Node#key?
|
181
|
+
def key? letter
|
182
|
+
root.key? letter
|
181
183
|
end
|
182
184
|
|
183
185
|
# Size of the Root {Nodes::Node Node}'s children tree.
|
@@ -186,47 +188,12 @@ module Rambling
|
|
186
188
|
root.size
|
187
189
|
end
|
188
190
|
|
189
|
-
# String representation of the current node, if it is a terminal node.
|
190
|
-
# @return [String] the string representation of the current node.
|
191
|
-
# @raise [InvalidOperation] if node is not terminal or is root.
|
192
|
-
# @deprecated This will always raise an {InvalidOperation} exception.
|
193
|
-
def as_word
|
194
|
-
warn '[DEPRECATION WARNING] `#as_word` is deprecated. Please use `#root#as_word` instead.'
|
195
|
-
root.as_word
|
196
|
-
end
|
197
|
-
|
198
|
-
# Root {Nodes::Node Node}'s letter.
|
199
|
-
# @return [Symbol] the root node's letter
|
200
|
-
# @see Nodes::Node#letter
|
201
|
-
# @deprecated This will always return `nil`.
|
202
|
-
def letter
|
203
|
-
warn '[DEPRECATION WARNING] `#letter` is deprecated. Please use `#root#letter` instead.'
|
204
|
-
root.letter
|
205
|
-
end
|
206
|
-
|
207
|
-
# Root {Nodes::Node Node}'s parent.
|
208
|
-
# @return [Symbol] the root node's parent
|
209
|
-
# @see Nodes::Node#parent
|
210
|
-
# @deprecated This will always return `nil`.
|
211
|
-
def parent
|
212
|
-
warn '[DEPRECATION WARNING] `#parent` is deprecated. Please use `#root#parent` instead.'
|
213
|
-
root.parent
|
214
|
-
end
|
215
|
-
|
216
|
-
# String representation of root {Nodes::Node Node}.
|
217
|
-
# @return [String] the root node's string representation.
|
218
|
-
# @see Stringifyable#to_s
|
219
|
-
# @deprecated This will always return an empty string (`''`).
|
220
|
-
def to_s
|
221
|
-
warn '[DEPRECATION WARNING] `#to_s` is deprecated. Please use `#root#to_s` instead.'
|
222
|
-
root.to_s
|
223
|
-
end
|
224
|
-
|
225
191
|
alias_method :include?, :word?
|
226
192
|
alias_method :match?, :partial_word?
|
227
193
|
alias_method :words, :scan
|
228
194
|
alias_method :<<, :add
|
229
|
-
alias_method :
|
195
|
+
alias_method :has_key?, :key?
|
196
|
+
alias_method :has_letter?, :key?
|
230
197
|
|
231
198
|
private
|
232
199
|
|
@@ -1,8 +1,10 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Rambling
|
2
4
|
module Trie
|
3
5
|
# Raised when trying to execute an invalid operation on a trie data
|
4
6
|
# structure.
|
5
|
-
class InvalidOperation <
|
7
|
+
class InvalidOperation < RuntimeError
|
6
8
|
# Creates a new {InvalidOperation InvalidOperation} exception.
|
7
9
|
# @param [String, nil] message the exception message.
|
8
10
|
def initialize message = nil
|
data/lib/rambling/trie/nodes.rb
CHANGED
@@ -1,30 +1,18 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Rambling
|
2
4
|
module Trie
|
3
5
|
module Nodes
|
4
|
-
|
6
|
+
# A representation of a node in an compressed trie data structure.
|
5
7
|
class Compressed < Rambling::Trie::Nodes::Node
|
6
8
|
# Always raises {Rambling::Trie::InvalidOperation InvalidOperation} when
|
7
9
|
# trying to add a word to the current compressed trie node
|
8
|
-
# @param [String]
|
10
|
+
# @param [String] _ the word to add to the trie.
|
9
11
|
# @raise [InvalidOperation] if the trie is already compressed.
|
10
12
|
# @return [nil] this never returns as it always raises an exception.
|
11
|
-
def add
|
12
|
-
raise Rambling::Trie::InvalidOperation,
|
13
|
-
|
14
|
-
|
15
|
-
# Checks if a path for set a of characters exists in the trie.
|
16
|
-
# @param [Array<String>] chars the characters to look for in the trie.
|
17
|
-
# @return [Boolean] `true` if the characters are found, `false` otherwise.
|
18
|
-
def partial_word? chars
|
19
|
-
chars.empty? || has_partial_word?(chars)
|
20
|
-
end
|
21
|
-
|
22
|
-
# Checks if a path for set of characters represents a word in the trie.
|
23
|
-
# @param [Array<String>] chars the characters to look for in the trie.
|
24
|
-
# @return [Boolean] `true` if the characters are found and form a word,
|
25
|
-
# `false` otherwise.
|
26
|
-
def word? chars
|
27
|
-
chars.empty? ? terminal? : has_word?(chars)
|
13
|
+
def add _
|
14
|
+
raise Rambling::Trie::InvalidOperation,
|
15
|
+
'Cannot add word to compressed trie'
|
28
16
|
end
|
29
17
|
|
30
18
|
# Always return `true` for a compressed node.
|
@@ -35,79 +23,74 @@ module Rambling
|
|
35
23
|
|
36
24
|
private
|
37
25
|
|
38
|
-
def
|
39
|
-
|
26
|
+
def partial_word_chars? chars
|
27
|
+
child = children_tree[chars.first.to_sym]
|
28
|
+
return false unless child
|
29
|
+
|
30
|
+
child_letter = child.letter.to_s
|
31
|
+
|
32
|
+
if chars.size >= child_letter.size
|
33
|
+
letter = chars.slice!(0, child_letter.size).join
|
34
|
+
return child.partial_word? chars if child_letter == letter
|
35
|
+
end
|
36
|
+
|
37
|
+
letter = chars.join
|
38
|
+
child_letter = child_letter.slice 0, letter.size
|
39
|
+
child_letter == letter
|
40
40
|
end
|
41
41
|
|
42
|
-
def
|
43
|
-
|
42
|
+
def word_chars? chars
|
43
|
+
letter = chars.slice! 0
|
44
|
+
letter_sym = letter.to_sym
|
45
|
+
|
46
|
+
child = children_tree[letter_sym]
|
47
|
+
return false unless child
|
48
|
+
|
49
|
+
loop do
|
50
|
+
return child.word? chars if letter_sym == child.letter
|
44
51
|
|
45
|
-
|
46
|
-
if current_key
|
47
|
-
current_key << chars.slice!(0)
|
48
|
-
else
|
49
|
-
current_key = chars.slice!(0)
|
50
|
-
end
|
52
|
+
break if chars.empty?
|
51
53
|
|
52
|
-
|
53
|
-
|
54
|
+
letter << chars.slice!(0)
|
55
|
+
letter_sym = letter.to_sym
|
54
56
|
end
|
55
57
|
|
56
58
|
false
|
57
59
|
end
|
58
60
|
|
59
61
|
def closest_node chars
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
def children_match_prefix chars
|
64
|
-
return enum_for :children_match_prefix, chars unless block_given?
|
65
|
-
|
66
|
-
current_key = nil
|
62
|
+
child = children_tree[chars.first.to_sym]
|
63
|
+
return missing unless child
|
67
64
|
|
68
|
-
|
69
|
-
if current_key
|
70
|
-
current_key << chars.slice!(0)
|
71
|
-
else
|
72
|
-
current_key = chars.slice!(0)
|
73
|
-
end
|
65
|
+
child_letter = child.letter.to_s
|
74
66
|
|
75
|
-
|
67
|
+
if chars.size >= child_letter.size
|
68
|
+
letter = chars.slice!(0, child_letter.size).join
|
69
|
+
return child.scan chars if child_letter == letter
|
70
|
+
end
|
76
71
|
|
77
|
-
|
72
|
+
letter = chars.join
|
73
|
+
child_letter = child_letter.slice 0, letter.size
|
78
74
|
|
79
|
-
|
80
|
-
yield word
|
81
|
-
end
|
82
|
-
end
|
75
|
+
child_letter == letter ? child : missing
|
83
76
|
end
|
84
77
|
|
85
|
-
def
|
86
|
-
|
87
|
-
current_key = current_key chars.slice!(0)
|
78
|
+
def children_match_prefix chars
|
79
|
+
return enum_for :children_match_prefix, chars unless block_given?
|
88
80
|
|
89
|
-
|
90
|
-
current_length += 1
|
81
|
+
return if chars.empty?
|
91
82
|
|
92
|
-
|
93
|
-
|
94
|
-
end
|
95
|
-
end while current_key && current_key[current_length] == chars.slice!(0)
|
96
|
-
end
|
83
|
+
child = children_tree[chars.first.to_sym]
|
84
|
+
return unless child
|
97
85
|
|
98
|
-
|
99
|
-
|
86
|
+
child_letter = child.letter.to_s
|
87
|
+
letter = chars.slice!(0, child_letter.size).join
|
100
88
|
|
101
|
-
|
102
|
-
letters_string = letters.to_s
|
89
|
+
return unless child_letter == letter
|
103
90
|
|
104
|
-
|
105
|
-
|
106
|
-
break
|
107
|
-
end
|
91
|
+
child.match_prefix chars do |word|
|
92
|
+
yield word
|
108
93
|
end
|
109
|
-
|
110
|
-
current_key
|
111
94
|
end
|
112
95
|
end
|
113
96
|
end
|