rambling-trie 0.8.1 → 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (35) hide show
  1. checksums.yaml +4 -4
  2. data/Rakefile +1 -1
  3. data/lib/rambling/trie.rb +21 -9
  4. data/lib/rambling/trie/compressed_node.rb +112 -0
  5. data/lib/rambling/trie/compression.rb +13 -0
  6. data/lib/rambling/trie/compressor.rb +30 -31
  7. data/lib/rambling/trie/{root.rb → container.rb} +41 -38
  8. data/lib/rambling/trie/enumerable.rb +11 -7
  9. data/lib/rambling/trie/missing_node.rb +1 -1
  10. data/lib/rambling/trie/node.rb +25 -22
  11. data/lib/rambling/trie/plain_text_reader.rb +1 -1
  12. data/lib/rambling/trie/raw_node.rb +90 -0
  13. data/lib/rambling/trie/tasks/helpers/path.rb +13 -0
  14. data/lib/rambling/trie/tasks/helpers/time.rb +7 -0
  15. data/lib/rambling/trie/tasks/performance.rb +10 -91
  16. data/lib/rambling/trie/tasks/performance/all.rb +4 -0
  17. data/lib/rambling/trie/tasks/performance/benchmark.rb +172 -0
  18. data/lib/rambling/trie/tasks/performance/directory.rb +11 -0
  19. data/lib/rambling/trie/tasks/performance/profile/call_tree.rb +132 -0
  20. data/lib/rambling/trie/tasks/performance/profile/memory.rb +116 -0
  21. data/lib/rambling/trie/version.rb +1 -1
  22. data/rambling-trie.gemspec +6 -4
  23. data/spec/integration/rambling/trie_spec.rb +63 -9
  24. data/spec/lib/rambling/trie/compressed_node_spec.rb +35 -0
  25. data/spec/lib/rambling/trie/compressor_spec.rb +31 -0
  26. data/spec/lib/rambling/trie/container_spec.rb +470 -0
  27. data/spec/lib/rambling/trie/enumerable_spec.rb +2 -2
  28. data/spec/lib/rambling/trie/inspector_spec.rb +21 -14
  29. data/spec/lib/rambling/trie/node_spec.rb +72 -209
  30. data/spec/lib/rambling/trie/raw_node_spec.rb +377 -0
  31. data/spec/lib/rambling/trie_spec.rb +46 -25
  32. metadata +57 -16
  33. data/lib/rambling/trie/branches.rb +0 -149
  34. data/spec/lib/rambling/trie/branches_spec.rb +0 -52
  35. data/spec/lib/rambling/trie/root_spec.rb +0 -376
@@ -1,40 +1,61 @@
1
1
  require 'spec_helper'
2
2
 
3
- module Rambling
4
- describe Trie do
5
- describe '.create' do
6
- let(:root) { double :root }
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
- before { allow(Trie::Root).to receive(:new).and_yield(root).and_return root }
13
+ it 'returns a new instance of the trie container' do
14
+ expect(Rambling::Trie.create).to eq container
15
+ end
9
16
 
10
- it 'returns a new instance of the trie root node' do
11
- expect(Trie.create).to eq root
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
- context 'with a block' do
15
- it 'yields the instantiated root' do
16
- yielded_trie = nil
17
- Trie.create { |trie| yielded_trie = trie }
18
- expect(yielded_trie).to eq root
19
- end
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
- context 'with a filepath' do
23
- let(:filepath) { 'test_words.txt' }
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
- before do
28
- receive_and_yield = receive(:each_word)
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
- it 'loads every word' do
34
- words.each { |word| expect(root).to receive(:<<).with(word) }
46
+ context 'without any reader' do
47
+ let(:filepath) { 'test_words.txt' }
48
+ let(:reader) { double :reader, each_word: nil }
35
49
 
36
- Trie.create filepath, reader
37
- end
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.8.1
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-20 00:00:00.000000000 Z
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.4'
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.4'
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: '10.5'
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: '10.5'
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.15.2
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.15.2
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.8.7
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.8.7
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/branches.rb
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/root.rb
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/branches_spec.rb
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/root_spec.rb
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/branches_spec.rb
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/root_spec.rb
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