rambling-trie 0.8.1 → 0.9.0

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