def print_table(graph, tails, node_id_map):
    """Print out a table of nodes and the blocks they have at each block height
    starting with the common ancestor."""
    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))
Print out a table of nodes and the blocks they have at each block height
    starting with the common ancestor.