rubytree 0.9.4 → 0.9.5pre
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.
- checksums.yaml +4 -4
- data/Gemfile.lock +12 -10
- data/History.rdoc +12 -0
- data/README.md +1 -0
- data/TAGS +242 -0
- data/TODO.org +15 -9
- data/lib/tree.rb +43 -11
- data/lib/tree/binarytree.rb +33 -1
- data/lib/tree/tree_deps.rb +1 -0
- data/lib/tree/utils/hash_converter.rb +161 -0
- data/lib/tree/utils/json_converter.rb +4 -4
- data/lib/tree/version.rb +1 -1
- data/test/test_binarytree.rb +67 -0
- data/test/test_tree.rb +239 -8
- metadata +7 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 93e0fdbd846f7fada7cd50d0e0ab414834f464dc
|
4
|
+
data.tar.gz: 3e70254cbc163580c3b7e40a497292a8e4d15128
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 957a7cdbb556f41f9c599f82483f058e72cf432837a73bf71d1c86a26c0a3f1c2e1d3a8706a419d1c057b46920215ba2b9046bd83f10720efe46f3bb29bb2486
|
7
|
+
data.tar.gz: e74fb819ae9e568a1d5409f98ae89c18e0bd85f98300df7cc272dbfa9a7c4f01aa1d9474a8bc7fbb0f334019e3b045e2313621f16b2276aaf206bec24f241c6e
|
data/Gemfile.lock
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
rubytree (0.9.
|
4
|
+
rubytree (0.9.5pre)
|
5
5
|
json (~> 1.8)
|
6
6
|
structured_warnings (~> 0.1)
|
7
7
|
|
8
8
|
GEM
|
9
9
|
remote: https://rubygems.org/
|
10
10
|
specs:
|
11
|
-
coveralls (0.7.
|
11
|
+
coveralls (0.7.1)
|
12
12
|
multi_json (~> 1.3)
|
13
13
|
rest-client
|
14
14
|
simplecov (>= 0.7)
|
@@ -16,27 +16,29 @@ GEM
|
|
16
16
|
thor
|
17
17
|
docile (1.1.5)
|
18
18
|
json (1.8.1)
|
19
|
-
mime-types (2.3)
|
19
|
+
mime-types (2.4.3)
|
20
20
|
multi_json (1.10.1)
|
21
|
+
netrc (0.8.0)
|
21
22
|
rake (10.3.2)
|
22
|
-
rdoc (4.1.
|
23
|
+
rdoc (4.1.2)
|
23
24
|
json (~> 1.4)
|
24
|
-
rest-client (1.
|
25
|
-
mime-types (>= 1.16)
|
25
|
+
rest-client (1.7.2)
|
26
|
+
mime-types (>= 1.16, < 3.0)
|
27
|
+
netrc (~> 0.7)
|
26
28
|
rtags (0.98)
|
27
29
|
rtagstask (0.0.4)
|
28
30
|
rtags (> 0.0.0)
|
29
|
-
simplecov (0.
|
31
|
+
simplecov (0.9.1)
|
30
32
|
docile (~> 1.1.0)
|
31
|
-
multi_json
|
33
|
+
multi_json (~> 1.0)
|
32
34
|
simplecov-html (~> 0.8.0)
|
33
35
|
simplecov-html (0.8.0)
|
34
36
|
structured_warnings (0.1.4)
|
35
37
|
term-ansicolor (1.3.0)
|
36
38
|
tins (~> 1.0)
|
37
39
|
thor (0.19.1)
|
38
|
-
tins (1.3.
|
39
|
-
yard (0.8.7.
|
40
|
+
tins (1.3.3)
|
41
|
+
yard (0.8.7.6)
|
40
42
|
|
41
43
|
PLATFORMS
|
42
44
|
ruby
|
data/History.rdoc
CHANGED
@@ -2,6 +2,18 @@
|
|
2
2
|
|
3
3
|
= History of Changes
|
4
4
|
|
5
|
+
=== 0.9.5pre / 2014-11-01
|
6
|
+
|
7
|
+
* Fixed {issue 13}[https://github.com/evolve75/RubyTree/issues/13] with the
|
8
|
+
patch provided by {Jen Hamon}[http://www.github.com/jhamon].
|
9
|
+
|
10
|
+
* Fixed a bug in {Tree::TreeNode#print_tree} with the patch provided by
|
11
|
+
{https://github.com/packetmonkey Evan Sharp}.
|
12
|
+
|
13
|
+
* Fixed {issue 31}[https://github.com/evolve75/RubyTree/issues/31], which was
|
14
|
+
causing incorrect behavior n {Tree::TreeNode#postordered_each} and
|
15
|
+
{Tree::TreeNode#breadth_each} methods when a block was not provided.
|
16
|
+
|
5
17
|
=== 0.9.4 / 2014-07-04
|
6
18
|
|
7
19
|
* Changed all references to {http://rubyforge.org}.
|
data/README.md
CHANGED
@@ -210,6 +210,7 @@ A big thanks to the following contributors for helping improve **RubyTree**:
|
|
210
210
|
duplicate node names in the tree (globally unique names).
|
211
211
|
6. [Paul de Courcel](https://github.com/pdecourcel) for adding the
|
212
212
|
`postordered_each` method.
|
213
|
+
7. [Jen Hamon](http://www.github.com/jhamon) for adding the `from_hash` method.
|
213
214
|
|
214
215
|
## LICENSE: ##
|
215
216
|
|
data/TAGS
ADDED
@@ -0,0 +1,242 @@
|
|
1
|
+
|
2
|
+
lib/rubytree.rb,0
|
3
|
+
|
4
|
+
lib/tree/binarytree.rb,795
|
5
|
+
module Tree::Tree43,1906
|
6
|
+
class BinaryTreeNode::Tree::BinaryTreeNode52,2215
|
7
|
+
def left_child::Tree::BinaryTreeNode#left_child62,2498
|
8
|
+
def right_child::Tree::BinaryTreeNode#right_child74,2889
|
9
|
+
def is_left_child?::Tree::BinaryTreeNode#is_left_child?83,3165
|
10
|
+
def is_right_child?::Tree::BinaryTreeNode#is_right_child?93,3496
|
11
|
+
def add::Tree::BinaryTreeNode#add110,4153
|
12
|
+
def add_from_hash::Tree::BinaryTreeNode#add_from_hash143,5539
|
13
|
+
def inordered_each::Tree::BinaryTreeNode#inordered_each160,6096
|
14
|
+
def set_child_at::Tree::BinaryTreeNode#set_child_at191,7032
|
15
|
+
def left_child=::Tree::BinaryTreeNode#left_child=210,7700
|
16
|
+
def right_child=::Tree::BinaryTreeNode#right_child=222,8069
|
17
|
+
def swap_children::Tree::BinaryTreeNode#swap_children227,8215
|
18
|
+
|
19
|
+
lib/tree/tree_deps.rb,0
|
20
|
+
|
21
|
+
lib/tree/utils/camel_case_method_handler.rb,324
|
22
|
+
module Tree::Tree41,1848
|
23
|
+
module CamelCaseMethodHandler::Tree::CamelCaseMethodHandler44,2004
|
24
|
+
def self.included::Tree::CamelCaseMethodHandler.included45,2038
|
25
|
+
def method_missing::Tree::CamelCaseMethodHandler#method_missing49,2186
|
26
|
+
def to_snake_case::Tree::CamelCaseMethodHandler#to_snake_case66,2798
|
27
|
+
|
28
|
+
lib/tree/utils/hash_converter.rb,265
|
29
|
+
module Tree::Tree40,1916
|
30
|
+
def self.included::Tree.included42,1953
|
31
|
+
module ClassMethods::Tree::ClassMethods49,2177
|
32
|
+
def from_hash::Tree::ClassMethods#from_hash86,3823
|
33
|
+
def add_from_hash::Tree#add_from_hash129,5519
|
34
|
+
def to_h::Tree#to_h151,6367
|
35
|
+
|
36
|
+
lib/tree/utils/json_converter.rb,258
|
37
|
+
module Tree::Tree42,1925
|
38
|
+
def self.included::Tree.included44,1962
|
39
|
+
def as_json::Tree#as_json61,2413
|
40
|
+
def to_json::Tree#to_json89,3121
|
41
|
+
module ClassMethods::Tree::ClassMethods94,3271
|
42
|
+
def json_create::Tree::ClassMethods#json_create113,3986
|
43
|
+
|
44
|
+
lib/tree/utils/metrics_methods.rb,718
|
45
|
+
module Tree::Tree41,1833
|
46
|
+
module TreeMetricsHandler::Tree::TreeMetricsHandler43,1918
|
47
|
+
def self.included::Tree::TreeMetricsHandler.included44,1948
|
48
|
+
def size::Tree::TreeMetricsHandler#size56,2317
|
49
|
+
def length::Tree::TreeMetricsHandler#length67,2661
|
50
|
+
def node_height::Tree::TreeMetricsHandler#node_height80,3078
|
51
|
+
def node_depth::Tree::TreeMetricsHandler#node_depth96,3689
|
52
|
+
def level::Tree::TreeMetricsHandler#level105,3875
|
53
|
+
def depth::Tree::TreeMetricsHandler#depth124,4560
|
54
|
+
def breadth::Tree::TreeMetricsHandler#breadth140,5197
|
55
|
+
def in_degree::Tree::TreeMetricsHandler#in_degree154,5660
|
56
|
+
def out_degree::Tree::TreeMetricsHandler#out_degree165,5973
|
57
|
+
|
58
|
+
lib/tree/utils/tree_merge_handler.rb,214
|
59
|
+
module Tree::Tree40,1769
|
60
|
+
def merge::Tree#merge57,2500
|
61
|
+
def merge!::Tree#merge!72,3134
|
62
|
+
def check_merge_prerequisites::Tree#check_merge_prerequisites85,3441
|
63
|
+
def merge_trees::Tree#merge_trees102,4086
|
64
|
+
|
65
|
+
lib/tree/utils/utils.rb,27
|
66
|
+
module Tree::Tree39,1838
|
67
|
+
|
68
|
+
lib/tree/version.rb,27
|
69
|
+
module Tree::Tree38,1723
|
70
|
+
|
71
|
+
lib/tree.rb,2790
|
72
|
+
module Tree::Tree48,2158
|
73
|
+
class TreeNode::Tree::TreeNode85,3731
|
74
|
+
attr_reader :name::Tree::TreeNode#name109,4522
|
75
|
+
attr_accessor :content::Tree::TreeNode#content116,4721
|
76
|
+
attr_reader :parent::Tree::TreeNode#parent120,4837
|
77
|
+
def root::Tree::TreeNode#root127,5049
|
78
|
+
def is_root?::Tree::TreeNode#is_root?138,5355
|
79
|
+
def has_content?::Tree::TreeNode#has_content?146,5538
|
80
|
+
def is_leaf?::Tree::TreeNode#is_leaf?157,5792
|
81
|
+
def parentage::Tree::TreeNode#parentage169,6167
|
82
|
+
def has_children?::Tree::TreeNode#has_children?187,6593
|
83
|
+
def initialize::Tree::TreeNode#Tree::TreeNode.new210,7419
|
84
|
+
def detached_copy::Tree::TreeNode#detached_copy228,8036
|
85
|
+
def detached_subtree_copy::Tree::TreeNode#detached_subtree_copy238,8322
|
86
|
+
alias :dup::Tree::TreeNode#dup247,8583
|
87
|
+
def marshal_dump::Tree::TreeNode#marshal_dump252,8761
|
88
|
+
def create_dump_rep::Tree::TreeNode#create_dump_rep258,8929
|
89
|
+
def marshal_load::Tree::TreeNode#marshal_load273,9467
|
90
|
+
def to_s::Tree::TreeNode#to_s298,10251
|
91
|
+
def <<::Tree::TreeNode#<<321,11022
|
92
|
+
def add::Tree::TreeNode#add356,12550
|
93
|
+
def insertion_range::Tree::TreeNode#insertion_range376,13512
|
94
|
+
def replace!::Tree::TreeNode#replace!391,13930
|
95
|
+
def replace_with::Tree::TreeNode#replace_with405,14303
|
96
|
+
def remove!::Tree::TreeNode#remove!423,15035
|
97
|
+
def parent=::Tree::TreeNode#parent=438,15438
|
98
|
+
def remove_from_parent!::Tree::TreeNode#remove_from_parent!451,15823
|
99
|
+
def remove_all!::Tree::TreeNode#remove_all!462,16195
|
100
|
+
def set_as_root!::Tree::TreeNode#set_as_root!473,16424
|
101
|
+
def freeze_tree!::Tree::TreeNode#freeze_tree!483,16750
|
102
|
+
def []::Tree::TreeNode#[]523,18268
|
103
|
+
def each::Tree::TreeNode#each548,19235
|
104
|
+
def preordered_each::Tree::TreeNode#preordered_each576,20195
|
105
|
+
def postordered_each::Tree::TreeNode#postordered_each588,20607
|
106
|
+
def breadth_each::Tree::TreeNode#breadth_each624,22052
|
107
|
+
def children::Tree::TreeNode#children650,23005
|
108
|
+
def each_leaf::Tree::TreeNode#each_leaf671,23626
|
109
|
+
def first_child::Tree::TreeNode#first_child688,24048
|
110
|
+
def last_child::Tree::TreeNode#last_child696,24259
|
111
|
+
def first_sibling::Tree::TreeNode#first_sibling712,24706
|
112
|
+
def is_first_sibling?::Tree::TreeNode#is_first_sibling?722,24980
|
113
|
+
def last_sibling::Tree::TreeNode#last_sibling736,25396
|
114
|
+
def is_last_sibling?::Tree::TreeNode#is_last_sibling?746,25666
|
115
|
+
def siblings::Tree::TreeNode#siblings762,26219
|
116
|
+
def is_only_child?::Tree::TreeNode#is_only_child?781,26771
|
117
|
+
def next_sibling::Tree::TreeNode#next_sibling794,27174
|
118
|
+
def previous_sibling::Tree::TreeNode#previous_sibling810,27648
|
119
|
+
def <=>::Tree::TreeNode#<=>826,28159
|
120
|
+
def print_tree::Tree::TreeNode#print_tree836,28539
|
121
|
+
|
122
|
+
test/run_test.rb,0
|
123
|
+
|
124
|
+
test/test_binarytree.rb,1361
|
125
|
+
module TestTree::TestTree39,1717
|
126
|
+
class TestBinaryTreeNode::TestTree::TestBinaryTreeNode41,1776
|
127
|
+
def setup::TestTree::TestBinaryTreeNode#setup44,1868
|
128
|
+
def teardown::TestTree::TestBinaryTreeNode#teardown52,2171
|
129
|
+
def test_initialize::TestTree::TestBinaryTreeNode#test_initialize59,2330
|
130
|
+
def test_from_hash::TestTree::TestBinaryTreeNode#test_from_hash66,2692
|
131
|
+
def test_add_from_hash::TestTree::TestBinaryTreeNode#test_add_from_hash101,4024
|
132
|
+
def test_add::TestTree::TestBinaryTreeNode#test_add134,5134
|
133
|
+
def test_inordered_each::TestTree::TestBinaryTreeNode#test_inordered_each157,6048
|
134
|
+
def test_left_child::TestTree::TestBinaryTreeNode#test_left_child201,7516
|
135
|
+
def test_right_child::TestTree::TestBinaryTreeNode#test_right_child209,7829
|
136
|
+
def test_left_child_equals::TestTree::TestBinaryTreeNode#test_left_child_equals217,8142
|
137
|
+
def test_right_child_equals::TestTree::TestBinaryTreeNode#test_right_child_equals236,9132
|
138
|
+
def test_is_left_child_eh::TestTree::TestBinaryTreeNode#test_is_left_child_eh256,10249
|
139
|
+
def test_is_right_child_eh::TestTree::TestBinaryTreeNode#test_is_right_child_eh271,10788
|
140
|
+
def test_swap_children::TestTree::TestBinaryTreeNode#test_swap_children285,11334
|
141
|
+
def test_old_camelCase_method_names::TestTree::TestBinaryTreeNode#test_old_camelCase_method_names303,12217
|
142
|
+
|
143
|
+
test/test_rubytree_require.rb,203
|
144
|
+
module TestTree::TestTree38,1678
|
145
|
+
class TestRequireRubytree::TestTree::TestRequireRubytree41,1759
|
146
|
+
def test_create_a_simple_node::TestTree::TestRequireRubytree#test_create_a_simple_node44,1884
|
147
|
+
|
148
|
+
test/test_subclassed_node.rb,389
|
149
|
+
module TestTree::TestTree39,1688
|
150
|
+
class TestSubclassedTreeNode::TestTree::TestSubclassedTreeNode42,1741
|
151
|
+
class MyNode::TestTree::TestSubclassedTreeNode::MyNode45,1868
|
152
|
+
def my_dummy_method::TestTree::TestSubclassedTreeNode::MyNode#my_dummy_method47,1967
|
153
|
+
def test_subclassed_camelcase_methods::TestTree::TestSubclassedTreeNode#test_subclassed_camelcase_methods52,2026
|
154
|
+
|
155
|
+
test/test_thread_and_fiber.rb,422
|
156
|
+
module TestTree::TestTree39,1695
|
157
|
+
class TestFiberAndThreadOnNode::TestTree::TestFiberAndThreadOnNode41,1747
|
158
|
+
def create_long_depth_trees::TestTree::TestFiberAndThreadOnNode#create_long_depth_trees44,1843
|
159
|
+
def test_fiber_for_recursion::TestTree::TestFiberAndThreadOnNode#test_fiber_for_recursion59,2260
|
160
|
+
def test_thread_for_recursion::TestTree::TestFiberAndThreadOnNode#test_thread_for_recursion73,2807
|
161
|
+
|
162
|
+
test/test_tree.rb,6262
|
163
|
+
module TestTree::TestTree39,1725
|
164
|
+
class TestTreeNode::TestTree::TestTreeNode41,1777
|
165
|
+
def setup::TestTree::TestTreeNode#setup65,2610
|
166
|
+
def setup_test_tree::TestTree::TestTreeNode#setup_test_tree77,3030
|
167
|
+
def teardown::TestTree::TestTreeNode#teardown84,3180
|
168
|
+
def test_has_version_number::TestTree::TestTreeNode#test_has_version_number89,3272
|
169
|
+
def test_root_setup::TestTree::TestTreeNode#test_root_setup94,3423
|
170
|
+
def test_root::TestTree::TestTreeNode#test_root111,4473
|
171
|
+
def test_from_hash::TestTree::TestTreeNode#test_from_hash123,4974
|
172
|
+
def test_from_hash_with_nils::TestTree::TestTreeNode#test_from_hash_with_nils175,6546
|
173
|
+
def test_add_from_hash::TestTree::TestTreeNode#test_add_from_hash221,7902
|
174
|
+
def test_to_h::TestTree::TestTreeNode#test_to_h253,8917
|
175
|
+
def test_to_h_from_hash_symmetry::TestTree::TestTreeNode#test_to_h_from_hash_symmetry279,9496
|
176
|
+
def test_has_content_eh::TestTree::TestTreeNode#test_has_content_eh295,9894
|
177
|
+
def test_length_is_size::TestTree::TestTreeNode#test_length_is_size306,10352
|
178
|
+
def test_spaceship::TestTree::TestTreeNode#test_spaceship312,10542
|
179
|
+
def test_is_comparable::TestTree::TestTreeNode#test_is_comparable338,11325
|
180
|
+
def test_to_s::TestTree::TestTreeNode#test_to_s356,12107
|
181
|
+
def test_first_sibling::TestTree::TestTreeNode#test_first_sibling389,13825
|
182
|
+
def test_is_first_sibling_eh::TestTree::TestTreeNode#test_is_first_sibling_eh402,14553
|
183
|
+
def test_is_last_sibling_eh::TestTree::TestTreeNode#test_is_last_sibling_eh413,15036
|
184
|
+
def test_last_sibling::TestTree::TestTreeNode#test_last_sibling424,15504
|
185
|
+
def test_siblings::TestTree::TestTreeNode#test_siblings436,16158
|
186
|
+
def test_is_only_child_eh::TestTree::TestTreeNode#test_is_only_child_eh464,17081
|
187
|
+
def test_next_sibling::TestTree::TestTreeNode#test_next_sibling475,17517
|
188
|
+
def test_previous_sibling::TestTree::TestTreeNode#test_previous_sibling486,18017
|
189
|
+
def test_add::TestTree::TestTreeNode#test_add497,18546
|
190
|
+
def test_add_duplicate::TestTree::TestTreeNode#test_add_duplicate518,19228
|
191
|
+
def test_add_at_specific_position::TestTree::TestTreeNode#test_add_at_specific_position559,20656
|
192
|
+
def test_replace_bang::TestTree::TestTreeNode#test_replace_bang623,23711
|
193
|
+
def test_replace_with::TestTree::TestTreeNode#test_replace_with647,24756
|
194
|
+
def test_remove_bang::TestTree::TestTreeNode#test_remove_bang665,25481
|
195
|
+
def test_remove_all_bang::TestTree::TestTreeNode#test_remove_all_bang697,26444
|
196
|
+
def test_remove_from_parent_bang::TestTree::TestTreeNode#test_remove_from_parent_bang707,26750
|
197
|
+
def test_children::TestTree::TestTreeNode#test_children726,27465
|
198
|
+
def test_first_child::TestTree::TestTreeNode#test_first_child762,29054
|
199
|
+
def test_last_child::TestTree::TestTreeNode#test_last_child771,29382
|
200
|
+
def test_find::TestTree::TestTreeNode#test_find780,29698
|
201
|
+
def test_parentage::TestTree::TestTreeNode#test_parentage795,30293
|
202
|
+
def test_each::TestTree::TestTreeNode#test_each804,30625
|
203
|
+
def test_each_leaf::TestTree::TestTreeNode#test_each_leaf823,31309
|
204
|
+
def test_parent::TestTree::TestTreeNode#test_parent850,32504
|
205
|
+
def test_indexed_access::TestTree::TestTreeNode#test_indexed_access861,32923
|
206
|
+
def test_print_tree::TestTree::TestTreeNode#test_print_tree872,33296
|
207
|
+
def test_marshal_dump::TestTree::TestTreeNode#test_marshal_dump879,33456
|
208
|
+
alias test_marshal_load::TestTree::TestTreeNode#test_marshal_load921,35578
|
209
|
+
def test_collect::TestTree::TestTreeNode#test_collect924,35699
|
210
|
+
def test_freeze_tree_bang::TestTree::TestTreeNode#test_freeze_tree_bang934,35965
|
211
|
+
def test_content::TestTree::TestTreeNode#test_content948,36487
|
212
|
+
def test_depth::TestTree::TestTreeNode#test_depth956,36878
|
213
|
+
def do_deprecated_depth::TestTree::TestTreeNode#do_deprecated_depth967,37251
|
214
|
+
def test_node_height::TestTree::TestTreeNode#test_node_height985,37819
|
215
|
+
def test_node_depth::TestTree::TestTreeNode#test_node_depth1010,39028
|
216
|
+
def test_level::TestTree::TestTreeNode#test_level1023,39465
|
217
|
+
def test_breadth::TestTree::TestTreeNode#test_breadth1038,40008
|
218
|
+
def test_breadth_each::TestTree::TestTreeNode#test_breadth_each1057,40655
|
219
|
+
def test_preordered_each::TestTree::TestTreeNode#test_preordered_each1106,42240
|
220
|
+
def test_postordered_each::TestTree::TestTreeNode#test_postordered_each1145,43494
|
221
|
+
def test_detached_copy::TestTree::TestTreeNode#test_detached_copy1194,45031
|
222
|
+
def test_detached_subtree_copy::TestTree::TestTreeNode#test_detached_subtree_copy1211,45759
|
223
|
+
def test_has_children_eh::TestTree::TestTreeNode#test_has_children_eh1245,48011
|
224
|
+
def test_is_leaf_eh::TestTree::TestTreeNode#test_is_leaf_eh1251,48173
|
225
|
+
def test_is_root_eh::TestTree::TestTreeNode#test_is_root_eh1258,48379
|
226
|
+
def test_content_equals::TestTree::TestTreeNode#test_content_equals1264,48542
|
227
|
+
def test_size::TestTree::TestTreeNode#test_size1272,48807
|
228
|
+
def test_lt2::TestTree::TestTreeNode#test_lt21281,49071
|
229
|
+
def test_index::TestTree::TestTreeNode#test_index1292,49563
|
230
|
+
def test_in_degree::TestTree::TestTreeNode#test_in_degree1313,50659
|
231
|
+
def test_out_degree::TestTree::TestTreeNode#test_out_degree1324,51126
|
232
|
+
def test_json_serialization::TestTree::TestTreeNode#test_json_serialization1335,51613
|
233
|
+
def test_json_deserialization::TestTree::TestTreeNode#test_json_deserialization1359,52413
|
234
|
+
def test_json_roundtrip::TestTree::TestTreeNode#test_json_roundtrip1387,53599
|
235
|
+
def test_old_camelCase_method_names::TestTree::TestTreeNode#test_old_camelCase_method_names1403,54340
|
236
|
+
def test_integer_node_names::TestTree::TestTreeNode#test_integer_node_names1434,55408
|
237
|
+
def test_add_node_to_self_as_child::TestTree::TestTreeNode#test_add_node_to_self_as_child1465,56638
|
238
|
+
def test_single_node_becomes_leaf::TestTree::TestTreeNode#test_single_node_becomes_leaf1481,57151
|
239
|
+
def test_unique_node_names::TestTree::TestTreeNode#test_unique_node_names1493,57572
|
240
|
+
def setup_other_test_tree::TestTree::TestTreeNode#setup_other_test_tree1507,57927
|
241
|
+
def test_merge::TestTree::TestTreeNode#test_merge1535,58916
|
242
|
+
def test_merge_bang::TestTree::TestTreeNode#test_merge_bang1564,60354
|
data/TODO.org
CHANGED
@@ -186,8 +186,18 @@
|
|
186
186
|
|
187
187
|
|
188
188
|
|
189
|
+
* R0.9.5
|
190
|
+
** DONE Pull the =hash= converter code from [[https://github.com/markthomas/RubyTree/commits/master][Mark Thomas]] ([[Issue:13][Issue #13]]). :ARCHIVE:
|
191
|
+
CLOSED: [2014-11-01 Sat 20:10]
|
192
|
+
This was contributed by @jhamon.
|
193
|
+
** DONE Misc. bug fixes :ARCHIVE:
|
194
|
+
CLOSED: [2014-11-01 Sat 20:11]
|
195
|
+
|
196
|
+
|
197
|
+
|
198
|
+
|
189
199
|
* Next Release
|
190
|
-
DEADLINE: <2014-
|
200
|
+
DEADLINE: <2014-12-01 Mon>
|
191
201
|
** STARTED [#A] Resolve the infinite loop bug if a node is added to itself as a child :Partial:
|
192
202
|
[[Issue:5][Issue #5.]]
|
193
203
|
|
@@ -219,19 +229,15 @@
|
|
219
229
|
duplicates). This needs to be a hash (to allow O(1) access),
|
220
230
|
and will sacrifice memory. There might be a need to
|
221
231
|
restructure the internals to make better use of memory.
|
232
|
+
** STARTED Convert all documentation to markdown mode.
|
222
233
|
** TODO Expand the examples section, and add supporting documentation
|
223
|
-
** TODO Pull the =hash= converter code from [[https://github.com/markthomas/RubyTree/commits/master][Mark Thomas]] ([[Issue:13][Issue #13]]).
|
224
|
-
** TODO Convert all documentation to markdown mode.
|
225
|
-
|
226
|
-
|
227
234
|
* Unplanned / Not assigned to any release
|
228
|
-
*** DONE [#A] Migrate the website and references from http://rubyforge.org/
|
235
|
+
*** DONE [#A] Migrate the website and references from http://rubyforge.org/ :ARCHIVE:
|
229
236
|
CLOSED: [2014-07-04 Fri 22:18]
|
230
|
-
***
|
231
|
-
*** DONE Revert the forced install of rubygem 2.1.11 from [[file:.travis.yml][.travis.yml]]
|
237
|
+
*** DONE Revert the forced install of rubygem 2.1.11 from [[file:.travis.yml][.travis.yml]] :ARCHIVE:
|
232
238
|
CLOSED: [2014-01-12 Sun 19:06]
|
233
239
|
The issue seems to have been resolved with the 2.2.1 release of Rubygems.
|
234
|
-
|
240
|
+
*** TODO Create a cycle-detection/validation mechanism to prevent cyclic graphs of nodes.
|
235
241
|
*** TODO Create a generic validation method to check for various issues in the created tree.
|
236
242
|
*** TODO Add a FAQ document to the project.
|
237
243
|
*** TODO The semantic of length is probably unclear. Should return the node_depth instead (or remove the method)
|
data/lib/tree.rb
CHANGED
@@ -89,6 +89,7 @@ module Tree
|
|
89
89
|
include Tree::Utils::CamelCaseMethodHandler
|
90
90
|
include Tree::Utils::JSONConverter
|
91
91
|
include Tree::Utils::TreeMergeHandler
|
92
|
+
include Tree::Utils::HashConverter
|
92
93
|
|
93
94
|
# @!group Core Attributes
|
94
95
|
|
@@ -380,6 +381,31 @@ module Tree
|
|
380
381
|
|
381
382
|
private :insertion_range
|
382
383
|
|
384
|
+
|
385
|
+
# Replaces the specified child node with another child node on this node.
|
386
|
+
#
|
387
|
+
# @param [Tree::TreeNode] old_child The child node to be replaced.
|
388
|
+
# @param [Tree::TreeNode] new_child The child node to be replaced with.
|
389
|
+
#
|
390
|
+
# @return [Tree::TreeNode] The removed child node
|
391
|
+
def replace!(old_child, new_child)
|
392
|
+
child_index = @children.find_index(old_child)
|
393
|
+
|
394
|
+
old_child = remove! old_child
|
395
|
+
add new_child, child_index
|
396
|
+
|
397
|
+
return old_child
|
398
|
+
end
|
399
|
+
|
400
|
+
# Replaces the node with another node
|
401
|
+
#
|
402
|
+
# @param [Tree::TreeNode] node The node to replace this node with
|
403
|
+
#
|
404
|
+
# @return [Tree::TreeNode] The replaced child node
|
405
|
+
def replace_with(node)
|
406
|
+
@parent.replace!(self, node)
|
407
|
+
end
|
408
|
+
|
383
409
|
# Removes the specified child node from this node.
|
384
410
|
#
|
385
411
|
# This method can also be used for *pruning* a sub-tree, in cases where the removed child node is
|
@@ -560,7 +586,7 @@ module Tree
|
|
560
586
|
# @return [Tree::TreeNode] this node, if a block if given
|
561
587
|
# @return [Enumerator] an enumerator on this tree, if a block is *not* given
|
562
588
|
def postordered_each(&block)
|
563
|
-
return self.to_enum unless block_given?
|
589
|
+
return self.to_enum(:postordered_each) unless block_given?
|
564
590
|
|
565
591
|
# Using a marked node in order to skip adding the children of nodes that
|
566
592
|
# have already been visited. This allows the stack depth to be controlled,
|
@@ -596,7 +622,7 @@ module Tree
|
|
596
622
|
# @return [Tree::TreeNode] this node, if a block if given
|
597
623
|
# @return [Enumerator] an enumerator on this tree, if a block is *not* given
|
598
624
|
def breadth_each(&block)
|
599
|
-
return self.to_enum unless block_given?
|
625
|
+
return self.to_enum(:breadth_each) unless block_given?
|
600
626
|
|
601
627
|
node_queue = [self] # Create a queue with self as the initial entry
|
602
628
|
|
@@ -805,20 +831,26 @@ module Tree
|
|
805
831
|
# Pretty prints the (sub)tree rooted at this node.
|
806
832
|
#
|
807
833
|
# @param [Integer] level The indentation level (4 spaces) to start with.
|
808
|
-
|
834
|
+
# @param [Integer] max_depth optional maximum depth at which the printing with stop.
|
835
|
+
# @param [Proc] block optional block to use for rendering
|
836
|
+
def print_tree(level = 0, max_depth = nil, block = lambda { |node, prefix| puts "#{prefix} #{node.name}" })
|
837
|
+
prefix = ''
|
838
|
+
|
809
839
|
if is_root?
|
810
|
-
|
840
|
+
prefix << '*'
|
811
841
|
else
|
812
|
-
|
813
|
-
|
814
|
-
|
815
|
-
|
816
|
-
|
842
|
+
prefix << '|' unless parent.is_last_sibling?
|
843
|
+
prefix << (' ' * (level - 1) * 4)
|
844
|
+
prefix << (is_last_sibling? ? '+' : '|')
|
845
|
+
prefix << '---'
|
846
|
+
prefix << (has_children? ? '+' : '>')
|
817
847
|
end
|
818
848
|
|
819
|
-
|
849
|
+
block.call(self, prefix)
|
850
|
+
|
851
|
+
return unless max_depth.nil? || level < max_depth # Exit if the max level is defined, and reached.
|
820
852
|
|
821
|
-
children { |child| child.print_tree(level + 1) if child } # Child might be 'nil'
|
853
|
+
children { |child| child.print_tree(level + 1, max_depth, block) if child } # Child might be 'nil'
|
822
854
|
end
|
823
855
|
|
824
856
|
end
|
data/lib/tree/binarytree.rb
CHANGED
@@ -8,7 +8,7 @@
|
|
8
8
|
# Author:: Anupam Sengupta (anupamsg@gmail.com)
|
9
9
|
#
|
10
10
|
|
11
|
-
# Copyright (c) 2007, 2008, 2009, 2010, 2012, 2013 Anupam Sengupta
|
11
|
+
# Copyright (c) 2007, 2008, 2009, 2010, 2012, 2013, 2014 Anupam Sengupta
|
12
12
|
#
|
13
13
|
# All rights reserved.
|
14
14
|
#
|
@@ -113,6 +113,38 @@ module Tree
|
|
113
113
|
super(child)
|
114
114
|
end
|
115
115
|
|
116
|
+
|
117
|
+
# Instantiate and insert child nodes from data in a Ruby +Hash+
|
118
|
+
#
|
119
|
+
# This method is used in conjunction with {Tree::TreeNode.from_hash} to
|
120
|
+
# provide a convenient way of building and inserting child nodes present
|
121
|
+
# in a Ruby hashes.
|
122
|
+
#
|
123
|
+
# This method will instantiate a {Tree::TreeNode} instance for each top-
|
124
|
+
# level key of the input hash, to be inserted as children of the receiver
|
125
|
+
# instance.
|
126
|
+
#
|
127
|
+
# Nested hashes are expected and further child nodes will be created and
|
128
|
+
# added accordingly. If a hash key is a single value that value will be
|
129
|
+
# used as the name for the node. If a hash key is an Array, both node
|
130
|
+
# name and content will be populated.
|
131
|
+
#
|
132
|
+
# A leaf element of the tree should be represented as a hash key with
|
133
|
+
# corresponding value nil or {}.
|
134
|
+
#
|
135
|
+
# @example
|
136
|
+
# root = Tree::TreeNode.new(:A, "Root content!")
|
137
|
+
# root.add_from_hash({:B => {:D => {}}, [:C, "C content!"] => {}})
|
138
|
+
#
|
139
|
+
# @param [Hash] hashed_subtree The hash of child subtrees.
|
140
|
+
# @raise [ArgumentError] This exception is raised if hash contains too many children.
|
141
|
+
# @raise [ArgumentError] This exception is raised if a non-hash is passed.
|
142
|
+
# @return [Array] Array of child nodes added
|
143
|
+
def add_from_hash(hashed_subtree)
|
144
|
+
raise ArgumentError, "Too many children" if hashed_subtree.size + @children.size > 2
|
145
|
+
super(hashed_subtree)
|
146
|
+
end
|
147
|
+
|
116
148
|
# Performs inorder traversal (including this node).
|
117
149
|
#
|
118
150
|
# @yieldparam node [Tree::BinaryTreeNode] Each node (in-order).
|
data/lib/tree/tree_deps.rb
CHANGED
@@ -0,0 +1,161 @@
|
|
1
|
+
# hash_converter.rb - This file is part of the RubyTree package.
|
2
|
+
#
|
3
|
+
# = hash_converter.rb - Provides utility methods for converting between
|
4
|
+
# {Tree::TreeNode} and Ruby's native +Hash+.
|
5
|
+
#
|
6
|
+
# Author:: Jen Hamon (http://www.github.com/jhamon)
|
7
|
+
#
|
8
|
+
# Time-stamp: <2014-10-25 16:20:23 anupam>
|
9
|
+
#
|
10
|
+
# Copyright (C) 2014 Jen Hamon (http://www.github.com/jhamon) and
|
11
|
+
# Anupam Sengupta <anupamsg@gmail.com>
|
12
|
+
#
|
13
|
+
# All rights reserved.
|
14
|
+
#
|
15
|
+
# Redistribution and use in source and binary forms, with or without modification,
|
16
|
+
# are permitted provided that the following conditions are met:
|
17
|
+
#
|
18
|
+
# - Redistributions of source code must retain the above copyright notice, this
|
19
|
+
# list of conditions and the following disclaimer.
|
20
|
+
#
|
21
|
+
# - Redistributions in binary form must reproduce the above copyright notice, this
|
22
|
+
# list of conditions and the following disclaimer in the documentation and/or
|
23
|
+
# other materials provided with the distribution.
|
24
|
+
#
|
25
|
+
# - Neither the name of the organization nor the names of its contributors may
|
26
|
+
# be used to endorse or promote products derived from this software without
|
27
|
+
# specific prior written permission.
|
28
|
+
#
|
29
|
+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
30
|
+
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
31
|
+
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
32
|
+
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
33
|
+
# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
34
|
+
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
35
|
+
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
36
|
+
# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
37
|
+
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
38
|
+
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
39
|
+
|
40
|
+
module Tree::Utils::HashConverter
|
41
|
+
|
42
|
+
def self.included(base)
|
43
|
+
base.extend(ClassMethods)
|
44
|
+
end
|
45
|
+
|
46
|
+
# Methods in {Tree::Utils::HashConverter::ClassMethods} will be added as
|
47
|
+
# class methods on any class mixing in the {Tree::Utils::HashConverter}
|
48
|
+
# module.
|
49
|
+
module ClassMethods
|
50
|
+
|
51
|
+
# Factory method builds a {Tree::TreeNode} from a +Hash+.
|
52
|
+
#
|
53
|
+
# This method will interpret each key of your +Hash+ as a {Tree::TreeNode}.
|
54
|
+
# Nested hashes are expected and child nodes will be added accordingly. If
|
55
|
+
# a hash key is a single value that value will be used as the name for the
|
56
|
+
# node. If a hash key is an Array, both node name and content will be
|
57
|
+
# populated.
|
58
|
+
#
|
59
|
+
# A leaf element of the tree should be represented as a hash key with
|
60
|
+
# corresponding value +nil+ or +{}+.
|
61
|
+
#
|
62
|
+
# @example
|
63
|
+
# TreeNode.from_hash({:A => {:B => {}, :C => {:D => {}, :E => {}}}})
|
64
|
+
# # would be parsed into the following tree structure:
|
65
|
+
# # A
|
66
|
+
# # / \
|
67
|
+
# # B C
|
68
|
+
# # / \
|
69
|
+
# # D E
|
70
|
+
#
|
71
|
+
# # The same tree would result from this nil-terminated Hash
|
72
|
+
# {:A => {:B => nil, :C => {:D => nil, :E => nil}}}
|
73
|
+
#
|
74
|
+
# # A tree with equivalent structure but with content present for
|
75
|
+
# # nodes A and D could be built from a hash like this:
|
76
|
+
# {[:A, "A content"] => {:B => {}, :C => {[:D, "D content"] => {}, :E => {}}}}
|
77
|
+
#
|
78
|
+
# @author Jen Hamon (http://www.github.com/jhamon)
|
79
|
+
# @param [Hash] hash Hash to build tree from.
|
80
|
+
# @return [Tree::TreeNode] The {Tree::TreeNode} instance representing the root of your tree.
|
81
|
+
#
|
82
|
+
# @raise [ArgumentError] This exception is raised if a non-Hash is passed.
|
83
|
+
# @raise [ArgumentError] This exception is raised if the hash has multiple top-level elements.
|
84
|
+
# @raise [ArgumentError] This exception is raised if the hash contains values that are not hashes or nils.
|
85
|
+
|
86
|
+
def from_hash(hash)
|
87
|
+
raise ArgumentError, "Argument must be a type of hash" unless hash.is_a?(Hash)
|
88
|
+
raise ArgumentError, "Hash must have one top-level element" if hash.size != 1
|
89
|
+
|
90
|
+
root, children = hash.first
|
91
|
+
|
92
|
+
unless [Hash, NilClass].include?(children.class)
|
93
|
+
raise ArgumentError, "Invalid child. Must be nil or hash."
|
94
|
+
end
|
95
|
+
|
96
|
+
node = self.new(*root)
|
97
|
+
node.add_from_hash(children) unless children.nil?
|
98
|
+
node
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
# Instantiate and insert child nodes from data in a Ruby +Hash+
|
103
|
+
#
|
104
|
+
# This method is used in conjunction with from_hash to provide a
|
105
|
+
# convenient way of building and inserting child nodes present in a Ruby
|
106
|
+
# hashes.
|
107
|
+
#
|
108
|
+
# This method will instantiate a node instance for each top-
|
109
|
+
# level key of the input hash, to be inserted as children of the receiver
|
110
|
+
# instance.
|
111
|
+
#
|
112
|
+
# Nested hashes are expected and further child nodes will be created and
|
113
|
+
# added accordingly. If a hash key is a single value that value will be
|
114
|
+
# used as the name for the node. If a hash key is an Array, both node
|
115
|
+
# name and content will be populated.
|
116
|
+
#
|
117
|
+
# A leaf element of the tree should be represented as a hash key with
|
118
|
+
# corresponding value +nil+ or {}.
|
119
|
+
#
|
120
|
+
# @example
|
121
|
+
# root = Tree::TreeNode.new(:A, "Root content!")
|
122
|
+
# root.add_from_hash({:B => {:D => {}}, [:C, "C content!"] => {}})
|
123
|
+
#
|
124
|
+
# @author Jen Hamon (http://www.github.com/jhamon)
|
125
|
+
# @param [Hash] children The hash of child subtrees.
|
126
|
+
# @raise [ArgumentError] This exception is raised if a non-hash is passed.
|
127
|
+
# @return [Array] Array of child nodes added
|
128
|
+
# @see ClassMethods#from_hash
|
129
|
+
def add_from_hash(children)
|
130
|
+
raise ArgumentError, "Argument must be a type of hash" unless children.is_a?(Hash)
|
131
|
+
|
132
|
+
child_nodes = []
|
133
|
+
children.each do |child, grandchildren|
|
134
|
+
child_node = self.class.from_hash({child => grandchildren})
|
135
|
+
child_nodes << child_node
|
136
|
+
self << child_node
|
137
|
+
end
|
138
|
+
|
139
|
+
child_nodes
|
140
|
+
end
|
141
|
+
|
142
|
+
# Convert a node and its subtree into a Ruby hash.
|
143
|
+
#
|
144
|
+
# @example
|
145
|
+
# root = Tree::TreeNode.new(:root, "root content")
|
146
|
+
# root << Tree::TreeNode.new(:child1, "child1 content")
|
147
|
+
# root << Tree::TreeNode.new(:child2, "child2 content")
|
148
|
+
# root.to_h # => {[:root, "root content"] => { [:child1, "child1 content"] => {}, [:child2, "child2 content"] => {}}}
|
149
|
+
# @author Jen Hamon (http://www.github.com/jhamon)
|
150
|
+
# @return [Hash] Hash representation of tree.
|
151
|
+
def to_h
|
152
|
+
key = has_content? ? [name, content] : name
|
153
|
+
|
154
|
+
children_hash = {}
|
155
|
+
children do |child|
|
156
|
+
children_hash.merge! child.to_h
|
157
|
+
end
|
158
|
+
|
159
|
+
{ key => children_hash }
|
160
|
+
end
|
161
|
+
end
|
@@ -1,12 +1,12 @@
|
|
1
|
-
#
|
1
|
+
# json_converter.rb - This file is part of the RubyTree package.
|
2
2
|
#
|
3
|
-
# =
|
3
|
+
# = json_converter.rb - Provides conversion to and from JSON.
|
4
4
|
#
|
5
5
|
# Author:: Anupam Sengupta (anupamsg@gmail.com)
|
6
6
|
#
|
7
|
-
# Time-stamp: <
|
7
|
+
# Time-stamp: <2014-10-25 16:16:23 anupam>
|
8
8
|
#
|
9
|
-
# Copyright (C) 2012, 2013 Anupam Sengupta <anupamsg@gmail.com>
|
9
|
+
# Copyright (C) 2012, 2013, 2014 Anupam Sengupta <anupamsg@gmail.com>
|
10
10
|
#
|
11
11
|
# All rights reserved.
|
12
12
|
#
|
data/lib/tree/version.rb
CHANGED
data/test/test_binarytree.rb
CHANGED
@@ -63,6 +63,73 @@ module TestTree
|
|
63
63
|
assert_equal(@root.children.size, 0, "Initially no children should be present")
|
64
64
|
end
|
65
65
|
|
66
|
+
def test_from_hash
|
67
|
+
# Can make a root note without a name
|
68
|
+
assert_raise (ArgumentError) { Tree::BinaryTreeNode.from_hash({})}
|
69
|
+
# Can't have multiple roots
|
70
|
+
assert_raise (ArgumentError) { Tree::BinaryTreeNode.from_hash({:A => {}, :B => {}}) }
|
71
|
+
|
72
|
+
# Can't have more than 2 children
|
73
|
+
too_many_kids = {:A => {:B => {}, :C => {}, :D => {} } }
|
74
|
+
assert_raise(ArgumentError) { Tree::BinaryTreeNode.from_hash(too_many_kids) }
|
75
|
+
|
76
|
+
valid_hash = {:A => {:B => {}, :C => { :D => {} } } }
|
77
|
+
tree = Tree::BinaryTreeNode.from_hash(valid_hash)
|
78
|
+
# A
|
79
|
+
# / \
|
80
|
+
# B C
|
81
|
+
# |
|
82
|
+
# D
|
83
|
+
|
84
|
+
assert_same(tree.class, Tree::BinaryTreeNode)
|
85
|
+
assert_same(tree.name, :A)
|
86
|
+
assert_equal(tree.is_root?, true)
|
87
|
+
assert_equal(tree.is_leaf?, false)
|
88
|
+
assert_equal(tree.children.count, 2) # B, C, D
|
89
|
+
assert_equal(tree.size, 4)
|
90
|
+
assert_equal(tree.left_child.name, :B)
|
91
|
+
assert_equal(tree.right_child.name, :C)
|
92
|
+
|
93
|
+
valid_hash_with_content = {[:A, "Content!"] => {:B => {}, :C => { [:D, "More content"] => {} } } }
|
94
|
+
tree2 = Tree::BinaryTreeNode.from_hash(valid_hash_with_content)
|
95
|
+
|
96
|
+
assert_equal(tree2.class, Tree::BinaryTreeNode)
|
97
|
+
assert_equal(tree2.content, "Content!" )
|
98
|
+
assert_equal(tree2[:C][:D].content, "More content")
|
99
|
+
end
|
100
|
+
|
101
|
+
def test_add_from_hash
|
102
|
+
root = Tree::BinaryTreeNode.new("Root")
|
103
|
+
|
104
|
+
# Can't have too many children
|
105
|
+
too_many_kids = {:child1 => {}, :child2 => {}, :child3 => {}}
|
106
|
+
assert_raise(ArgumentError) { root.add_from_hash(too_many_kids) }
|
107
|
+
assert_equal(root.children.count, 0) # Nothing added
|
108
|
+
|
109
|
+
# Well behaved when adding nothing
|
110
|
+
assert_equal(root.add_from_hash({}), [])
|
111
|
+
assert_equal(root.size, 1)
|
112
|
+
|
113
|
+
valid_hash = {:A => {}, :B => { :C => {}, [:D, "leaf"] => {} } }
|
114
|
+
added = root.add_from_hash(valid_hash)
|
115
|
+
# root
|
116
|
+
# / \
|
117
|
+
# A B
|
118
|
+
# / \
|
119
|
+
# C D
|
120
|
+
|
121
|
+
assert_equal(added.class, Array)
|
122
|
+
assert_equal(added.count, 2)
|
123
|
+
assert_equal(root.size, 5)
|
124
|
+
assert_equal(root.children.count, 2)
|
125
|
+
assert_equal(root[:B][:D].content, "leaf")
|
126
|
+
|
127
|
+
# Can't add more than two children
|
128
|
+
assert_raise(ArgumentError) { root.add_from_hash({:X => {}}) }
|
129
|
+
node = Tree::BinaryTreeNode.new("Root 2")
|
130
|
+
assert_raise(ArgumentError) { node.add_from_hash({:A => {}, :B => {}, :C => {}}) }
|
131
|
+
end
|
132
|
+
|
66
133
|
# Test the add method.
|
67
134
|
def test_add
|
68
135
|
@root.add @left_child1
|
data/test/test_tree.rb
CHANGED
@@ -120,6 +120,177 @@ module TestTree
|
|
120
120
|
assert_equal(2 , @root.node_height, "Root's height after adding the children should be 2")
|
121
121
|
end
|
122
122
|
|
123
|
+
def test_from_hash
|
124
|
+
# A
|
125
|
+
# / | \
|
126
|
+
# B C D
|
127
|
+
# / \ /
|
128
|
+
# E F G
|
129
|
+
# / \
|
130
|
+
# H I
|
131
|
+
|
132
|
+
hash = {[:A, "Root content"] => {
|
133
|
+
:B => {
|
134
|
+
:E => {},
|
135
|
+
:F => {
|
136
|
+
:H => {},
|
137
|
+
[:I, "Leaf content"] => {}
|
138
|
+
}
|
139
|
+
},
|
140
|
+
:C => {},
|
141
|
+
:D => {
|
142
|
+
:G => {}
|
143
|
+
}
|
144
|
+
}
|
145
|
+
}
|
146
|
+
|
147
|
+
tree = Tree::TreeNode.from_hash(hash)
|
148
|
+
|
149
|
+
assert_same(tree.class, Tree::TreeNode)
|
150
|
+
assert_same(tree.name, :A)
|
151
|
+
assert_equal(tree.is_root?, true)
|
152
|
+
assert_equal(tree.is_leaf?, false)
|
153
|
+
assert_equal(tree.size, 9)
|
154
|
+
assert_equal(tree.content, "Root content")
|
155
|
+
assert_equal(tree.children.count, 3) # B, C, D
|
156
|
+
|
157
|
+
leaf_with_content = tree[:B][:F][:I]
|
158
|
+
assert_equal(leaf_with_content.content, "Leaf content")
|
159
|
+
assert_equal(leaf_with_content.is_leaf?, true)
|
160
|
+
|
161
|
+
leaf_without_content = tree[:C]
|
162
|
+
assert_equal(leaf_without_content.is_leaf?, true)
|
163
|
+
|
164
|
+
interior_node = tree[:B][:F]
|
165
|
+
assert_equal(interior_node.is_leaf?, false)
|
166
|
+
assert_equal(interior_node.children.count, 2)
|
167
|
+
|
168
|
+
# Can't make a node without a name
|
169
|
+
assert_raise (ArgumentError) { Tree::TreeNode.from_hash({}) }
|
170
|
+
# Can't have multiple roots
|
171
|
+
assert_raise (ArgumentError) { Tree::TreeNode.from_hash({:A => {}, :B => {}}) }
|
172
|
+
|
173
|
+
end
|
174
|
+
|
175
|
+
def test_from_hash_with_nils
|
176
|
+
# A
|
177
|
+
# / | \
|
178
|
+
# B C D
|
179
|
+
# / \ /
|
180
|
+
# E F G
|
181
|
+
# / \
|
182
|
+
# H I
|
183
|
+
|
184
|
+
hash = {[:A, "Root content"] => {
|
185
|
+
:B => {
|
186
|
+
:E => nil,
|
187
|
+
:F => {
|
188
|
+
:H => nil,
|
189
|
+
[:I, "Leaf content"] => nil
|
190
|
+
}
|
191
|
+
},
|
192
|
+
:C => nil,
|
193
|
+
:D => {
|
194
|
+
:G => nil
|
195
|
+
}
|
196
|
+
}
|
197
|
+
}
|
198
|
+
|
199
|
+
tree = Tree::TreeNode.from_hash(hash)
|
200
|
+
|
201
|
+
assert_same(tree.class, Tree::TreeNode)
|
202
|
+
assert_same(tree.name, :A)
|
203
|
+
assert_equal(tree.is_root?, true)
|
204
|
+
assert_equal(tree.is_leaf?, false)
|
205
|
+
assert_equal(tree.size, 9)
|
206
|
+
assert_equal(tree.content, "Root content")
|
207
|
+
assert_equal(tree.children.count, 3) # B, C, D
|
208
|
+
|
209
|
+
leaf_with_content = tree[:B][:F][:I]
|
210
|
+
assert_equal(leaf_with_content.content, "Leaf content")
|
211
|
+
assert_equal(leaf_with_content.is_leaf?, true)
|
212
|
+
|
213
|
+
leaf_without_content = tree[:C]
|
214
|
+
assert_equal(leaf_without_content.is_leaf?, true)
|
215
|
+
|
216
|
+
interior_node = tree[:B][:F]
|
217
|
+
assert_equal(interior_node.is_leaf?, false)
|
218
|
+
assert_equal(interior_node.children.count, 2)
|
219
|
+
end
|
220
|
+
|
221
|
+
def test_add_from_hash
|
222
|
+
tree = Tree::TreeNode.new(:A)
|
223
|
+
|
224
|
+
# Doesn't blow up when added an empty hash
|
225
|
+
hash = {}
|
226
|
+
assert_equal(tree.add_from_hash(hash), [])
|
227
|
+
|
228
|
+
# Okay, now try a real hash
|
229
|
+
hash = {:B => {:C => {:D => nil}, :E => {}, :F => {}}, [:G, "G content"] => {}}
|
230
|
+
# A
|
231
|
+
# / \
|
232
|
+
# B G
|
233
|
+
# /|\
|
234
|
+
# C E F
|
235
|
+
# |
|
236
|
+
# D
|
237
|
+
|
238
|
+
added_children = tree.add_from_hash(hash)
|
239
|
+
assert_equal(added_children.class, Array)
|
240
|
+
assert_equal(added_children.count, 2)
|
241
|
+
assert_equal(tree.size, 7)
|
242
|
+
assert_equal(tree[:G].content, "G content")
|
243
|
+
assert_equal(tree[:G].is_leaf?, true)
|
244
|
+
assert_equal(tree[:B].size, 5)
|
245
|
+
assert_equal(tree[:B].children.count, 3)
|
246
|
+
|
247
|
+
assert_raise (ArgumentError) { tree.add_from_hash([]) }
|
248
|
+
assert_raise (ArgumentError) { tree.add_from_hash("not a hash") }
|
249
|
+
assert_raise (ArgumentError) { tree.add_from_hash({:X => "Not a hash or nil"}) }
|
250
|
+
end
|
251
|
+
|
252
|
+
# Test exporting to ruby Hash
|
253
|
+
def test_to_h
|
254
|
+
a = Tree::TreeNode.new(:A)
|
255
|
+
b = Tree::TreeNode.new(:B)
|
256
|
+
c = Tree::TreeNode.new(:C)
|
257
|
+
d = Tree::TreeNode.new(:D)
|
258
|
+
e = Tree::TreeNode.new(:E)
|
259
|
+
f = Tree::TreeNode.new(:F)
|
260
|
+
g = Tree::TreeNode.new(:G)
|
261
|
+
# A
|
262
|
+
# / \
|
263
|
+
# B C
|
264
|
+
# | / \
|
265
|
+
# E F G
|
266
|
+
|
267
|
+
a << b
|
268
|
+
a << c
|
269
|
+
c << f
|
270
|
+
c << g
|
271
|
+
b << e
|
272
|
+
|
273
|
+
exported = a.to_h
|
274
|
+
expected = {:A => {:B => {:E => {}}, :C => {:F => {}, :G => {}}}}
|
275
|
+
assert_equal(exported, expected)
|
276
|
+
end
|
277
|
+
|
278
|
+
# Test that from_hash and to_h are symmetric
|
279
|
+
def test_to_h_from_hash_symmetry
|
280
|
+
# A
|
281
|
+
# / \
|
282
|
+
# B C
|
283
|
+
# /|\ \
|
284
|
+
# E F G H
|
285
|
+
# |\ |
|
286
|
+
# I J K
|
287
|
+
|
288
|
+
input = {:A => {:B => {:E => {:I => {}, :J =>{}}, :F => {}, :G => {}}, :C =>{:H => {:K => {}}}}}
|
289
|
+
|
290
|
+
node = Tree::TreeNode.from_hash(input)
|
291
|
+
assert_equal(node.to_h, input)
|
292
|
+
end
|
293
|
+
|
123
294
|
# Test the presence of content in the nodes.
|
124
295
|
def test_has_content_eh
|
125
296
|
a_node = Tree::TreeNode.new("A Node")
|
@@ -448,6 +619,48 @@ module TestTree
|
|
448
619
|
assert_equal(5, @root.children.size, "Should have five child nodes")
|
449
620
|
end
|
450
621
|
|
622
|
+
# Test the replace! and replace_with! methods
|
623
|
+
def test_replace_bang
|
624
|
+
@root << @child1
|
625
|
+
@root << @child2
|
626
|
+
@root << @child3
|
627
|
+
|
628
|
+
assert_equal(4, @root.size, "Should have four nodes")
|
629
|
+
assert(@root.children.include?(@child1), "Should parent child1")
|
630
|
+
assert(@root.children.include?(@child2), "Should parent child2")
|
631
|
+
assert(@root.children.include?(@child3), "Should parent child3")
|
632
|
+
assert(!@root.children.include?(@child4), "Should not parent child4")
|
633
|
+
|
634
|
+
@root.replace!(@child2, @child4)
|
635
|
+
|
636
|
+
# Also test replacing with a node of the same name
|
637
|
+
@root.replace! @child4, @child4.detached_copy
|
638
|
+
|
639
|
+
assert_equal(4, @root.size, "Should have three nodes")
|
640
|
+
assert(@root.children.include?(@child1), "Should parent child1")
|
641
|
+
assert(!@root.children.include?(@child2), "Should not parent child2")
|
642
|
+
assert(@root.children.include?(@child3), "Should parent child3")
|
643
|
+
assert(@root.children.include?(@child4), "Should parent child4")
|
644
|
+
assert_equal(1, @root.children.find_index(@child4), "Should add child4 to index 1")
|
645
|
+
end
|
646
|
+
|
647
|
+
def test_replace_with
|
648
|
+
@root << @child1
|
649
|
+
@root << @child2
|
650
|
+
|
651
|
+
assert_equal(3, @root.size, "Should have three nodes")
|
652
|
+
assert(@root.children.include?(@child1), "Should parent child1")
|
653
|
+
assert(@root.children.include?(@child2), "Should parent child2")
|
654
|
+
assert(!@root.children.include?(@child3), "Should not parent child3")
|
655
|
+
|
656
|
+
@child2.replace_with @child3
|
657
|
+
|
658
|
+
assert_equal(3, @root.size, "Should have three nodes")
|
659
|
+
assert(@root.children.include?(@child1), "Should parent child1")
|
660
|
+
assert(!@root.children.include?(@child2), "Should not parent child2")
|
661
|
+
assert(@root.children.include?(@child3), "Should parent child3")
|
662
|
+
end
|
663
|
+
|
451
664
|
# Test the remove! and remove_all! methods.
|
452
665
|
def test_remove_bang
|
453
666
|
@root << @child1
|
@@ -868,17 +1081,25 @@ module TestTree
|
|
868
1081
|
f << h
|
869
1082
|
j << k << z
|
870
1083
|
|
871
|
-
#
|
872
|
-
result_array =
|
1084
|
+
# Test when a block is given
|
1085
|
+
result_array = []
|
873
1086
|
result = j.breadth_each { |node| result_array << node.detached_copy }
|
874
1087
|
|
875
|
-
assert_equal(j, result)
|
1088
|
+
assert_equal(j, result) # The invocation target is returned
|
1089
|
+
|
1090
|
+
expected_array.each_index do |i|
|
1091
|
+
assert_equal(expected_array[i].name, result_array[i].name) # Match only the names.
|
1092
|
+
end
|
1093
|
+
|
1094
|
+
assert_equal(Enumerator, j.breadth_each.class) if defined?(Enumerator.class ) # Without a block
|
1095
|
+
assert_equal(Enumerable::Enumerator, j.breadth_each.class) if defined?(Enumerable::Enumerator.class) # Without a block
|
1096
|
+
|
1097
|
+
# Now test without a block
|
1098
|
+
result_array = j.breadth_each.collect { |node| node}
|
876
1099
|
expected_array.each_index do |i|
|
877
1100
|
assert_equal(expected_array[i].name, result_array[i].name) # Match only the names.
|
878
1101
|
end
|
879
1102
|
|
880
|
-
assert_equal(Enumerator, j.breadth_each.class) if defined?(Enumerator.class )# Without a block
|
881
|
-
assert_equal(Enumerable::Enumerator, j.breadth_each.class) if defined?(Enumerable::Enumerator.class )# Without a block
|
882
1103
|
end
|
883
1104
|
|
884
1105
|
# Test the preordered_each method.
|
@@ -945,18 +1166,28 @@ module TestTree
|
|
945
1166
|
f << h
|
946
1167
|
j << k << z
|
947
1168
|
|
1169
|
+
# Test when a block is given
|
948
1170
|
result_array = []
|
949
1171
|
result = j.postordered_each { |node| result_array << node.detached_copy}
|
950
1172
|
|
951
|
-
assert_equal(j, result) #
|
1173
|
+
assert_equal(j, result) # The invocation target is returned
|
1174
|
+
|
1175
|
+
expected_array.each_index do |i|
|
1176
|
+
# Match only the names.
|
1177
|
+
assert_equal(expected_array[i].name, result_array[i].name)
|
1178
|
+
end
|
1179
|
+
|
1180
|
+
assert_equal(Enumerator, j.postordered_each.class) if defined?(Enumerator.class) # Without a block
|
1181
|
+
assert_equal(Enumerable::Enumerator, j.postordered_each.class) if defined?(Enumerable::Enumerator.class) # Without a block
|
1182
|
+
|
1183
|
+
# Now test without a block
|
1184
|
+
result_array = j.postordered_each.collect { |node| node }
|
952
1185
|
|
953
1186
|
expected_array.each_index do |i|
|
954
1187
|
# Match only the names.
|
955
1188
|
assert_equal(expected_array[i].name, result_array[i].name)
|
956
1189
|
end
|
957
1190
|
|
958
|
-
assert_equal(Enumerator, j.postordered_each.class) if defined?(Enumerator.class )# Without a block
|
959
|
-
assert_equal(Enumerable::Enumerator, j.postordered_each.class) if defined?(Enumerable::Enumerator.class )# Without a block
|
960
1191
|
end
|
961
1192
|
|
962
1193
|
# test the detached_copy method.
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rubytree
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.9.
|
4
|
+
version: 0.9.5pre
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Anupam Sengupta
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-01
|
11
|
+
date: 2014-11-01 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: structured_warnings
|
@@ -136,6 +136,7 @@ files:
|
|
136
136
|
- LICENSE.md
|
137
137
|
- README.md
|
138
138
|
- Rakefile
|
139
|
+
- TAGS
|
139
140
|
- TODO.org
|
140
141
|
- examples/example_basic.rb
|
141
142
|
- lib/rubytree.rb
|
@@ -143,6 +144,7 @@ files:
|
|
143
144
|
- lib/tree/binarytree.rb
|
144
145
|
- lib/tree/tree_deps.rb
|
145
146
|
- lib/tree/utils/camel_case_method_handler.rb
|
147
|
+
- lib/tree/utils/hash_converter.rb
|
146
148
|
- lib/tree/utils/json_converter.rb
|
147
149
|
- lib/tree/utils/metrics_methods.rb
|
148
150
|
- lib/tree/utils/tree_merge_handler.rb
|
@@ -179,12 +181,12 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
179
181
|
version: 1.8.7
|
180
182
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
181
183
|
requirements:
|
182
|
-
- - "
|
184
|
+
- - ">"
|
183
185
|
- !ruby/object:Gem::Version
|
184
|
-
version:
|
186
|
+
version: 1.3.1
|
185
187
|
requirements: []
|
186
188
|
rubyforge_project:
|
187
|
-
rubygems_version: 2.2.
|
189
|
+
rubygems_version: 2.2.2
|
188
190
|
signing_key:
|
189
191
|
specification_version: 4
|
190
192
|
summary: A generic tree data structure.
|