rambling-trie 0.3.0 → 0.3.2

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