rooted_tree 0.2.3 → 0.3.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.
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