rooted_tree 0.2.1 → 0.2.2
Sign up to get free protection for your applications and to get access to all the features.
- 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
|