# Cycles def cycle_demo(): """A linked list can contain cycles. >>> s = Link(1, Link(2, Link(3))) >>> s.first = 5 >>> t = s.rest >>> t.rest = s >>> s.first 5 >>> s.rest.rest.rest.rest.rest.first 2 """ # Bear Environment def oski(bear): """Oski the bear. >>> oski(abs) [2, [3, 1]] """ def cal(berk): nonlocal bear if bear(berk) == 0: return [berk+1, berk-1] bear = lambda ley: berk-ley return [berk, cal(berk)] return cal(2) # Work class Worker: greeting = 'Sir' def __init__(self): self.elf = Worker def work(self): return self.greeting + ', I work' def __repr__(self): return Bourgeoisie.greeting class Bourgeoisie(Worker): greeting = 'Peon' def work(self): print(Worker.work(self)) return 'My job is to gather wealth' jack = Worker() john = Bourgeoisie() jack.greeting = 'Maam' def work(): """Working. >>> Worker().work() 'Sir, I work' >>> jack Peon >>> jack.work() 'Maam, I work' >>> john.work() Peon, I work 'My job is to gather wealth' >>> john.elf.work(john) 'Peon, I work' """ # Morse tree abcde = {'a': '.-', 'b': '-...', 'c': '-.-.', 'd': '-..', 'e': '.'} def morse(code): """Return a tree representing the code. Each internal (non-leaf) node of the tree other than its root is a signal. Each leaf node is a letter encoded by the path from the root. >>> pretty(morse(abcde)) None / \ . - / \ | - e . | / \ a . - / \ | . d . | | b c """ whole = Tree(None) for letter, signals in sorted(code.items()): t = whole for s in signals: if s in [b.label for b in t.branches]: t = [b for b in t.branches if b.label == s][0] else: b = Tree(s) t.branches.append(b) t = b t.branches.append(Tree(letter)) return whole def decode(signals, tree): """Decode signals into a letter according to tree, assuming signals correctly represents a letter. tree has the format returned by morse(). >>> t = morse(abcde) >>> [decode(s, t) for s in ['-..', '.', '-.-.', '.-', '-..', '.']] ['d', 'e', 'c', 'a', 'd', 'e'] """ for signal in signals: tree = [b for b in tree.branches if b.label == signal][0] leaves = [b for b in tree.branches if b.is_leaf()] assert len(leaves) == 1 return leaves[0].label # Link & Tree class Link: """A linked list.""" empty=() def __init__(self, first, rest=empty): self.first = first self.rest = rest class Tree: """A tree with label as its label value.""" def __init__(self, label, branches=()): self.label = label for branch in branches: assert isinstance(branch, Tree) self.branches = list(branches) def __repr__(self): if self.branches: branch_str = ', ' + repr(self.branches) else: branch_str = '' return 'Tree({0}{1})'.format(repr(self.label), branch_str) def __str__(self): return '\n'.join(self.indented()) def indented(self, k=0): indented = [] for b in self.branches: for line in b.indented(k + 1): indented.append(' ' + line) return [str(self.label)] + indented def is_leaf(self): return not self.branches from io import StringIO # A StringIO is a file-like object that builds a string instead of printing # anything out. def height(tree): """The height of a tree.""" if tree.is_leaf(): return 0 else: return 1 + max([height(b) for b in tree.branches]) def width(tree): """Returns the printed width of this tree.""" label_width = len(str(tree.label)) w = max(label_width, sum([width(t) for t in tree.branches]) + len(tree.branches) - 1) extra = (w - label_width) % 2 return w + extra def pretty(tree): """Print a tree laid out horizontally rather than vertically.""" def gen_levels(tr): w = width(tr) label = str(tr.label) label_pad = " " * ((w - len(label)) // 2) yield w print(label_pad, file=out, end="") print(label, file=out, end="") print(label_pad, file=out, end="") yield if tr.is_leaf(): pad = " " * w while True: print(pad, file=out, end="") yield below = [ gen_levels(b) for b in tr.branches ] L = 0 for g in below: if L > 0: print(" ", end="", file=out) L += 1 w1 = next(g) left = (w1-1) // 2 right = w1 - left - 1 mid = L + left print(" " * left, end="", file=out) if mid*2 + 1 == w: print("|", end="", file=out) elif mid*2 > w: print("\\", end="", file=out) else: print("/", end="", file=out) print(" " * right, end="", file=out) L += w1 print(" " * (w - L), end="", file=out) yield while True: started = False for g in below: if started: print(" ", end="", file=out) next(g); started = True print(" " * (w - L), end="", file=out) yield out = StringIO() h = height(tree) g = gen_levels(tree) next(g) for i in range(2*h + 1): next(g) print(file=out) print(out.getvalue(), end="")