code: def print_table(graph, tails, node_id_map):
      
      node_count = len(tails)
  
      # Get the width of the table columns
      num_col_width = max(
          floor(log(max(get_heights(tails)), 10)) + 1,
          len("NUM"))
      node_col_width = max(
          floor(log(node_count, 10)) + 1,
          8)
  
      # Construct the output format string
      format_str = ''
      format_str += '{:<' + str(num_col_width) + '} '
      for _ in range(node_count):
          format_str += '{:<' + str(node_col_width) + '} '
  
      nodes_header = ["NODE " + str(node_id_map[i]) for i in range(node_count)]
      header = format_str.format("NUM", *nodes_header)
      print(header)
      print('-' * len(header))
  
      prev_block_num = -1
      node_list = [''] * node_count
      for block_num, _, siblings in graph.walk():
          if block_num != prev_block_num:
              # Need to skip the first one
              if prev_block_num != -1:
                  print(format_str.format(prev_block_num, *node_list))
  
              node_list.clear()
              node_list.extend([''] * node_count)
              prev_block_num = block_num
  
          for block_id, node_ids in siblings.items():
              for node_id in node_ids:
                  node_list[node_id] = block_id[:8]
  
      # Print the last one
      print(format_str.format(prev_block_num, *node_list))
docs: Print out a table of nodes and the blocks they have at each block height
      starting with the common ancestor.