rambling-trie 0.3.0 → 0.3.2

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.
@@ -1,4 +1,7 @@
1
1
  module Rambling
2
2
  class InvalidTrieOperation < Exception
3
+ def initialize(message = nil)
4
+ super
5
+ end
3
6
  end
4
7
  end
data/lib/rambling-trie.rb CHANGED
@@ -1,6 +1,7 @@
1
1
  require File.join(File.dirname(__FILE__), 'invalid_trie_operation.rb')
2
2
  require File.join(File.dirname(__FILE__), 'children_hash_deferer.rb')
3
3
  require File.join(File.dirname(__FILE__), 'trie_compressor.rb')
4
+ require File.join(File.dirname(__FILE__), 'trie_branches.rb')
4
5
  require File.join(File.dirname(__FILE__), 'trie_node.rb')
5
6
  require File.join(File.dirname(__FILE__), 'trie.rb')
6
7
 
data/lib/trie.rb CHANGED
@@ -4,16 +4,29 @@ module Rambling
4
4
  super(nil)
5
5
 
6
6
  @filename = filename
7
+ @is_compressed = false
7
8
  add_all_nodes if filename
8
9
  end
9
10
 
10
11
  def compress!
11
- @is_compressed = true
12
- super
12
+ unless compressed?
13
+ compress_own_tree!
14
+ @is_compressed = true
15
+ end
16
+
17
+ self
13
18
  end
14
19
 
15
20
  def compressed?
16
- @is_compressed
21
+ @is_compressed = @is_compressed.nil? ? false : @is_compressed
22
+ end
23
+
24
+ def has_branch_for?(word = '')
25
+ compressed? ? has_compressed_branch_for?(word) : has_uncompressed_branch_for?(word)
26
+ end
27
+
28
+ def is_word?(word = '')
29
+ compressed? ? is_compressed_word?(word) : is_uncompressed_word?(word)
17
30
  end
18
31
 
19
32
  private
@@ -0,0 +1,68 @@
1
+ module Rambling
2
+ module TrieBranches
3
+ def add_branch_from(word)
4
+ raise InvalidTrieOperation.new('Cannot add branch to compressed trie') if compressed?
5
+ if word.empty?
6
+ @is_terminal = true
7
+ return
8
+ end
9
+
10
+ first_letter = word.slice(0).to_sym
11
+
12
+ if @children.has_key?(first_letter)
13
+ word.slice!(0)
14
+ @children[first_letter].add_branch_from(word)
15
+ else
16
+ @children[first_letter] = TrieNode.new(word, self)
17
+ end
18
+ end
19
+
20
+ protected
21
+
22
+ def has_uncompressed_branch_for?(word = '')
23
+ word.empty? or fulfills_uncompressed_condition?(:has_uncompressed_branch_for?, word)
24
+ end
25
+
26
+ def fulfills_uncompressed_condition?(method, word)
27
+ clone = word.clone
28
+ first_letter = clone.slice!(0)
29
+ unless first_letter.nil?
30
+ first_letter_sym = first_letter.to_sym
31
+ return @children[first_letter_sym].send(method, clone) if @children.has_key?(first_letter_sym)
32
+ end
33
+
34
+ false
35
+ end
36
+
37
+ def has_compressed_branch_for?(word = '')
38
+ return true if word.empty?
39
+
40
+ keys = @children.keys.map { |x| x.to_s }
41
+ return true if keys.include?(word)
42
+
43
+ partial_key = keys.select { |x| x.start_with?(word) }.first
44
+ return true unless partial_key.nil?
45
+
46
+ key = keys.select { |x| word.start_with?(x) }.first
47
+ return @children[key.to_sym].has_compressed_branch_for?(word.slice(key.length..word.length)) unless key.nil?
48
+
49
+ false
50
+ end
51
+
52
+ def is_uncompressed_word?(word = '')
53
+ (word.empty? and terminal?) or fulfills_uncompressed_condition?(:is_uncompressed_word?, word)
54
+ end
55
+
56
+ def is_compressed_word?(word = '')
57
+ return true if word.empty? and terminal?
58
+
59
+ length = word.length
60
+ for index in (0...length)
61
+ key = word.slice(0..index).to_sym
62
+ return @children[key].is_compressed_word?(word.slice((index + 1)...length)) if @children.has_key?(key)
63
+ end
64
+
65
+ false
66
+ end
67
+ end
68
+ end
@@ -1,12 +1,22 @@
1
1
  module Rambling
2
2
  module TrieCompressor
3
- def compress!
4
- if @children.size == 1 and not terminal?
3
+ def compressed?
4
+ if instance_variable_defined?(:@is_compressed)
5
+ @is_compressed
6
+ else
7
+ @parent.nil? ? false : @parent.compressed?
8
+ end
9
+ end
10
+
11
+ protected
12
+
13
+ def compress_own_tree!
14
+ if @children.size == 1 and not terminal? and not @letter.nil?
5
15
  merge_with!(@children.values.first)
6
- compress!
16
+ compress_own_tree!
7
17
  end
8
18
 
9
- @children.values.each { |node| node.compress! }
19
+ @children.values.each { |node| node.compress_own_tree! }
10
20
 
11
21
  self
12
22
  end
data/lib/trie_node.rb CHANGED
@@ -2,6 +2,7 @@ module Rambling
2
2
  class TrieNode
3
3
  include ChildrenHashDeferer
4
4
  include TrieCompressor
5
+ include TrieBranches
5
6
 
6
7
  attr_reader :letter, :children, :parent
7
8
 
@@ -27,32 +28,11 @@ module Rambling
27
28
  @is_terminal
28
29
  end
29
30
 
30
- def add_branch_from(word)
31
- return if word.empty?
32
-
33
- first_letter = word.slice(0).to_sym
34
-
35
- if @children.has_key?(first_letter)
36
- word.slice!(0)
37
- @children[first_letter].add_branch_from(word)
38
- else
39
- @children[first_letter] = TrieNode.new(word, self)
40
- end
41
- end
42
-
43
- def has_branch_for?(word)
44
- word.empty? or branch_exists_and(word, :has_branch_for?)
45
- end
46
-
47
31
  def as_word
48
32
  raise InvalidTrieOperation.new() unless @letter.nil? or terminal?
49
33
  get_letter_string
50
34
  end
51
35
 
52
- def is_word?(word = '')
53
- (word.empty? and terminal?) or branch_exists_and(word, :is_word?)
54
- end
55
-
56
36
  protected
57
37
  def get_letter_string
58
38
  (@parent.nil? ? '' : @parent.get_letter_string) + @letter.to_s
@@ -61,16 +41,5 @@ module Rambling
61
41
  def parent=(parent)
62
42
  @parent = parent
63
43
  end
64
-
65
- private
66
-
67
- def branch_exists_and(word, method)
68
- first_letter = word.slice!(0)
69
-
70
- return false if first_letter.nil?
71
-
72
- first_letter_key = first_letter.to_sym
73
- @children.has_key?(first_letter_key) ? @children[first_letter_key].send(method, word) : false
74
- end
75
44
  end
76
45
  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.3.0
4
+ version: 0.3.2
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-02-09 00:00:00.000000000 Z
12
+ date: 2012-02-11 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rspec
16
- requirement: &15464280 !ruby/object:Gem::Requirement
16
+ requirement: &14554820 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,7 +21,18 @@ dependencies:
21
21
  version: 2.0.0
22
22
  type: :development
23
23
  prerelease: false
24
- version_requirements: *15464280
24
+ version_requirements: *14554820
25
+ - !ruby/object:Gem::Dependency
26
+ name: rake
27
+ requirement: &14554220 !ruby/object:Gem::Requirement
28
+ none: false
29
+ requirements:
30
+ - - ! '>='
31
+ - !ruby/object:Gem::Version
32
+ version: 0.9.2
33
+ type: :development
34
+ prerelease: false
35
+ version_requirements: *14554220
25
36
  description: The Rambling Trie is a custom implementation of the Trie data structure
26
37
  with Ruby, which includes compression abilities and is designed to be very fast
27
38
  to traverse.
@@ -34,6 +45,7 @@ files:
34
45
  - ./lib/invalid_trie_operation.rb
35
46
  - ./lib/rambling-trie.rb
36
47
  - ./lib/trie.rb
48
+ - ./lib/trie_branches.rb
37
49
  - ./lib/trie_compressor.rb
38
50
  - ./lib/trie_node.rb
39
51
  - LICENSE
@@ -58,7 +70,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
58
70
  version: '0'
59
71
  requirements: []
60
72
  rubyforge_project:
61
- rubygems_version: 1.8.10
73
+ rubygems_version: 1.8.15
62
74
  signing_key:
63
75
  specification_version: 3
64
76
  summary: A custom implementation of the trie data structure.