| """Generic tools for working with trees.""" |
| from math import ceil, log |
| def build_n_ary_tree(leaves, n): |
| """Build N-ary tree from sequence of leaf nodes. |
| Return a list of lists where each non-leaf node is a list containing |
| depth = ceil(log(len(leaves), n)) |
| # Fully populate complete subtrees of root until we have enough leaves left |
| full_step = n ** (depth - 1) |
| for i in range(0, len(leaves), full_step): |
| subtree = leaves[i : i + full_step] |
| if len(subtree) < full_step: |
| subtree = [subtree[k : k + n] for k in range(0, len(subtree), n)] |
| # Recurse to fill the last subtree, which is the only partially populated one |
| subtree = build_n_ary_tree(unassigned, n) |
| if len(subtree) <= n - len(root): |
| # replace last subtree with its children if they can still fit |