rooted_tree 0.2.3 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 70e0e394dca29c945f79679ac2ade085f9210412
4
- data.tar.gz: d8e06827ee6b284d2cc39140229125b5f0232428
3
+ metadata.gz: dfa5843433eb9461adb4ab0e2698e0429d994263
4
+ data.tar.gz: ef4f2f8a52ee1aa796e435cb767ab96dc7b563b7
5
5
  SHA512:
6
- metadata.gz: 2b63502165e12f8d0ff158f07c2d2c010485f85f227ffbe05b1f73cc541907601c8a642816e568b8575a6cb7f7b2f4b41d901e5ffafe926a34b855077ea1764b
7
- data.tar.gz: 29c29640e1f5e18812f994a76646e91e15b7e0bc5df125056707901e197a97455d5442cb6e19ff758221fc361663646d50a69b9d64331db5a836e51136c96346
6
+ metadata.gz: cd771695cade59e40219f65827246e54534158e3d5612e8555c829b4293dafb01f2a60805cb2c36af6a8a80c1c70f5b96f7c2a616cb8af02cb568acb23e68f9e
7
+ data.tar.gz: d29de94468510ee7f2a52c2658a08e6ee8a8973d61cc1f3c6cc819f8f3751768d99fcaaae0315bc49ffe76dbcfe4b1a1e1ff41c138c798399ba0543e9f856252
data/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # RootedTree
2
2
 
3
- [![Gem Version](https://badge.fury.io/rb/richtext.png)](http://badge.fury.io/rb/rooted_tree)
3
+ [![Gem Version](https://badge.fury.io/rb/rooted_tree.png)](http://badge.fury.io/rb/rooted_tree)
4
4
  [![Build Status](https://travis-ci.org/seblindberg/ruby-rooted_tree.svg?branch=master)](https://travis-ci.org/seblindberg/ruby-rooted_tree)
5
5
  [![Coverage Status](https://coveralls.io/repos/github/seblindberg/ruby-rooted_tree/badge.svg?branch=master)](https://coveralls.io/github/seblindberg/ruby-rooted_tree?branch=master)
6
6
  [![Inline docs](http://inch-ci.org/github/seblindberg/ruby-rooted_tree.svg?branch=master)](http://inch-ci.org/github/seblindberg/ruby-rooted_tree)
@@ -61,16 +61,12 @@ module RootedTree
61
61
  super
62
62
  end
63
63
 
64
- # Leaf?
65
- #
66
- # A node is a leaf if it has no children.
64
+ # Returns true if this node is a leaf. A leaf is a node with no children.
67
65
 
68
66
  def leaf?
69
67
  @degree == 0
70
68
  end
71
69
 
72
- # Internal?
73
- #
74
70
  # Returns true if the node is internal, which is equivalent to it having
75
71
  # children.
76
72
 
@@ -78,17 +74,13 @@ module RootedTree
78
74
  !leaf?
79
75
  end
80
76
 
81
- # Root?
82
- #
83
- # Returns true if node has no parent.
77
+ # Returns true if the node has no parent.
84
78
 
85
79
  def root?
86
80
  @parent.nil?
87
81
  end
88
82
 
89
- # Root
90
- #
91
- # Returns the root of the tree.
83
+ # Returns the root of the tree structure that the node is part of.
92
84
 
93
85
  def root
94
86
  return self if root?
@@ -98,24 +90,18 @@ module RootedTree
98
90
  node
99
91
  end
100
92
 
101
- # First?
102
- #
103
93
  # Returns true if this node is the first of its siblings.
104
94
 
105
95
  def first?
106
96
  @prev.nil?
107
97
  end
108
98
 
109
- # Last?
110
- #
111
99
  # Returns true if this node is the last of its siblings.
112
100
 
113
101
  def last?
114
102
  @next.nil?
115
103
  end
116
104
 
117
- # Depth
118
- #
119
105
  # Returns the depth of the node within the tree
120
106
 
121
107
  def depth
@@ -124,8 +110,6 @@ module RootedTree
124
110
 
125
111
  alias level depth
126
112
 
127
- # Max Depth
128
- #
129
113
  # Returns the maximum node depth under this node.
130
114
 
131
115
  def max_depth(offset = depth)
@@ -134,36 +118,34 @@ module RootedTree
134
118
  children.map { |c| c.max_depth offset + 1 }.max
135
119
  end
136
120
 
137
- # Max Degree
138
- #
139
121
  # Returns the highest child count of the nodes in the subtree.
140
122
 
141
123
  def max_degree
142
124
  children.map(&:degree).push(degree).max
143
125
  end
144
126
 
145
- # Size
146
- #
147
127
  # Calculate the size in vertecies of the subtree.
128
+ #
129
+ # Returns the number of nodes under this node, including self.
148
130
 
149
131
  def size
150
132
  children.reduce(1) { |a, e| a + e.size }
151
133
  end
152
134
 
153
- # Next
154
- #
155
135
  # Access the next sibling. Raises a StopIteration if this node is the last
156
136
  # one.
137
+ #
138
+ # Returns the previous sibling node.
157
139
 
158
140
  def next
159
141
  raise StopIteration if last?
160
142
  @next
161
143
  end
162
144
 
163
- # Prev(ious)
164
- #
165
145
  # Access the previous sibling. Raises a StopIteration if this node is the
166
146
  # first one.
147
+ #
148
+ # Returns the previous sibling node.
167
149
 
168
150
  def prev
169
151
  raise StopIteration if first?
@@ -172,19 +154,19 @@ module RootedTree
172
154
 
173
155
  alias previous prev
174
156
 
175
- # Parent
176
- #
177
157
  # Access the parent node. Raises a StopIteration if this node is the
178
158
  # root.
159
+ #
160
+ # Returns the parent node.
179
161
 
180
162
  def parent
181
163
  raise StopIteration if root?
182
164
  @parent
183
165
  end
184
166
 
185
- # Append Sibling
186
- #
187
167
  # Insert a child between this node and the one after it.
168
+ #
169
+ # Returns self.
188
170
 
189
171
  def append_sibling(value = nil)
190
172
  raise StructureException, 'Root node can not have siblings' if root?
@@ -203,9 +185,9 @@ module RootedTree
203
185
  @next = node
204
186
  end
205
187
 
206
- # Prepend Sibling
207
- #
208
188
  # Insert a child between this node and the one before it.
189
+ #
190
+ # Returns self.
209
191
 
210
192
  def prepend_sibling(value = nil)
211
193
  raise StructureException, 'Root node can not have siblings' if root?
@@ -232,9 +214,9 @@ module RootedTree
232
214
  node.parent = self
233
215
  end
234
216
 
235
- # Append Child
236
- #
237
217
  # Insert a child after the last one.
218
+ #
219
+ # Returns self.
238
220
 
239
221
  def append_child(value = nil)
240
222
  if leaf?
@@ -247,9 +229,9 @@ module RootedTree
247
229
 
248
230
  alias << append_child
249
231
 
250
- # Prepend Child
251
- #
252
232
  # Insert a child before the first one.
233
+ #
234
+ # Returns self.
253
235
 
254
236
  def prepend_child(value = nil)
255
237
  if leaf?
@@ -259,9 +241,9 @@ module RootedTree
259
241
  end
260
242
  end
261
243
 
262
- # Extract
263
- #
264
244
  # Extracts the node and its subtree from the larger structure.
245
+ #
246
+ # Returns self, now made root.
265
247
 
266
248
  def extract
267
249
  return self if root?
@@ -283,9 +265,9 @@ module RootedTree
283
265
  self
284
266
  end
285
267
 
286
- # Delete
287
- #
288
268
  # Removes the node from the tree.
269
+ #
270
+ # Returns an array of the children to the deleted node, now made roots.
289
271
 
290
272
  def delete
291
273
  extract.children.map do |child|
@@ -294,12 +276,11 @@ module RootedTree
294
276
  end
295
277
  end
296
278
 
297
- # Ancestors
279
+ # Iterates over the nodes above this in the tree hierarchy and yields them
280
+ # to a block. If no block is given an enumerator is returned.
298
281
  #
299
282
  # Returns an enumerator that will iterate over the parents of this node
300
283
  # until the root is reached.
301
- #
302
- # If a block is given it will be yielded to.
303
284
 
304
285
  def ancestors
305
286
  return to_enum(__callee__) unless block_given?
@@ -310,14 +291,14 @@ module RootedTree
310
291
  end
311
292
  end
312
293
 
313
- # Children
314
- #
315
- # Yields to each of the node children. The default order is left-to-right,
316
- # but by passing rtl: true the order can be reversed. If a block is not
317
- # given an enumerator is returned.
294
+ # Yields each of the node children. The default order is left-to-right, but
295
+ # by passing rtl: true the order is reversed. If a block is not given an
296
+ # enumerator is returned.
318
297
  #
319
298
  # Note that the block will catch any StopIteration that is raised and
320
299
  # terminate early, returning the value of the exception.
300
+ #
301
+ # rtl - reverses the iteration order if true.
321
302
 
322
303
  def children(rtl: false)
323
304
  return to_enum(__callee__, rtl: rtl) unless block_given?
@@ -335,9 +316,14 @@ module RootedTree
335
316
  end
336
317
  end
337
318
 
338
- # Child
319
+ # Accessor method for any of the n children under this node. If called
320
+ # without an argument and the node has anything but exactly one child an
321
+ # exception will be raised.
339
322
  #
340
- # Accessor method for any of the n children under this node.
323
+ # n - the n:th child to be returned. If n is negative the indexing will be
324
+ # reversed and the children counted from the last to the first.
325
+ #
326
+ # Returns the child at the n:th index.
341
327
 
342
328
  def child(n = nil)
343
329
  if n.nil?
@@ -362,8 +348,6 @@ module RootedTree
362
348
  end
363
349
  end
364
350
 
365
- # Each
366
- #
367
351
  # Yields first to self and then to each child. If a block is not given an
368
352
  # enumerator is returned.
369
353
 
@@ -373,9 +357,31 @@ module RootedTree
373
357
  children { |v| v.each(&block) }
374
358
  end
375
359
 
376
- # Leafs
360
+ # Converts the tree structure to a nested array of the nodes. Each internal
361
+ # node is placed at index zero of its own array, followed by an array of its
362
+ # children. Leaf nodes are not wraped in arrays but inserted directly.
377
363
  #
364
+ # flatten - flattens the array if true.
365
+ #
366
+ # Example
367
+ #
368
+ # r
369
+ # / \
370
+ # a b => [r, [[a, [c]], b]]
371
+ # |
372
+ # c
373
+ #
374
+ # Returns a nested array of nodes.
375
+
376
+ def to_a flatten: false
377
+ return super() if flatten
378
+ return self if leaf?
379
+ [self, children.map(&:to_a)]
380
+ end
381
+
378
382
  # Iterates over each of the leafs.
383
+ #
384
+ # rtl - if true the iteration order is switched to right to left.
379
385
 
380
386
  def leafs(rtl: false, &block)
381
387
  return to_enum(__callee__, rtl: rtl) unless block_given?
@@ -383,9 +389,10 @@ module RootedTree
383
389
  children(rtl: rtl) { |v| v.leafs(rtl: rtl, &block) }
384
390
  end
385
391
 
386
- # Edges
392
+ # Iterates over each of the edges and yields the parent and the child. If no
393
+ # block is given an enumerator is returned.
387
394
  #
388
- # Iterates over each of the edges.
395
+ # block - an optional block that will be yielded to, if given.
389
396
 
390
397
  def edges(&block)
391
398
  return to_enum(__callee__) unless block_given?
@@ -396,11 +403,13 @@ module RootedTree
396
403
  end
397
404
  end
398
405
 
399
- # Add
400
- #
401
406
  # Add two roots together to create a larger tree. A new common root will be
402
407
  # created and returned. Note that if the any of the root nodes are not
403
408
  # frozen they will be modified, and as a result seize to be roots.
409
+ #
410
+ # other - a Node-like object that responds true to #root?
411
+ #
412
+ # Returns a new root with the two nodes as children.
404
413
 
405
414
  def +(other)
406
415
  unless root? && other.root?
@@ -414,53 +423,18 @@ module RootedTree
414
423
  ab << a << b
415
424
  end
416
425
 
417
- # Equality
426
+ # Compare one node (sub)structure with another.
418
427
  #
419
428
  # Returns true if the two vertecies form identical subtrees
420
429
 
421
430
  def ==(other)
422
431
  return false unless other.is_a? self.class
423
432
  return false unless degree == other.degree
433
+ return false unless value == other.value
424
434
 
425
435
  children.to_a == other.children.to_a
426
436
  end
427
437
 
428
- # Tree!
429
- #
430
- # Wraps the entire tree in a Tree object. The operation will freeze the node
431
- # structure, making it immutable. If this node is a child the root will be
432
- # found and passed to Tree.new.
433
-
434
- def tree!
435
- Tree.new root
436
- end
437
-
438
- # Tree
439
- #
440
- # Duplicates the entire tree and calls #tree! on the copy.
441
-
442
- def tree
443
- root.dup.tree!
444
- end
445
-
446
- # Subtree!
447
- #
448
- # Extracts this node from the larger tree and wraps it in a Tree object.
449
-
450
- def subtree!
451
- Tree.new extract
452
- end
453
-
454
- # Subtree
455
- #
456
- # Duplicates this node and its descendants and wraps them in a Tree object.
457
-
458
- def subtree
459
- Tree.new dup
460
- end
461
-
462
- # Inspect
463
- #
464
438
  # Visalizes the tree structure in a style very similar to the cli tool tree.
465
439
  # An example of the output can be seen below. Note that the output string
466
440
  # contains unicode characters.
@@ -1,32 +1,40 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module RootedTree
4
- class Tree
5
- attr_reader :root
6
-
7
- def initialize(node)
8
- @root = node.root
9
- @root.freeze
10
- end
11
-
12
- def tree
13
- self
14
- end
15
-
16
- # Degree
17
- #
18
- # Returns the maximum degree (number of children) in the tree.
4
+ module Tree
5
+ # Returns the maximum degree (highest number of children) in the tree.
19
6
 
20
7
  def degree
21
8
  @degree ||= root.max_degree
22
9
  end
23
10
 
24
- # Depth
25
- #
26
11
  # Returns the maximum depth of the tree.
27
12
 
28
13
  def depth
29
14
  @depth ||= root.max_depth
30
15
  end
16
+
17
+ # Iterates over each node in the tree. When given a block it will be yielded
18
+ # to once for each node. If no block is given an enumerator is returned.
19
+
20
+ def each_node(&block)
21
+ @root.each(&block)
22
+ end
23
+
24
+ # Iterates over each leaf in the tree. When given a block it will be yielded
25
+ # to once for leaf node. If no block is given an enumerator is returned.
26
+
27
+ def each_leaf(&block)
28
+ @root.leafs(&block)
29
+ end
30
+
31
+ # Iterates over each edge in the tree. An edge is composed of the parent
32
+ # node and the child, always in that order. When given a block it will be
33
+ # yielded to once for each node. If no block is given an enumerator is
34
+ # returned.
35
+
36
+ def each_edge(&block)
37
+ @root.edges(&block)
38
+ end
31
39
  end
32
40
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module RootedTree
4
- VERSION = '0.2.3'
4
+ VERSION = '0.3.0'
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rooted_tree
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.3
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sebastian Lindberg
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2016-07-27 00:00:00.000000000 Z
11
+ date: 2016-07-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler