Create all possible teams from a list of players

Say I have a list of players and I want to separate them into two teams of identical size. I want to know what are all the possibilities.

Here is some code that works if I have 16 players and want to know all possible combos of Team 1:

  def potential_teams_of_8() do
    num_players = 16
    last = num_players - 1
    # AWLOG the first player is on the team
    for i1 <- 0..0,
        i2 <- (i1 + 1)..(last - 6),
        i3 <- (i2 + 1)..(last - 5),
        i4 <- (i3 + 1)..(last - 4),
        i5 <- (i4 + 1)..(last - 3),
        i6 <- (i5 + 1)..(last - 2),
        i7 <- (i6 + 1)..(last - 1),
        i8 <- (i7 + 1)..last,
        do: [i1, i2, i3, i4, i5, i6, i7, i8]
  end

How do I make this function more general such that it can handle any number of players?

It’s slightly different than combinations. Combinations would give double the number of results.

Team1: 0,1,2,3,4,5,6,7
Team2: 8,9,10,11,12,13,14,15

is identical to

Team1: 8,9,10,11,12,13,14,15
Team2: 0,1,2,3,4,5,6,7

So the number of combos is halved.

edit: apologies, misread the for loop

Are there only ever 2 teams?

That is, do you need to also be able to calculate, e.g. splitting up 9 players into 3 teams of 3?

Edit: I saw you clearly stated “2 teams” so ignore this question.

If you’re not willing to devise the algorithm then I’d think Combinatorics.n_combinations/2 will serve you fine.

1 Like

Looking at the library proposed by dimitarvp, you could adapt it something like this for your specific use case:

defmodule Comb do
    defp n_comb(0, _list), do: [[]]
    defp n_comb(_, []), do: []

    defp n_comb(n, [h | t]) do
        list = for l <- n_comb(n-1, t), do: [h | l]
        list ++ n_comb(n, t)
    end

    def n_comb(list) do
        n = trunc(length(list)/2)
        for i <- n_comb(n-1, tl(list)),
            do: [hd(list) | i]
    end
end
1 Like

Thanks for your answer! :grinning: This works for when the list is of even size and the number of players on each team is exactly the same.

But I need a slight adjustment for when the list size is odd. For example if list size is 5 then I should get 10 results where each list in the result is of size 2. Effectively I could just call the Combinations library but wondering if I could somehow adjust what you wrote.

When list size is even I have duplicates of
Team1: [1,2]
Team2: [3,4]

is duplicate of
Team1: [3,4]
Team2: [1,2]

And your code correctly removes these duplicates.

But with odd size list
Team1: [1,2]
Team2: [3,4,5]

Has no duplicates. So our combinations should just be the same as

1..5 |> Combination.combine(2)

So if you allow for teams to be different sizes, when No. of players is odd, then like you said there is no duplicates and you can run the library function. Maybe run a case to check if num_players is odd or even and redirect the flow accordingly.