Python all possible group combinations of teams with different sizes

Viewed 266

I am trying to form every unique possible set of teams, of different sizes, from a group of people. I have a list of people of size n and there are k teams. In the case below there are 13 people and 4 teams.

people = ["Bob", "Jane", "Mary", "Martha", "James", "Charles", "Kevin", "Debbie", "Brian", "Matt", "Milo", "Chris", "Sam"]

example output:

[[Bob, Jane, Mary], [Martha, James, Charles], [Kevin, Debbie, Brian], [Matt, Milo, Chris, Sam]]
[[Bob, Jane, Mary], [Martha, James, Charles], [Kevin, Debbie, Matt], [Brian, Milo, Chris, Sam]]
[[Bob, Jane, Mary], [Martha, James, Charles], [Kevin, Debbie, Milo], [Brain, Matt, Chris, Sam]]
[[Bob, Jane, Mary], [Martha, James, Charles], [Kevin, Debbie, Chris], [Brian, Matt, Milo, Sam]]
.
.
.
[[Bob, Jane, Mary], [Martha, James, Charles], [Kevin, Debbie, Brian, Matt], [Milo, Chris, Sam]]
.
.
.

Teams can be any size 3 - 5. I have seen similar versions of this problem but none with the addition that teams can vary in size. The result I'm hoping for is implemented in such a way that I can call a function that takes in the set of teams and returns an integer as a score for the team and keeps track of the team with the highest score.

ie:

def generate_best_teams(people, num_teams):
    loop:
        teams gets created
        teams_score = calculate_score(teams)
        if teams_score > best_score:
            best_score = teams_score
            best_teams = teams

    return best_teams

Any help with this problem would be greatly apricated.

2 Answers

I have tried to make a generator to produce the result. I'm pretty sure there is better way to do it. See if it works:

from itertools import permutations, islice, product

def length_to_split(n, min_teammate, max_teammate):
    '''Return a list of pattern, e.g.

    >>> length_to_split(13, 3, 5)
    [(3, 5, 5), (4, 4, 5), (3, 3, 3, 4)]
    '''
    min_number_of_group = n // max_teammate + 1
    max_number_of_group = n // min_teammate

    result = []
    for i in range(min_number_of_group, max_number_of_group + 1):
        for x in list(product(*([range(min_teammate, max_teammate + 1)] * i))):
            if sum(x) == n and list(x) == sorted(x):
                result.append(x)
    return result

def team_generator(people, min_teammate, max_teammate):
    '''Loop through all permutation then remove duplicate.'''
    n = len(people)
    patterns = length_to_split(n, min_teammate, max_teammate)
    for p in patterns:
        for comb in permutations(range(n), n):
            input = iter(comb)
            comb = [list(islice(input, elem)) for elem in p]
            
            # Remove duplicate permutation
            for sublist in comb:
                if sublist != sorted(sublist):
                    break
            else:
                comb = [[people[i] for i in t] for t in comb]
                yield comb

# Testing
people = ["Bob", "Jane", "Mary", "Martha", "James", "Charles", "Kevin", "Debbie", "Brian", "Matt", "Milo", "Chris", "Sam"]
min_teammate = 3
max_teammate = 5

g = team_generator(range(13), min_teammate, max_teammate)
for i in range(3):
    print(next(g))

print()

g = team_generator(people, min_teammate, max_teammate)
for i in range(3):
    print(next(g))

Output:

[[0, 1, 2], [3, 4, 5, 6, 7], [8, 9, 10, 11, 12]]
[[0, 1, 2], [3, 4, 5, 6, 8], [7, 9, 10, 11, 12]]
[[0, 1, 2], [3, 4, 5, 6, 9], [7, 8, 10, 11, 12]]

[['Bob', 'Jane', 'Mary'], ['Martha', 'James', 'Charles', 'Kevin', 'Debbie'], ['Brian', 'Matt', 'Milo', 'Chris', 'Sam']]
[['Bob', 'Jane', 'Mary'], ['Martha', 'James', 'Charles', 'Kevin', 'Brian'], ['Debbie', 'Matt', 'Milo', 'Chris', 'Sam']]
[['Bob', 'Jane', 'Mary'], ['Martha', 'James', 'Charles', 'Kevin', 'Matt'], ['Debbie', 'Brian', 'Milo', 'Chris', 'Sam']]

Edited: fixed some typos in the code.

If you got like here 13 people, you used teams of three until you need a team of four for the other people. Now you have to create an algorithm that will create teams in a size of three to five. I think this variation of members per team is for the problem that the people can't fit in teams of like three. I would create teams of three until I need teams of four or five. Also you can create all teams in all sizes but this is for a higher number of people too much teams.

Related