stringtree 0.1.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.
- data/.gitignore +7 -0
- data/.rspec +1 -0
- data/.travis.yml +2 -0
- data/CODE_OF_CONDUCT.md +13 -0
- data/Gemfile +3 -0
- data/Gemfile.lock +78 -0
- data/LICENSE.txt +21 -0
- data/README.md +95 -0
- data/Rakefile +13 -0
- data/examples/demo.rb +82 -0
- data/examples/dictionary.txt +61217 -0
- data/examples/hamlet.txt +5590 -0
- data/examples/warandpeace.txt +64950 -0
- data/hamlet.tokens.txt +31262 -0
- data/lib/stringtree/item.rb +28 -0
- data/lib/stringtree/node.rb +216 -0
- data/lib/stringtree/tree.rb +98 -0
- data/lib/stringtree/version.rb +5 -0
- data/lib/stringtree.rb +6 -0
- data/spec/item_spec.rb +32 -0
- data/spec/node_spec.rb +187 -0
- data/spec/spec_helper.rb +19 -0
- data/spec/tree_spec.rb +266 -0
- data/stringtree.gemspec +26 -0
- data/warandpeace.tokens.txt +572121 -0
- metadata +220 -0
@@ -0,0 +1,28 @@
|
|
1
|
+
module StringTree
|
2
|
+
# Represents an individual tokenized item in a dataset, i.e. A match, its offset and its terminator node
|
3
|
+
class Item
|
4
|
+
# The offset of the Item in the dataset, in chars
|
5
|
+
attr_accessor :offset
|
6
|
+
# The match itself
|
7
|
+
attr_accessor :match
|
8
|
+
# The terminating node of the match.
|
9
|
+
attr_accessor :node
|
10
|
+
|
11
|
+
# Create a new Item with the specifid offset,match and optionally, node.
|
12
|
+
def initialize(offset, match, node = nil)
|
13
|
+
@offset = offset
|
14
|
+
@match = match
|
15
|
+
@node = node
|
16
|
+
end
|
17
|
+
|
18
|
+
# Returns true if this is a match.
|
19
|
+
def match?
|
20
|
+
@match
|
21
|
+
end
|
22
|
+
|
23
|
+
# Returns the value of the match if not nil
|
24
|
+
def value
|
25
|
+
@node.value unless @node.nil?
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,216 @@
|
|
1
|
+
module StringTree
|
2
|
+
# Node represents a node in a StringTree::Tree.
|
3
|
+
#
|
4
|
+
# This is essentially a binary tree node with additional up and down pointers.
|
5
|
+
class Node
|
6
|
+
# The char Character value of this node
|
7
|
+
attr_accessor :char
|
8
|
+
# The next left node to this node, or nil
|
9
|
+
attr_accessor :left
|
10
|
+
# The next right node to this node, or nil
|
11
|
+
attr_accessor :right
|
12
|
+
# The child (down) node of this node, or nil
|
13
|
+
attr_accessor :down
|
14
|
+
# The parent (up) node to this node, or nil
|
15
|
+
attr_accessor :up
|
16
|
+
# The value of this node, or nil
|
17
|
+
attr_accessor :value
|
18
|
+
|
19
|
+
# Create a new Node with the given char and optionally, parent node and value
|
20
|
+
def initialize(char, parent = nil, value = nil)
|
21
|
+
@char = char
|
22
|
+
@up = parent
|
23
|
+
@value = value
|
24
|
+
end
|
25
|
+
|
26
|
+
# Add another node horizontally
|
27
|
+
# (within the left-right binary tree of this Node)
|
28
|
+
def add_horizontal(node)
|
29
|
+
if(node.char > @char)
|
30
|
+
if (@right === nil)
|
31
|
+
@right = node
|
32
|
+
else
|
33
|
+
@right.add_horizontal(node)
|
34
|
+
end
|
35
|
+
else
|
36
|
+
if (@left === nil)
|
37
|
+
@left = node
|
38
|
+
else
|
39
|
+
@left.add_horizontal(node)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
# Add and return a new, or return the existing, node with the given char horizontally
|
45
|
+
# (within the left-right binary tree of this Node)
|
46
|
+
def add_horizontal_char(char)
|
47
|
+
node = find_horizontal(char);
|
48
|
+
if node != nil
|
49
|
+
return node
|
50
|
+
end
|
51
|
+
node = Node.new(char, up)
|
52
|
+
add_horizontal(node)
|
53
|
+
return node
|
54
|
+
end
|
55
|
+
|
56
|
+
# Find and return the node corresponding to the given char horizontally, or nil if not found
|
57
|
+
# (within the left-right binary tree of this Node)
|
58
|
+
def find_horizontal(char)
|
59
|
+
return self if @char == char
|
60
|
+
if(char > @char)
|
61
|
+
if (@right === nil)
|
62
|
+
return nil
|
63
|
+
else
|
64
|
+
return @right.find_horizontal(char)
|
65
|
+
end
|
66
|
+
else
|
67
|
+
if (@left === nil)
|
68
|
+
return nil
|
69
|
+
else
|
70
|
+
return @left.find_horizontal(char)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
# Add the given String str and value vertically to this node, by adding or finding each character
|
76
|
+
# horizontally, then stepping down and repeating with the next character and so on, writing the
|
77
|
+
# value to the last node.
|
78
|
+
def add_vertical(str, value)
|
79
|
+
node = nil
|
80
|
+
str.each_char { |c|
|
81
|
+
if (node == nil)
|
82
|
+
node = self.add_horizontal_char(c)
|
83
|
+
elsif (node.down != nil)
|
84
|
+
node = node.down.add_horizontal_char(c)
|
85
|
+
else
|
86
|
+
node.down = Node.new(c, node)
|
87
|
+
node = node.down
|
88
|
+
end
|
89
|
+
}
|
90
|
+
node.value = value
|
91
|
+
end
|
92
|
+
|
93
|
+
# Find the given String str vertically by finding each character horizontally, then stepping down
|
94
|
+
# and repeating with the next character and so on. Return the last node if found, or nil if any
|
95
|
+
# horizontal search fails.
|
96
|
+
# Optionally, set the offset into the string and its length
|
97
|
+
def find_vertical(str, offset = 0, length = str.length)
|
98
|
+
node = nil
|
99
|
+
i = offset
|
100
|
+
while (i<offset+length)
|
101
|
+
c = str[i]
|
102
|
+
if (node == nil)
|
103
|
+
node = self.find_horizontal(c)
|
104
|
+
elsif (node.down != nil)
|
105
|
+
node = node.down.find_horizontal(c)
|
106
|
+
else
|
107
|
+
return nil
|
108
|
+
end
|
109
|
+
|
110
|
+
return nil if (node == nil)
|
111
|
+
i += 1
|
112
|
+
end
|
113
|
+
node
|
114
|
+
end
|
115
|
+
|
116
|
+
# Find the next match (terminating node with value non-nil) in the String data
|
117
|
+
# Optionally, set the offset into the data and its length
|
118
|
+
def find_forward(data, offset = 0, length = data.length)
|
119
|
+
node = nil
|
120
|
+
lastvaluenode = nil
|
121
|
+
i = offset
|
122
|
+
while (i<offset+length)
|
123
|
+
c = data[i]
|
124
|
+
if (node == nil)
|
125
|
+
node = self.find_horizontal(c)
|
126
|
+
elsif (node.down != nil)
|
127
|
+
node = node.down.find_horizontal(c)
|
128
|
+
else
|
129
|
+
return lastvaluenode
|
130
|
+
end
|
131
|
+
return lastvaluenode if (node == nil)
|
132
|
+
lastvaluenode = node if (node.value != nil)
|
133
|
+
i += 1
|
134
|
+
end
|
135
|
+
lastvaluenode
|
136
|
+
end
|
137
|
+
|
138
|
+
# Count the number of nodes in the given direction (:up,:down,:left,:right) until
|
139
|
+
# the edge of the tree.
|
140
|
+
def count(direction)
|
141
|
+
i = 0
|
142
|
+
node = self
|
143
|
+
while (node != nil)
|
144
|
+
node = node.send(direction)
|
145
|
+
i += 1
|
146
|
+
end
|
147
|
+
i
|
148
|
+
end
|
149
|
+
|
150
|
+
# Recursively balance this node in its own tree, and every node in all four directions,
|
151
|
+
# and return the new root node.
|
152
|
+
def balance
|
153
|
+
node = self
|
154
|
+
i = (node.count(:right) - node.count(:left))/2
|
155
|
+
while (i!=0)
|
156
|
+
if (i>0)
|
157
|
+
mvnode = node.right
|
158
|
+
node.right = nil
|
159
|
+
mvnode.add_horizontal node
|
160
|
+
i -= 1
|
161
|
+
else
|
162
|
+
mvnode = node.left
|
163
|
+
node.left = nil
|
164
|
+
mvnode.add_horizontal node
|
165
|
+
i += 1
|
166
|
+
end
|
167
|
+
node = mvnode
|
168
|
+
end
|
169
|
+
if (node.left != nil)
|
170
|
+
node.left = node.left.balance
|
171
|
+
end
|
172
|
+
if (node.right != nil)
|
173
|
+
node.right = node.right.balance
|
174
|
+
end
|
175
|
+
if (node.down != nil)
|
176
|
+
node.down = node.down.balance
|
177
|
+
end
|
178
|
+
node
|
179
|
+
end
|
180
|
+
|
181
|
+
# Walk the tree from this node, yielding all strings and values where the
|
182
|
+
# value is not nil. Optionally, use the given prefix String str.
|
183
|
+
def walk(str="", &block)
|
184
|
+
@down.walk(str+char, &block) if @down != nil
|
185
|
+
@left.walk(str, &block) if @left != nil
|
186
|
+
yield str+@char, @value if @value != nil
|
187
|
+
@right.walk(str, &block) if @right != nil
|
188
|
+
end
|
189
|
+
|
190
|
+
# Return the complete string from the tree root up to and including this node
|
191
|
+
# i.e. The total string key for this node from root.
|
192
|
+
def to_s
|
193
|
+
st = @char
|
194
|
+
node = self
|
195
|
+
while node != nil
|
196
|
+
node = node.up
|
197
|
+
break if node==nil
|
198
|
+
st = node.char+st
|
199
|
+
end
|
200
|
+
st
|
201
|
+
end
|
202
|
+
|
203
|
+
# Return the length of the total string key for this node from root.
|
204
|
+
def length
|
205
|
+
count(:up)
|
206
|
+
end
|
207
|
+
|
208
|
+
# Return an Array of Strings of all possible partial string from this node.
|
209
|
+
# Optionally, use the given prefix String str.
|
210
|
+
def all_partials(str = "")
|
211
|
+
list = []
|
212
|
+
@down.walk(str) { |str| list << str } unless @down.nil?
|
213
|
+
list
|
214
|
+
end
|
215
|
+
end
|
216
|
+
end
|
@@ -0,0 +1,98 @@
|
|
1
|
+
module StringTree
|
2
|
+
# Tree represents a complete StringTree, and has functionality resembling a Hash.
|
3
|
+
class Tree
|
4
|
+
# The root StringTree::Node, or nil if empty
|
5
|
+
attr_accessor :root
|
6
|
+
|
7
|
+
# Create a new empty Tree
|
8
|
+
def initialize
|
9
|
+
@root = nil
|
10
|
+
end
|
11
|
+
|
12
|
+
# Add a key and value to this Tree
|
13
|
+
def add(key,value)
|
14
|
+
@root = Node.new(key[0], nil) if (@root == nil)
|
15
|
+
@root.add_vertical(key,value)
|
16
|
+
end
|
17
|
+
|
18
|
+
# Find a specified key in the Tree, and return the value, or nil if not found.
|
19
|
+
def find(key)
|
20
|
+
return nil if @root == nil
|
21
|
+
node = @root.find_vertical(key)
|
22
|
+
(node == nil ? nil : node.value)
|
23
|
+
end
|
24
|
+
|
25
|
+
# Return true if the given key exists
|
26
|
+
def has_key?(key)
|
27
|
+
return false if @root == nil
|
28
|
+
node = @root.find_vertical(key)
|
29
|
+
return false if node.nil? or node.value.nil?
|
30
|
+
true
|
31
|
+
end
|
32
|
+
|
33
|
+
# Return an Array of Strings representing all partial matches forward of key in the Tree.
|
34
|
+
# Please note the key itself is not included, even if it exists as a value.
|
35
|
+
#
|
36
|
+
# E.g.: A tree containing 'ant','antler','deer','anthropic','beer'
|
37
|
+
# tree.partials('ant') would return ['antler','anthropic']
|
38
|
+
def partials(key)
|
39
|
+
return nil if @root == nil
|
40
|
+
node = @root.find_vertical(key)
|
41
|
+
return nil if node == nil
|
42
|
+
node.all_partials(key)
|
43
|
+
end
|
44
|
+
|
45
|
+
# Rebalance the tree for faster access.
|
46
|
+
def optimize!
|
47
|
+
return nil if @root == nil
|
48
|
+
@root = @root.balance
|
49
|
+
end
|
50
|
+
|
51
|
+
# Tokenize the string Data by finding all instances of any key in the Tree.
|
52
|
+
# yields each instance as a StringTree::Item.
|
53
|
+
def match_all(data, &block)
|
54
|
+
return nil if @root == nil
|
55
|
+
i=0
|
56
|
+
while (i<data.length)
|
57
|
+
node = @root.find_forward(data, i, data.length-i)
|
58
|
+
if (node!=nil && node.value!=nil)
|
59
|
+
yield Item.new(i, true, node)
|
60
|
+
i += node.length
|
61
|
+
else
|
62
|
+
i += 1
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
# Alias for find
|
68
|
+
def [](key)
|
69
|
+
find(key)
|
70
|
+
end
|
71
|
+
|
72
|
+
# Alias for add
|
73
|
+
def []=(key,value)
|
74
|
+
add(key,value)
|
75
|
+
end
|
76
|
+
|
77
|
+
# Return a Hash of terminating nodes to Integer counts for a given String data,
|
78
|
+
# i.e. Find the count of instances of each String in the tree in the given data.
|
79
|
+
def match_count(data, list = {})
|
80
|
+
return nil if @root == nil
|
81
|
+
i=0
|
82
|
+
while (i<data.length)
|
83
|
+
node = @root.find_forward(data, i, data.length-i)
|
84
|
+
if (node!=nil && node.value!=nil)
|
85
|
+
if (!list.has_key?(node))
|
86
|
+
list[node] = 1
|
87
|
+
else
|
88
|
+
list[node] += 1
|
89
|
+
end
|
90
|
+
i += node.length
|
91
|
+
else
|
92
|
+
i += 1
|
93
|
+
end
|
94
|
+
end
|
95
|
+
list
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
data/lib/stringtree.rb
ADDED
data/spec/item_spec.rb
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe StringTree::Item do
|
4
|
+
describe "#initalize" do
|
5
|
+
it "should initialize correctly" do
|
6
|
+
@nodea = StringTree::Item.new(1,2,3)
|
7
|
+
expect(@nodea.offset).to eq(1)
|
8
|
+
expect(@nodea.match).to eq(2)
|
9
|
+
expect(@nodea.node).to eq(3)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
describe "#match?" do
|
14
|
+
it "should return @match" do
|
15
|
+
@nodea = StringTree::Item.new(1,2,3)
|
16
|
+
expect(@nodea.match?).to eq(2)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
describe "#value" do
|
21
|
+
it "should return @node.value if not nil" do
|
22
|
+
x = OpenStruct.new(:value => "foo")
|
23
|
+
@nodea = StringTree::Item.new(1,2,x)
|
24
|
+
expect(@nodea.value).to eq("foo")
|
25
|
+
end
|
26
|
+
|
27
|
+
it "should return nil if value is nil" do
|
28
|
+
@nodea = StringTree::Item.new(1,2,nil)
|
29
|
+
expect(@nodea.value).to be_nil()
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
data/spec/node_spec.rb
ADDED
@@ -0,0 +1,187 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe StringTree::Node do
|
4
|
+
describe "when instantiated" do
|
5
|
+
it "has correct char" do
|
6
|
+
@nodea = StringTree::Node.new 'a'
|
7
|
+
expect(@nodea.char).to eq(@nodea.char)
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
describe "add tests" do
|
12
|
+
before do
|
13
|
+
@nodeb = StringTree::Node.new 'b'
|
14
|
+
@nodec = @nodeb.add_horizontal_char('c')
|
15
|
+
@nodea = @nodeb.add_horizontal_char('a')
|
16
|
+
end
|
17
|
+
it "adds a on correct side" do
|
18
|
+
expect(@nodeb.left).to eq(@nodeb.left)
|
19
|
+
end
|
20
|
+
it "adds c on correct side" do
|
21
|
+
expect(@nodeb.right).to eq(@nodeb.right)
|
22
|
+
end
|
23
|
+
it "does not add a again" do
|
24
|
+
expect(@nodeb.add_horizontal_char('a')).to eq(@nodeb.add_horizontal_char('a'))
|
25
|
+
end
|
26
|
+
it "count left correct" do
|
27
|
+
expect(@nodeb.count(:left)).to eq(@nodeb.count(:left))
|
28
|
+
end
|
29
|
+
it "count right correct" do
|
30
|
+
expect(@nodeb.count(:right)).to eq(@nodeb.count(:right))
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
describe "find tests" do
|
35
|
+
before do
|
36
|
+
@nodeb = StringTree::Node.new 'b'
|
37
|
+
@nodec = @nodeb.add_horizontal_char('c')
|
38
|
+
@nodea = @nodeb.add_horizontal_char('a')
|
39
|
+
end
|
40
|
+
it "finds a" do
|
41
|
+
@nodeb.find_horizontal('a') == @nodea
|
42
|
+
end
|
43
|
+
it "finds c" do
|
44
|
+
@nodeb.find_horizontal('c') == @nodec
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
describe "vertical tests" do
|
49
|
+
before do
|
50
|
+
@node = StringTree::Node.new 'a'
|
51
|
+
@str = "testing"
|
52
|
+
@node.add_vertical(@str, 'one')
|
53
|
+
end
|
54
|
+
it "string exists in stringtree" do
|
55
|
+
@str.each_char { |c|
|
56
|
+
@node = @node.find_horizontal(c);
|
57
|
+
expect(@node).not_to be(nil)
|
58
|
+
expect(@node.char).to eq(@node.char)
|
59
|
+
@node = @node.down
|
60
|
+
}
|
61
|
+
end
|
62
|
+
it "find_vertical returns correct value" do
|
63
|
+
expect(@node.find_vertical(@str).value).to eq(@node.find_vertical(@str).value)
|
64
|
+
end
|
65
|
+
it "find_vertical does not find superstring" do
|
66
|
+
expect(@node.find_vertical("testing1")).to eq(@node.find_vertical("testing1"))
|
67
|
+
expect(@node.find_vertical("testin").value).to eq(@node.find_vertical("testin").value)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
describe "optimize tests" do
|
72
|
+
before do
|
73
|
+
@node = StringTree::Node.new 'a'
|
74
|
+
@val = {
|
75
|
+
"one"=>1, "two"=>2, "three"=>3, "four"=>4, "five"=>5, "six"=>6, "seven"=>7, "eight"=>8, "nine"=>9, "ten"=>10,
|
76
|
+
"eleven"=>11, "twelve"=>12, "thirteen"=>13, "fourteen"=>14, "fifteen"=>15, "sixteen"=>16, "seventeen"=>17, "eighteen"=>18, "nineteen"=>19, "twenty"=>20
|
77
|
+
}
|
78
|
+
@val.each { |c,d| @node.add_vertical(c,d) }
|
79
|
+
@node = @node.balance
|
80
|
+
end
|
81
|
+
it "string exists in stringtree" do
|
82
|
+
'one'.each_char { |c|
|
83
|
+
@node = @node.find_horizontal(c)
|
84
|
+
expect(@node).not_to be(nil)
|
85
|
+
expect(@node.char).to eq(@node.char)
|
86
|
+
@node = @node.down
|
87
|
+
}
|
88
|
+
end
|
89
|
+
it "find_vertical returns correct value" do
|
90
|
+
expect(@node.find_vertical("one").value).to eq(@node.find_vertical("one").value)
|
91
|
+
end
|
92
|
+
it "find_vertical does not find superstring" do
|
93
|
+
expect(@node.find_vertical("testing1")).to eq(@node.find_vertical("testing1"))
|
94
|
+
expect(@node.find_vertical("testin")).to eq(@node.find_vertical("testin"))
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
describe '#walk' do
|
99
|
+
it 'should walk a tree correctly' do
|
100
|
+
inst = StringTree::Node.new 'b'
|
101
|
+
inst.left = StringTree::Node.new 'a'
|
102
|
+
inst.right = StringTree::Node.new 'c'
|
103
|
+
inst.down = StringTree::Node.new '2'
|
104
|
+
inst.down.left = StringTree::Node.new '1'
|
105
|
+
inst.down.right = StringTree::Node.new '3'
|
106
|
+
|
107
|
+
list = []
|
108
|
+
inst.walk do |k,v|
|
109
|
+
puts k,v
|
110
|
+
list << { k => v }
|
111
|
+
end
|
112
|
+
expect(list).to eq []
|
113
|
+
end
|
114
|
+
|
115
|
+
end
|
116
|
+
|
117
|
+
describe '#all_partials' do
|
118
|
+
it 'should call @down.walk if it exists' do
|
119
|
+
|
120
|
+
inst = StringTree::Node.new 'a'
|
121
|
+
inst.down = StringTree::Node.new 'b'
|
122
|
+
|
123
|
+
expect(inst.down).to receive(:walk).with('one')
|
124
|
+
inst.all_partials('one')
|
125
|
+
end
|
126
|
+
|
127
|
+
it 'should not call @down.walk if it doesnt exist' do
|
128
|
+
# Spec will fail with exception if faulty.
|
129
|
+
inst = StringTree::Node.new 'a'
|
130
|
+
inst.down = nil
|
131
|
+
inst.all_partials('one')
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
describe '#find_forward' do
|
136
|
+
it 'should return the correct node' do
|
137
|
+
|
138
|
+
inst = StringTree::Node.new 'b'
|
139
|
+
inst.left = StringTree::Node.new 'a'
|
140
|
+
inst.right = StringTree::Node.new 'c'
|
141
|
+
inst.down = StringTree::Node.new '2', inst, 'one'
|
142
|
+
inst.down.left = StringTree::Node.new '1', inst
|
143
|
+
inst.down.right = StringTree::Node.new '3', inst
|
144
|
+
|
145
|
+
expect(inst.find_forward("b2",0,2)).to be(inst.down)
|
146
|
+
expect(inst.find_forward("asoicbasicn",0,2)).to be_nil
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
describe '#to_s' do
|
151
|
+
it 'should return the correct string' do
|
152
|
+
inst = StringTree::Node.new 'b'
|
153
|
+
inst.left = StringTree::Node.new 'a'
|
154
|
+
inst.right = StringTree::Node.new 'c'
|
155
|
+
inst.down = StringTree::Node.new '2', inst, 'one'
|
156
|
+
inst.down.left = StringTree::Node.new '1', inst
|
157
|
+
inst.down.right = StringTree::Node.new '3', inst
|
158
|
+
|
159
|
+
expect(inst.down.left.to_s).to eq("b1")
|
160
|
+
expect(inst.down.right.to_s).to eq("b3")
|
161
|
+
expect(inst.down.to_s).to eq("b2")
|
162
|
+
expect(inst.right.to_s).to eq("c")
|
163
|
+
expect(inst.left.to_s).to eq("a")
|
164
|
+
expect(inst.to_s).to eq("b")
|
165
|
+
end
|
166
|
+
end
|
167
|
+
|
168
|
+
describe '#length' do
|
169
|
+
it 'should return the correct count' do
|
170
|
+
inst = StringTree::Node.new 'b'
|
171
|
+
inst.left = StringTree::Node.new 'a'
|
172
|
+
inst.right = StringTree::Node.new 'c'
|
173
|
+
inst.down = StringTree::Node.new '2', inst, 'one'
|
174
|
+
inst.down.left = StringTree::Node.new '1', inst
|
175
|
+
inst.down.right = StringTree::Node.new '3', inst
|
176
|
+
inst.down.left.down = StringTree::Node.new 'z', inst.down.left
|
177
|
+
inst.down.left.down.left = StringTree::Node.new 'v', inst.down.left
|
178
|
+
|
179
|
+
expect(inst.down.left.down.left.length).to eq(3)
|
180
|
+
expect(inst.down.left.down.length).to eq(3)
|
181
|
+
expect(inst.down.left.length).to eq(2)
|
182
|
+
expect(inst.down.length).to eq(2)
|
183
|
+
expect(inst.length).to eq(1)
|
184
|
+
end
|
185
|
+
end
|
186
|
+
|
187
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
# Supress Warnings
|
2
|
+
warn_level = $VERBOSE
|
3
|
+
$VERBOSE = nil
|
4
|
+
|
5
|
+
if ENV.has_key?('SIMPLECOV')
|
6
|
+
require 'simplecov'
|
7
|
+
require 'simplecov-rcov'
|
8
|
+
|
9
|
+
SimpleCov.formatter = SimpleCov::Formatter::RcovFormatter
|
10
|
+
SimpleCov.start do
|
11
|
+
add_filter '/spec/'
|
12
|
+
end
|
13
|
+
else
|
14
|
+
require 'coveralls'
|
15
|
+
Coveralls.wear!
|
16
|
+
end
|
17
|
+
|
18
|
+
require 'stringtree'
|
19
|
+
require 'ostruct'
|