Diagram G script
From Geb
#18:30 Tuesday 21 March 2006 #By Evgeni Sergeev #First, construct a tree. Then call propagateSubtreeWidths() on the root. #Then call printTree() on the root. import sys class Node: """Represents a node in the tree. """ def __init__(self, content): self.children = [] self.content = content self.subtree_width = 1 self.root_offset = 0 def addChild(self, child): self.children.append(child) def propagateSubtreeWidths(self): for child in self.children: child.propagateSubtreeWidths() if len(self.children) == 1: self.subtree_width = self.children[0].subtree_width self.root_offset = self.children[0].root_offset elif len(self.children) == 0: self.subtree_width = len(str(self.content)) + 1 self.root_offset = 0 else: n = 0 for child in self.children: n = n + child.subtree_width self.subtree_width = n right_child_relative_offset = self.subtree_width - \\ (self.children[len(self.children)-1].subtree_width - \\ self.children[len(self.children)-1].root_offset) self.root_offset = (self.children[0].root_offset + \\ right_child_relative_offset) / 2 def printLineTwo(self): n = self.root_offset - len(str(self.content))/2 if n < 0: n = 0 sys.stdout.write(' '*n) sys.stdout.write(str(self.content)) sys.stdout.write(' '*(self.subtree_width - n - len(str(self.content)))) def printLineOne(self): n = self.root_offset sys.stdout.write(' '*n) sys.stdout.write('|') sys.stdout.write(' '*(self.subtree_width - n - 1)) def printLineThree(self, horizontal_char = '_'): if len(self.children) > 0: if len(self.children) == 1: self.printLineOne() elif len(self.children) == 0: sys.stdout.write(' '*self.subtree_width) else: left_child_offset = self.children[0].root_offset right_child_offset = self.subtree_width - \\ (self.children[len(self.children)-1].subtree_width - \\ self.children[len(self.children)-1].root_offset) left_dashes = self.root_offset - left_child_offset - 1 right_dashes = right_child_offset - self.root_offset - 1 left_spaces = self.root_offset - left_dashes right_spaces = self.subtree_width - left_spaces - left_dashes \\ - 1 - right_dashes sys.stdout.write(' '*left_spaces) sys.stdout.write(horizontal_char*left_dashes) sys.stdout.write('|') sys.stdout.write(horizontal_char*right_dashes) sys.stdout.write(' '*right_spaces) def addChildren(self, queue, levels, parent_level): queue.extend(self.children) new_levels = [] for child in self.children: new_levels.append(parent_level + 1) levels.extend(new_levels) def printTree(self, upside_down = 0): queue = [self] levels = [0] n = 0 #Breadth queue while n < len(queue): queue[n].addChildren(queue, levels, levels[n]) n = n + 1 #levels[n] contains the level of n if not upside_down: i = 0 while i < n: start_of_level = i end_of_level = i while end_of_level < n and \\ levels[end_of_level] == levels[start_of_level]: end_of_level = end_of_level + 1 end_of_level = end_of_level - 1 for item in range(start_of_level,end_of_level+1): queue[item].printLineOne() print ' ' for item in range(start_of_level,end_of_level+1): queue[item].printLineTwo() print ' ' for item in range(start_of_level,end_of_level+1): queue[item].printLineThree() print ' ' i = end_of_level + 1 else: i = n - 1 while i >= 0: start_of_level = i end_of_level = i while start_of_level >= 0 and \\ levels[end_of_level] == levels[start_of_level]: start_of_level = start_of_level - 1 start_of_level = start_of_level + 1 for item in range(start_of_level,end_of_level+1): queue[item].printLineThree('"') print ' ' for item in range(start_of_level,end_of_level+1): queue[item].printLineTwo() print ' ' for item in range(start_of_level,end_of_level+1): queue[item].printLineOne() print ' ' i = start_of_level - 1 def outputTree(f, n): n = n + 1 nodes = range(n-1) i = 1 while i < n: nodes[i-1] = Node(i) if (f(i) != i): nodes[f(i)-1].addChild(nodes[i-1]) i = i + 1 nodes[0].propagateSubtreeWidths() nodes[0].printTree(upside_down = 1) print "Diagram G up to n=55." def G(n, cache={}): #cache is shared between calls (!) if n == 0: return 0 if n not in cache: cache[n] = n - G(G(n-1)) return cache[n] outputTree(G, 55) print "\
\ Diagram H up to n=59."
def H(n, cache={}): if n == 0: return 0 if n not in cache: cache[n] = n - H(H(H(n-1))) return cache[n] outputTree(H, 59) print "\
\ Diagram I up to n=69."
def I(n, cache={}): if n == 0: return 0 if n not in cache: cache[n] = n - I(I(I(I(n-1)))) return cache[n] outputTree(I, 69) print "\
\ Diagram J up to n=80."
def J(n, cache={}): if n == 0: return 0 if n not in cache: cache[n] = n - J(J(J(J(J(n-1))))) return cache[n] outputTree(J, 80) print "\
\ The tree for Q(n) up to n=64."
def Q(n, cache={}): if n == 0: return 0 if n not in cache: cache[n] = n - Q(n-1) return cache[n] outputTree(Q, 64) print "\
\ The mirror tree MG(n) up to n=55."
def L(n, cache={}): if n == 1: return 1 if n not in cache: cache[n] = L(G(n)) + 1 return cache[n] def F(n, cache={0:1, 1:1}): if n == 1 or n == 0: return 1 if n not in cache: keys = cache.keys() keys.sort(reverse=True) max_known = keys[0] a, b = F(max_known), F(max_known - 1) for i in range(max_known + 1, n + 1): a, b = a + b, a cache[i] = a return cache[n] def M(n): if n == 1: return 1 return F(L(n)) - (n - F(L(n)-1)) + 1 def MG(n): return M(G(M(n))) outputTree(MG, 55) #Debugging code. #print nodes #for node in nodes: #print node.content, ': ', #for child in node.children: #print child.content, ' ', #print ' '
See the Diagram G script output