def pathlength_sets(t: Tree) -> None: """ Replace the value of each node in Tree t by a set containing all path lengths from that node to any leaf. A path's length is the number of edges it contains. >>> t = Tree(5) >>> pathlength_sets(t) >>> print(t) {0} >>> t.children.append(Tree(17)) >>> t.children.append(Tree(13, [Tree(11)])) >>> pathlength_sets(t) >>> print(t) {1, 2} {0} {1} {0} """ if t.value is None: pass elif t.children == []: t.value = {0} else: t.value = set() for s in t.children: pathlength_sets(s) t.value = t.value.union(s.value) t.value = set([e + 1 for e in t.value])
def test_in_order2(): tree = Tree() s = 100 elem = list() for i in reversed(range(0, s)): tree.insert(i, i) elem.append(i) res = tree.pre_order() assert res == elem
def test_right_most_child(): tree = Tree() l = [38, 13, 51, 10, 25, 40, 84, 12, 37, 66, 89, 95] length = len(l) while len(l) > 0: key = l.pop(0) value = chr(key) tree.insert(key, value) croot = tree.right_most_child(tree.root.left) assert croot.key == 37
def test_insert(): tree = Tree() s = 100 for i in range(0, s): tree.insert(i, i) k = 0 curr = tree.root while k < s: assert curr.key == k assert curr.left == None curr = curr.right k += 1
def test_print_paths(): tree = Tree() l = [38, 13, 51, 10, 25, 40, 84, 12, 37, 66, 89, 95] length = len(l) while len(l) > 0: key = l.pop(0) value = chr(key) tree.insert(key, value) l = tree.print_paths() assert l[0] == ' 38 13 10 12' assert l[1] == ' 38 13 25 37' assert l[2] == ' 38 51 40' assert l[3] == ' 38 51 84 66' assert l[4] == ' 38 51 84 89 95'
def descendants_from_list(t: Tree, list_: list, branching: int) -> Tree: """ Populate Tree t's descendants from list_, filling them in in level order, with up to arity children per node. Then return t. This is a helper function for doctests >>> descendants_from_list(Tree(0), [1, 2, 3, 4], 2) Tree(0, [Tree(1, [Tree(3), Tree(4)]), Tree(2)]) """ q = Queue() q.add(t) list_ = list_.copy() while not q.is_empty(): # unlikely to happen new_t = q.remove() new_t: Tree for _ in range(0, branching): if len(list_) == 0: return t # our work here is done else: new_t_child = Tree(list_.pop(0)) new_t.children.append(new_t_child) q.add(new_t_child) return t
def test_find(): l = list() for i in range(97, 107): l.append(i) tree = Tree() random.shuffle(l) while len(l) > 0: key = l.pop() value = chr(key) tree.insert(key, value) for i in range(97, 107): key = i value = chr(key) croot = tree.find(key) assert croot.value == value
def path_to_tree(path_name: str) -> Tree: """ Return a Tree representing a filesystem starting from pathname. """ return Tree((path_name, [f.name for f in scandir(path_name)]), [ path_to_tree(path.join(path_name, f.name)) for f in scandir(path_name) if f.is_dir() ])
def test_height(): tree = Tree() s = 100 assert tree.height() == -1 for i in range(0, s): tree.insert(i, i) tree.height() == i
def test_mirror(): tree = Tree() l = [38, 13, 51, 10, 25, 40, 84, 12, 37, 66, 89, 95] length = len(l) while len(l) > 0: key = l.pop(0) value = chr(key) tree.insert(key, value) level_order = tree.level_order() assert level_order == [38, 13, 51, 10, 25, 40, 84, 12, 37, 66, 89, 95] tree.mirror() level_order = tree.level_order() pre_order = tree.pre_order() assert level_order == [38, 51, 13, 84, 40, 25, 10, 89, 66, 37, 12, 95] assert pre_order == [38, 51, 84, 89, 95, 66, 40, 13, 25, 37, 10, 12]
def test_remove3(): tree = Tree() s = 100 for i in range(0, s): tree.insert(i, i) for i in range(0, s): tree.remove(i)
def test_remove4(): tree = Tree() s = 100 for i in reversed(range(0, s)): tree.insert(i, i) for i in reversed(range(0, s)): tree.remove(i)
def test_find2(): tree = Tree() l = [38, 13, 51, 10, 25, 40, 84, 12, 37, 66, 89, 95] length = len(l) while len(l) > 0: key = l.pop(0) value = chr(key) tree.insert(key, value) assert tree.find(100).key == 95 assert tree.find(50).key == 40 assert tree.find(39).key == 40 assert tree.find(15).key == 25
def test_in_order_pre_order_level_order(): tree = Tree() l = [38, 13, 51, 10, 25, 40, 84, 12, 37, 66, 89, 95] length = len(l) while len(l) > 0: key = l.pop(0) value = chr(key) tree.insert(key, value) in_order = tree.in_order() pre_order = tree.pre_order() level_order = tree.level_order() assert in_order == [10, 12, 13, 25, 37, 38, 40, 51, 66, 84, 89, 95] assert pre_order == [38, 13, 10, 12, 25, 37, 51, 40, 84, 66, 89, 95] assert level_order == [38, 13, 51, 10, 25, 40, 84, 12, 37, 66, 89, 95]
def test_remove5(): tree = Tree() l = list() s = 100 for i in range(0, s): tree.insert(i, i) for i in range(0, s): l.append(i) random.shuffle(l) size = 100 while len(l) > 1: key = l.pop() tree.remove(key) size -= 1 assert len(tree.in_order()) == size croot = tree.find(key) assert croot.key != key
def string_postorder(t: Tree) -> str: """ Return a string of tree in post order >>> t = Tree("a", [Tree("b"), Tree("c", [Tree("d")]), \ Tree("e", [Tree("f")]), Tree("g")]) >>> string_postorder(t) 'bdcfega' >>> string_postorder(Tree("a")) 'a' >>> t = Tree("a", [Tree("b", [Tree("c")]), Tree("d")]) >>> string_postorder(t) 'cbda' """ if t.value is None: return '' else: return ''.join([string_postorder(s) for s in t.children]) + str(t.value)
def concatenate_at_depth(t: Tree, d: int) -> str: """ Return the concatenation of node values at depth d of t. Assume that node values are strings and that there are no None values in any list of children in t or its descendants. >>> t = Tree("a", [Tree("b"), Tree("c", [Tree("d")]), \ Tree("e", [Tree("f")]), Tree("g")]) >>> concatenate_at_depth(t, 0) 'a' >>> concatenate_at_depth(t, 1) 'bceg' >>> concatenate_at_depth(t, 2) 'df' >>> concatenate_at_depth(t, 5) '' """ if t.value is None: return '' elif d == 0: return str(t.value) else: return ''.join([concatenate_at_depth(s, d - 1) for s in t.children])
def count_internal(t: Tree) -> int: """ Return number of internal nodes of t. >>> t = Tree(0) >>> count_internal(t) 0 >>> t = descendants_from_list(Tree(0), [1, 2, 3, 4, 5, 6, 7, 8], 3) >>> t Tree(0, [Tree(1, [Tree(4), Tree(5), Tree(6)]), Tree(2, [Tree(7), \ Tree(8)]), Tree(3)]) >>> count_internal(t) 3 >>> descendants_from_list(Tree(0), [1, 2, 3, 4], 2) Tree(0, [Tree(1, [Tree(3), Tree(4)]), Tree(2)]) """ if t.value is None: return 0 elif t.children == []: # we're at a leaf -> not internal. return 0 else: # we're at an internal node return 1 + sum(count_internal(subtree) for subtree in t.children)
def prune(t: Tree, predicate: Callable[[object], bool]) -> Optional[Tree]: """ Return a new tree with the same values as t, except it prunes (omits) all paths of t that start with nodes where predicate(node.value) == False. If predicate(t.value) == False, then prune returns None. Assume that all values in t are ints, and that predicate always takes an int and returns a bool. >>> v: int >>> t1 = Tree(6, [Tree(8) , Tree(9)]) >>> t2 = Tree(4, [Tree(11), Tree(10)]) >>> t3 = Tree(7, [Tree(3), Tree(12)]) >>> t = Tree(5, [t1, t2, t3]) >>> t3_pruned = Tree(7, [Tree(12)]) >>> def predicate (v) : return v > 4 >>> prune(t, predicate) == Tree(5, [t1, t3_pruned]) True """ # version 1 # if t.value is None: # pass # elif not predicate(t.value): # pass # else: # new_t = Tree(t.value) # for s in t.children: # subtree = prune(s, predicate) # if subtree is not None: # new_t.children.append(subtree) # return new_t # version 2 ** modifies t *** # if t.value is None: # pass # elif not predicate(t.value): # pass # else: # list_ = [prune(subtree, predicate) for subtree in t.children] # t.children = [x for x in list_ if x is not None] # return t # Version 3 # if t.value is None: # pass # elif not predicate(t.value): # pass # else: # new_t = Tree(t.value) # lst = [prune(s, predicate) for s in t.children] # new_t.children = [s for s in lst if s is not None] # return new_t # version 4: # if t.value is None: # pass # elif not predicate(t.value): # return Tree() # else: # new_t = Tree(t.value) # for subtree in t.children: # tree = prune(subtree, predicate) # if tree.value is not None: # new_t.children.append(tree) # return new_t if t.value is None: pass elif predicate(t.value) is False: pass else: new_t = Tree(t.value) for s in t.children: child = prune(s, predicate) if child is not None: new_t.children.append(child) return new_t
def test_remove(): tree = Tree() l = [38, 13, 51, 10, 25, 40, 84, 12, 37, 66, 89, 95] length = len(l) while len(l) > 0: key = l.pop(0) value = chr(key) tree.insert(key, value) tree.remove(38) assert tree.root.key == 37 assert tree.find(13).parent.key == 37 assert tree.find(51).parent.key == 37 assert tree.find(38).key == 40 tree.remove(89) assert tree.find(95).key == 95 assert tree.find(95).parent.key == 84 tree.remove(13) assert tree.find(13).key == 25 assert tree.find(12).parent.key == 37 assert tree.find(10).parent.key == 12 assert tree.find(25).parent.key == 12
def test_remove2(): tree = Tree() l = [38, 13, 51, 10, 25, 40, 84, 12, 37, 66, 89, 95] length = len(l) while len(l) > 0: key = l.pop(0) value = chr(key) tree.insert(key, value) tree.remove(100) tree.remove(50) tree.remove(14) tree.remove(39) assert len(tree.in_order()) == length