rooted_tree 0.2.1 → 0.2.2
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/README.md +2 -9
- data/examples/filesystem_tree.rb +4 -10
- data/lib/rooted_tree/node.rb +76 -38
- data/lib/rooted_tree/tree.rb +7 -7
- data/lib/rooted_tree/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 22a5b2a13278deccce0118fecd19ba5d65e39a4c
|
4
|
+
data.tar.gz: f2de5a5dba41d23f396e325889f9ed2dd6d468af
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 492a612d75f800c8e3ab638beb1c7bc9f352125eb29ceff47bf2a38855b12bbbb4675846dd52a4813877baf5402da1f39a6b53880c2c9adf9083621c50122dc7
|
7
|
+
data.tar.gz: cd0a3ef730dca13e6d083bdf44ed0b834a973121dff0ca05369fd355f8c6b30a9be1fd957dc5b9e60dd5b0ba1395964fe63122e0914a4593441b791c6b4b87f3
|
data/README.md
CHANGED
@@ -53,22 +53,15 @@ The gem is primarily ment to be extended by other classes. The following example
|
|
53
53
|
|
54
54
|
```ruby
|
55
55
|
class FileSystemItem < RootedTree::Node
|
56
|
-
attr_reader :name
|
57
|
-
|
58
|
-
def initialize name
|
59
|
-
super()
|
60
|
-
@name = name
|
61
|
-
end
|
62
|
-
|
63
56
|
def display
|
64
|
-
inspect { |item| item.
|
57
|
+
inspect { |item| item.value }
|
65
58
|
end
|
66
59
|
|
67
60
|
def self.map_to_path path = '.', root: new(path)
|
68
61
|
# Iterate over all of the files in the directory
|
69
62
|
Dir[path + '/*'].each do |entry|
|
70
63
|
# Create a new FileSystemItem for the entry
|
71
|
-
item = new File.basename
|
64
|
+
item = new File.basename(entry)
|
72
65
|
root << item
|
73
66
|
# Continue to map the files and directories under
|
74
67
|
# entry, if it is a directory
|
data/examples/filesystem_tree.rb
CHANGED
@@ -6,25 +6,19 @@ require 'rooted_tree'
|
|
6
6
|
#
|
7
7
|
# Maps the entries in the file system to `Node` objects via .map_to_path. The
|
8
8
|
# Node#inspect method is then exploited in #display to show the resulting tree
|
9
|
-
# structure.
|
9
|
+
# structure. The name of each entry in the filesystem is stored in the value
|
10
|
+
# field of the Node.
|
10
11
|
|
11
12
|
class FileSystemItem < RootedTree::Node
|
12
|
-
attr_reader :name
|
13
|
-
|
14
|
-
def initialize name
|
15
|
-
super()
|
16
|
-
@name = name
|
17
|
-
end
|
18
|
-
|
19
13
|
def display
|
20
|
-
inspect { |item| item.
|
14
|
+
inspect { |item| item.value }
|
21
15
|
end
|
22
16
|
|
23
17
|
def self.map_to_path path = '.', root: new(path)
|
24
18
|
# Iterate over all of the files in the directory
|
25
19
|
Dir[path + '/*'].each do |entry|
|
26
20
|
# Create a new FileSystemItem for the entry
|
27
|
-
item = new File.basename
|
21
|
+
item = new File.basename(entry)
|
28
22
|
root << item
|
29
23
|
# Continue to map the files and directories under
|
30
24
|
# entry, if it is a directory
|
data/lib/rooted_tree/node.rb
CHANGED
@@ -23,21 +23,27 @@
|
|
23
23
|
module RootedTree
|
24
24
|
class Node
|
25
25
|
include Enumerable
|
26
|
-
|
27
|
-
attr_accessor :first_child, :last_child, :degree
|
26
|
+
|
27
|
+
attr_accessor :first_child, :last_child, :degree, :value
|
28
28
|
attr_writer :next, :prev, :parent
|
29
|
-
|
29
|
+
|
30
30
|
protected :next=, :prev=, :parent=, :first_child=, :last_child=, :degree=
|
31
|
-
|
31
|
+
|
32
32
|
alias arity degree
|
33
33
|
|
34
|
-
def
|
34
|
+
def self.[](value = nil)
|
35
|
+
return value if value.is_a? self
|
36
|
+
self.new value
|
37
|
+
end
|
38
|
+
|
39
|
+
def initialize value = nil
|
35
40
|
@parent = nil
|
36
41
|
@next = nil
|
37
42
|
@prev = nil
|
38
43
|
@first_child = nil
|
39
44
|
@last_child = nil
|
40
45
|
@degree = 0
|
46
|
+
@value = value
|
41
47
|
end
|
42
48
|
|
43
49
|
def initialize_copy(*)
|
@@ -48,9 +54,10 @@ module RootedTree
|
|
48
54
|
@first_child = duped_children.first
|
49
55
|
@last_child = duped_children.last
|
50
56
|
end
|
51
|
-
|
57
|
+
|
52
58
|
def freeze
|
53
59
|
super
|
60
|
+
@value.freeze
|
54
61
|
children.each(&:freeze)
|
55
62
|
end
|
56
63
|
|
@@ -85,7 +92,7 @@ module RootedTree
|
|
85
92
|
|
86
93
|
def root
|
87
94
|
return self if root?
|
88
|
-
|
95
|
+
|
89
96
|
node = self
|
90
97
|
loop { node = node.parent }
|
91
98
|
node
|
@@ -116,15 +123,15 @@ module RootedTree
|
|
116
123
|
end
|
117
124
|
|
118
125
|
alias level depth
|
119
|
-
|
126
|
+
|
120
127
|
# Max Depth
|
121
128
|
#
|
122
129
|
# Returns the maximum node depth under this node.
|
123
|
-
|
124
|
-
def max_depth
|
130
|
+
|
131
|
+
def max_depth(offset = depth)
|
125
132
|
return offset if leaf?
|
126
|
-
|
127
|
-
children.map {|c| c.max_depth offset + 1 }.max
|
133
|
+
|
134
|
+
children.map { |c| c.max_depth offset + 1 }.max
|
128
135
|
end
|
129
136
|
|
130
137
|
# Max Degree
|
@@ -179,14 +186,15 @@ module RootedTree
|
|
179
186
|
#
|
180
187
|
# Insert a child between this node and the one after it.
|
181
188
|
|
182
|
-
def append_sibling(
|
189
|
+
def append_sibling(value = nil)
|
183
190
|
raise StructureException, 'Root node can not have siblings' if root?
|
184
191
|
|
192
|
+
node = self.class[value]
|
185
193
|
node.next = @next
|
186
194
|
node.prev = self
|
187
195
|
node.parent = @parent
|
188
196
|
@parent.degree += 1
|
189
|
-
|
197
|
+
|
190
198
|
if @next
|
191
199
|
@next.prev = node
|
192
200
|
else
|
@@ -199,14 +207,15 @@ module RootedTree
|
|
199
207
|
#
|
200
208
|
# Insert a child between this node and the one before it.
|
201
209
|
|
202
|
-
def prepend_sibling(
|
210
|
+
def prepend_sibling(value = nil)
|
203
211
|
raise StructureException, 'Root node can not have siblings' if root?
|
204
212
|
|
213
|
+
node = self.class[value]
|
205
214
|
node.next = self
|
206
215
|
node.prev = @prev
|
207
216
|
node.parent = @parent
|
208
217
|
@parent.degree += 1
|
209
|
-
|
218
|
+
|
210
219
|
if @prev
|
211
220
|
@prev.next = node
|
212
221
|
else
|
@@ -214,41 +223,42 @@ module RootedTree
|
|
214
223
|
end
|
215
224
|
@prev = node
|
216
225
|
end
|
217
|
-
|
218
|
-
private def add_child_to_leaf(
|
219
|
-
|
220
|
-
|
226
|
+
|
227
|
+
private def add_child_to_leaf(value)
|
228
|
+
node = self.class[value]
|
229
|
+
@first_child = @last_child = node
|
230
|
+
node.next = node.prev = nil
|
221
231
|
@degree = 1
|
222
|
-
|
232
|
+
node.parent = self
|
223
233
|
end
|
224
234
|
|
225
235
|
# Append Child
|
226
236
|
#
|
227
237
|
# Insert a child after the last one.
|
228
238
|
|
229
|
-
def append_child(
|
239
|
+
def append_child(value = nil)
|
230
240
|
if leaf?
|
231
|
-
add_child_to_leaf
|
241
|
+
add_child_to_leaf value
|
232
242
|
else
|
233
|
-
@last_child.append_sibling
|
243
|
+
@last_child.append_sibling value
|
234
244
|
end
|
235
245
|
self
|
236
246
|
end
|
237
247
|
|
248
|
+
alias << append_child
|
249
|
+
|
238
250
|
# Prepend Child
|
239
251
|
#
|
240
252
|
# Insert a child before the first one.
|
241
253
|
|
242
|
-
def prepend_child(
|
254
|
+
def prepend_child(value = nil)
|
243
255
|
if leaf?
|
244
|
-
add_child_to_leaf
|
256
|
+
add_child_to_leaf value
|
245
257
|
else
|
246
|
-
@first_child.prepend_sibling
|
258
|
+
@first_child.prepend_sibling value
|
247
259
|
end
|
248
260
|
end
|
249
261
|
|
250
|
-
alias << append_child
|
251
|
-
|
252
262
|
# Extract
|
253
263
|
#
|
254
264
|
# Extracts the node and its subtree from the larger structure.
|
@@ -303,7 +313,8 @@ module RootedTree
|
|
303
313
|
# Children
|
304
314
|
#
|
305
315
|
# Yields to each of the node children. The default order is left-to-right,
|
306
|
-
# but by passing rtl: true the order can be reversed. If a block is not
|
316
|
+
# but by passing rtl: true the order can be reversed. If a block is not
|
317
|
+
# given an enumerator is returned.
|
307
318
|
#
|
308
319
|
# Note that the block will catch any StopIteration that is raised and
|
309
320
|
# terminate early, returning the value of the exception.
|
@@ -324,6 +335,33 @@ module RootedTree
|
|
324
335
|
end
|
325
336
|
end
|
326
337
|
|
338
|
+
# Child
|
339
|
+
#
|
340
|
+
# Accessor method for any of the n children under this node.
|
341
|
+
|
342
|
+
def child(n = nil)
|
343
|
+
if n.nil?
|
344
|
+
if @degree != 1
|
345
|
+
raise ArgumentError, 'No argument given for node with degree != 1'
|
346
|
+
end
|
347
|
+
return @first_child
|
348
|
+
end
|
349
|
+
|
350
|
+
rtl = if n < 0
|
351
|
+
n = -1 - n
|
352
|
+
true
|
353
|
+
else
|
354
|
+
false
|
355
|
+
end
|
356
|
+
|
357
|
+
raise RangeError, 'Child index out of range' if n >= @degree
|
358
|
+
|
359
|
+
children(rtl: rtl).each do |c|
|
360
|
+
break c if n == 0
|
361
|
+
n -= 1
|
362
|
+
end
|
363
|
+
end
|
364
|
+
|
327
365
|
# Each
|
328
366
|
#
|
329
367
|
# Yields first to self and then to each child. If a block is not given an
|
@@ -382,37 +420,37 @@ module RootedTree
|
|
382
420
|
|
383
421
|
children.to_a == other.children.to_a
|
384
422
|
end
|
385
|
-
|
423
|
+
|
386
424
|
# Tree!
|
387
425
|
#
|
388
426
|
# Wraps the entire tree in a Tree object. The operation will freeze the node
|
389
427
|
# structure, making it immutable. If this node is a child the root will be
|
390
428
|
# found and passed to Tree.new.
|
391
|
-
|
429
|
+
|
392
430
|
def tree!
|
393
431
|
Tree.new root
|
394
432
|
end
|
395
|
-
|
433
|
+
|
396
434
|
# Tree
|
397
435
|
#
|
398
436
|
# Duplicates the entire tree and calls #tree! on the copy.
|
399
|
-
|
437
|
+
|
400
438
|
def tree
|
401
439
|
root.dup.tree!
|
402
440
|
end
|
403
|
-
|
441
|
+
|
404
442
|
# Subtree!
|
405
443
|
#
|
406
444
|
# Extracts this node from the larger tree and wraps it in a Tree object.
|
407
|
-
|
445
|
+
|
408
446
|
def subtree!
|
409
447
|
Tree.new extract
|
410
448
|
end
|
411
|
-
|
449
|
+
|
412
450
|
# Subtree
|
413
451
|
#
|
414
452
|
# Duplicates this node and its descendants and wraps them in a Tree object.
|
415
|
-
|
453
|
+
|
416
454
|
def subtree
|
417
455
|
Tree.new dup
|
418
456
|
end
|
data/lib/rooted_tree/tree.rb
CHANGED
@@ -3,30 +3,30 @@
|
|
3
3
|
module RootedTree
|
4
4
|
class Tree
|
5
5
|
attr_reader :root
|
6
|
-
|
6
|
+
|
7
7
|
def initialize(node)
|
8
8
|
@root = node.root
|
9
9
|
@root.freeze
|
10
10
|
end
|
11
|
-
|
11
|
+
|
12
12
|
def tree
|
13
13
|
self
|
14
14
|
end
|
15
|
-
|
15
|
+
|
16
16
|
# Degree
|
17
17
|
#
|
18
18
|
# Returns the maximum degree (number of children) in the tree.
|
19
|
-
|
19
|
+
|
20
20
|
def degree
|
21
21
|
@degree ||= root.max_degree
|
22
22
|
end
|
23
|
-
|
23
|
+
|
24
24
|
# Depth
|
25
25
|
#
|
26
26
|
# Returns the maximum depth of the tree.
|
27
|
-
|
27
|
+
|
28
28
|
def depth
|
29
29
|
@depth ||= root.max_depth
|
30
30
|
end
|
31
31
|
end
|
32
|
-
end
|
32
|
+
end
|
data/lib/rooted_tree/version.rb
CHANGED
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.
|
4
|
+
version: 0.2.2
|
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-
|
11
|
+
date: 2016-07-25 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|