Skip to content

Instantly share code, notes, and snippets.

@rik0
Last active December 21, 2015 15:39
Show Gist options
  • Save rik0/6328252 to your computer and use it in GitHub Desktop.
Save rik0/6328252 to your computer and use it in GitHub Desktop.
Example of function to create some classes of methods to operate on trees. Doctests are annoying, but for now they suffice. Besides, this is not as tested as it should.
def make_mr(reduce_, f, base):
def mr(self):
if not self.children:
return base(self)
else:
mapped = map(f, self.children)
red = reduce_(mapped)
return red
# return reduce_(f(child) for child in self.children)
return mr
class Node(object):
"""
>>> Node(1).height()
0
>>> Node(1).count()
1
>>> Node.from_array([0, 0, 0, 1, 1, 1, 2, 2, 7]).height()
3
>>> Node.from_array([0, 0, 0, 1, 1, 1, 2, 2, 7]).count()
9
"""
def __init__(self, value, *children):
"""
>>> Node(1)
N(1)
>>> Node(0, Node(1), Node(2))
N(0, N(1), N(2))
"""
self.value = value
self.children = list(children)
height = make_mr(lambda mapped_children: max(mapped_children) + 1,
lambda node: node.height(),
lambda node: 0)
count = make_mr(lambda mapped_children: sum(mapped_children) + 1,
lambda node: node.count(),
lambda node: 1)
@classmethod
def from_array(cls, arr):
"""
>>> Node.from_array([0])
N(0)
>>> Node.from_array([0, 0, 0])
N(0, N(1), N(2))
>>> Node.from_array([0, 0, 0, 1, 1, 1, 2, 2, 7])
N(0, N(1, N(3), N(4), N(5)), N(2, N(6), N(7, N(8))))
>>> Node.from_array([1])
Traceback (most recent call last):
...
ValueError: Invalid array spec: missing root.
>>> Node.from_array([0, 1])
Traceback (most recent call last):
...
ValueError: Invalid array spec: multiple roots.
"""
if not arr:
raise ValueError("Empty container")
nodes = {}
def add(node, child):
new_node = cls(child)
nodes[child] = new_node
node.children.append(new_node)
root_index = None
for index, el in enumerate(arr):
if index == el and root_index is None:
root_index = index
nodes.setdefault(index, cls(index))
elif index == el:
raise ValueError(
"Invalid array spec: multiple roots.")
else:
add(nodes.setdefault(el, cls(el)), index)
if root_index is not None:
return nodes[root_index]
else:
raise ValueError(
"Invalid array spec: missing root.")
def __str__(self):
if self.children:
return 'N(%s, %s)' % (
self.value, ', '.join(str(child) for child in
self.children))
else:
return 'N(%s)' % self.value
__repr__ = __str__
if __name__ == "__main__":
import doctest
doctest.testmod()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment