Takes a grid of phenotypes or resource sets representing as strings
    representing binary numbers, and an integer indicating the maximum number
    of clusters to generated.

    Clusters the data in grid into a maximum of n groups, ranks each group by
    the complexity and length of its "average" member, and returns a dictionary
    mapping binary numbers to integers representing the rank of the cluster
    they're part of.

def generate_ranks(grid, n):
    """
    Takes a grid of phenotypes or resource sets representing as strings
    representing binary numbers, and an integer indicating the maximum number
    of clusters to generated.

    Clusters the data in grid into a maximum of n groups, ranks each group by
    the complexity and length of its "average" member, and returns a dictionary
    mapping binary numbers to integers representing the rank of the cluster
    they're part of.
    """
    phenotypes = deepcopy(grid)
    if type(phenotypes) is list and type(phenotypes[0]) is list:
        phenotypes = flatten_array(phenotypes)

    # Remove duplicates from types
    types = list(frozenset(phenotypes))
    if len(types) < n:
        ranks = rank_types(types)
    else:
        ranks = cluster_types(types, n)

    return ranks