I have a number of bins. Each bin accommodates only one ball.
Let's say, I have
Na number of red balls
Nb number of blue balls
Nc number of green balls
and so on.
I want to find out all possible ways of placing the balls into bins of length (Na+Nb+Nc).
For example, let's say I have only two red balls and two blue balls. I want to place them into 4 bins. The possible ways of arrangements are:
R R B B
R B R B
R B B R
B R R B
B R B R
B B R R
( I hope I did not miss any combination)
Is there any easy way to generate the indices for the different colors, for example:
First row is : R=(0,1) B=(2,3)
Second row is : R=(0,2) B=(1,3)
Is there an easy way to generate this in numpy?
The bins actually have different weights, something like:
[0.1, 0.3, 0.2, 0.5]
So for the combination R R B B represented as R at (0,1) and B at (2,3) , the total weight for R is 0.1+0.3=0.4 and for B is 0.2+0.5=0.7
I ultimately am interested in the total weight for each color in the different arrangements and want to choose the best one from another cost function f(total_weight(R), total_weight(B)). Any comments if the generation of total weight could be done in a different easy way in numpy?
Here's a "multi-combinations" implementation that doesn't require eliminating duplicate permutations. The first argument, n, is the list [Na, Nb, Nc, ...].
It is implemented as a recursive generator, so you can iterate through the combinations without having them all in memory at once. You say in a comment that Na + Nb + ... is typically around 20 but could be as high as 50 or 100. That means you almost certainly do not want to store all the combinations in memory. Consider an example with four "colors" where Na = Nb = Nc = Nd = 5. The number of combinations is choose(20, 5) * choose(15, 5) * choose(10, 5) = 11732745024, where choose(n, k) is the binomial coefficient. My computer has just 16 GB of RAM, so the storage required for that number of combinations would far exceed my computer's memory.
from itertools import combinations
def multicombinations(n, bins=None):
if bins is None:
bins = set(range(sum(n)))
if len(n) == 0:
yield []
else:
for c in combinations(bins, n[0]):
for t in multicombinations(n[1:], bins - set(c)):
yield [c] + t
It generates a list of tuples. That is, where your description of the first row is "First row is : R=(0,1) B=(2,3)", the first value generated by multicombinations([2, 2]) is [(0, 1), (2, 3)]. (This might not be the best format for the result, given the description of the weight calculation that you want to do next.)
Some examples:
In [74]: list(multicombinations([2, 2]))
Out[74]:
[[(0, 1), (2, 3)],
[(0, 2), (1, 3)],
[(0, 3), (1, 2)],
[(1, 2), (0, 3)],
[(1, 3), (0, 2)],
[(2, 3), (0, 1)]]
In [75]: list(multicombinations([3, 2]))
Out[75]:
[[(0, 1, 2), (3, 4)],
[(0, 1, 3), (2, 4)],
[(0, 1, 4), (2, 3)],
[(0, 2, 3), (1, 4)],
[(0, 2, 4), (1, 3)],
[(0, 3, 4), (1, 2)],
[(1, 2, 3), (0, 4)],
[(1, 2, 4), (0, 3)],
[(1, 3, 4), (0, 2)],
[(2, 3, 4), (0, 1)]]
In [76]: list(multicombinations([2, 3, 2]))
Out[76]:
[[(0, 1), (2, 3, 4), (5, 6)],
[(0, 1), (2, 3, 5), (4, 6)],
[(0, 1), (2, 3, 6), (4, 5)],
[(0, 1), (2, 4, 5), (3, 6)],
[(0, 1), (2, 4, 6), (3, 5)],
[(0, 1), (2, 5, 6), (3, 4)],
[(0, 1), (3, 4, 5), (2, 6)],
[(0, 1), (3, 4, 6), (2, 5)],
[(0, 1), (3, 5, 6), (2, 4)],
[(0, 1), (4, 5, 6), (2, 3)],
[(0, 2), (1, 3, 4), (5, 6)],
[(0, 2), (1, 3, 5), (4, 6)],
[(0, 2), (1, 3, 6), (4, 5)],
[(0, 2), (1, 4, 5), (3, 6)],
[(0, 2), (1, 4, 6), (3, 5)],
[(0, 2), (1, 5, 6), (3, 4)],
[(0, 2), (3, 4, 5), (1, 6)],
[(0, 2), (3, 4, 6), (1, 5)],
[(0, 2), (3, 5, 6), (1, 4)],
[(0, 2), (4, 5, 6), (1, 3)],
[(0, 3), (1, 2, 4), (5, 6)],
[(0, 3), (1, 2, 5), (4, 6)],
[(0, 3), (1, 2, 6), (4, 5)],
[(0, 3), (1, 4, 5), (2, 6)],
[(0, 3), (1, 4, 6), (2, 5)],
[(0, 3), (1, 5, 6), (2, 4)],
[(0, 3), (2, 4, 5), (1, 6)],
[(0, 3), (2, 4, 6), (1, 5)],
[(0, 3), (2, 5, 6), (1, 4)],
[(0, 3), (4, 5, 6), (1, 2)],
[(0, 4), (1, 2, 3), (5, 6)],
[(0, 4), (1, 2, 5), (3, 6)],
[(0, 4), (1, 2, 6), (3, 5)],
[(0, 4), (1, 3, 5), (2, 6)],
[(0, 4), (1, 3, 6), (2, 5)],
[(0, 4), (1, 5, 6), (2, 3)],
[(0, 4), (2, 3, 5), (1, 6)],
[(0, 4), (2, 3, 6), (1, 5)],
[(0, 4), (2, 5, 6), (1, 3)],
[(0, 4), (3, 5, 6), (1, 2)],
[(0, 5), (1, 2, 3), (4, 6)],
[(0, 5), (1, 2, 4), (3, 6)],
[(0, 5), (1, 2, 6), (3, 4)],
[(0, 5), (1, 3, 4), (2, 6)],
[(0, 5), (1, 3, 6), (2, 4)],
[(0, 5), (1, 4, 6), (2, 3)],
[(0, 5), (2, 3, 4), (1, 6)],
[(0, 5), (2, 3, 6), (1, 4)],
[(0, 5), (2, 4, 6), (1, 3)],
[(0, 5), (3, 4, 6), (1, 2)],
[(0, 6), (1, 2, 3), (4, 5)],
[(0, 6), (1, 2, 4), (3, 5)],
[(0, 6), (1, 2, 5), (3, 4)],
[(0, 6), (1, 3, 4), (2, 5)],
[(0, 6), (1, 3, 5), (2, 4)],
[(0, 6), (1, 4, 5), (2, 3)],
[(0, 6), (2, 3, 4), (1, 5)],
[(0, 6), (2, 3, 5), (1, 4)],
[(0, 6), (2, 4, 5), (1, 3)],
[(0, 6), (3, 4, 5), (1, 2)],
[(1, 2), (0, 3, 4), (5, 6)],
[(1, 2), (0, 3, 5), (4, 6)],
[(1, 2), (0, 3, 6), (4, 5)],
[(1, 2), (0, 4, 5), (3, 6)],
[(1, 2), (0, 4, 6), (3, 5)],
[(1, 2), (0, 5, 6), (3, 4)],
[(1, 2), (3, 4, 5), (0, 6)],
[(1, 2), (3, 4, 6), (0, 5)],
[(1, 2), (3, 5, 6), (0, 4)],
[(1, 2), (4, 5, 6), (0, 3)],
[(1, 3), (0, 2, 4), (5, 6)],
[(1, 3), (0, 2, 5), (4, 6)],
[(1, 3), (0, 2, 6), (4, 5)],
[(1, 3), (0, 4, 5), (2, 6)],
[(1, 3), (0, 4, 6), (2, 5)],
[(1, 3), (0, 5, 6), (2, 4)],
[(1, 3), (2, 4, 5), (0, 6)],
[(1, 3), (2, 4, 6), (0, 5)],
[(1, 3), (2, 5, 6), (0, 4)],
[(1, 3), (4, 5, 6), (0, 2)],
[(1, 4), (0, 2, 3), (5, 6)],
[(1, 4), (0, 2, 5), (3, 6)],
[(1, 4), (0, 2, 6), (3, 5)],
[(1, 4), (0, 3, 5), (2, 6)],
[(1, 4), (0, 3, 6), (2, 5)],
[(1, 4), (0, 5, 6), (2, 3)],
[(1, 4), (2, 3, 5), (0, 6)],
[(1, 4), (2, 3, 6), (0, 5)],
[(1, 4), (2, 5, 6), (0, 3)],
[(1, 4), (3, 5, 6), (0, 2)],
[(1, 5), (0, 2, 3), (4, 6)],
[(1, 5), (0, 2, 4), (3, 6)],
[(1, 5), (0, 2, 6), (3, 4)],
[(1, 5), (0, 3, 4), (2, 6)],
[(1, 5), (0, 3, 6), (2, 4)],
[(1, 5), (0, 4, 6), (2, 3)],
[(1, 5), (2, 3, 4), (0, 6)],
[(1, 5), (2, 3, 6), (0, 4)],
[(1, 5), (2, 4, 6), (0, 3)],
[(1, 5), (3, 4, 6), (0, 2)],
[(1, 6), (0, 2, 3), (4, 5)],
[(1, 6), (0, 2, 4), (3, 5)],
[(1, 6), (0, 2, 5), (3, 4)],
[(1, 6), (0, 3, 4), (2, 5)],
[(1, 6), (0, 3, 5), (2, 4)],
[(1, 6), (0, 4, 5), (2, 3)],
[(1, 6), (2, 3, 4), (0, 5)],
[(1, 6), (2, 3, 5), (0, 4)],
[(1, 6), (2, 4, 5), (0, 3)],
[(1, 6), (3, 4, 5), (0, 2)],
[(2, 3), (0, 1, 4), (5, 6)],
[(2, 3), (0, 1, 5), (4, 6)],
[(2, 3), (0, 1, 6), (4, 5)],
[(2, 3), (0, 4, 5), (1, 6)],
[(2, 3), (0, 4, 6), (1, 5)],
[(2, 3), (0, 5, 6), (1, 4)],
[(2, 3), (1, 4, 5), (0, 6)],
[(2, 3), (1, 4, 6), (0, 5)],
[(2, 3), (1, 5, 6), (0, 4)],
[(2, 3), (4, 5, 6), (0, 1)],
[(2, 4), (0, 1, 3), (5, 6)],
[(2, 4), (0, 1, 5), (3, 6)],
[(2, 4), (0, 1, 6), (3, 5)],
[(2, 4), (0, 3, 5), (1, 6)],
[(2, 4), (0, 3, 6), (1, 5)],
[(2, 4), (0, 5, 6), (1, 3)],
[(2, 4), (1, 3, 5), (0, 6)],
[(2, 4), (1, 3, 6), (0, 5)],
[(2, 4), (1, 5, 6), (0, 3)],
[(2, 4), (3, 5, 6), (0, 1)],
[(2, 5), (0, 1, 3), (4, 6)],
[(2, 5), (0, 1, 4), (3, 6)],
[(2, 5), (0, 1, 6), (3, 4)],
[(2, 5), (0, 3, 4), (1, 6)],
[(2, 5), (0, 3, 6), (1, 4)],
[(2, 5), (0, 4, 6), (1, 3)],
[(2, 5), (1, 3, 4), (0, 6)],
[(2, 5), (1, 3, 6), (0, 4)],
[(2, 5), (1, 4, 6), (0, 3)],
[(2, 5), (3, 4, 6), (0, 1)],
[(2, 6), (0, 1, 3), (4, 5)],
[(2, 6), (0, 1, 4), (3, 5)],
[(2, 6), (0, 1, 5), (3, 4)],
[(2, 6), (0, 3, 4), (1, 5)],
[(2, 6), (0, 3, 5), (1, 4)],
[(2, 6), (0, 4, 5), (1, 3)],
[(2, 6), (1, 3, 4), (0, 5)],
[(2, 6), (1, 3, 5), (0, 4)],
[(2, 6), (1, 4, 5), (0, 3)],
[(2, 6), (3, 4, 5), (0, 1)],
[(3, 4), (0, 1, 2), (5, 6)],
[(3, 4), (0, 1, 5), (2, 6)],
[(3, 4), (0, 1, 6), (2, 5)],
[(3, 4), (0, 2, 5), (1, 6)],
[(3, 4), (0, 2, 6), (1, 5)],
[(3, 4), (0, 5, 6), (1, 2)],
[(3, 4), (1, 2, 5), (0, 6)],
[(3, 4), (1, 2, 6), (0, 5)],
[(3, 4), (1, 5, 6), (0, 2)],
[(3, 4), (2, 5, 6), (0, 1)],
[(3, 5), (0, 1, 2), (4, 6)],
[(3, 5), (0, 1, 4), (2, 6)],
[(3, 5), (0, 1, 6), (2, 4)],
[(3, 5), (0, 2, 4), (1, 6)],
[(3, 5), (0, 2, 6), (1, 4)],
[(3, 5), (0, 4, 6), (1, 2)],
[(3, 5), (1, 2, 4), (0, 6)],
[(3, 5), (1, 2, 6), (0, 4)],
[(3, 5), (1, 4, 6), (0, 2)],
[(3, 5), (2, 4, 6), (0, 1)],
[(3, 6), (0, 1, 2), (4, 5)],
[(3, 6), (0, 1, 4), (2, 5)],
[(3, 6), (0, 1, 5), (2, 4)],
[(3, 6), (0, 2, 4), (1, 5)],
[(3, 6), (0, 2, 5), (1, 4)],
[(3, 6), (0, 4, 5), (1, 2)],
[(3, 6), (1, 2, 4), (0, 5)],
[(3, 6), (1, 2, 5), (0, 4)],
[(3, 6), (1, 4, 5), (0, 2)],
[(3, 6), (2, 4, 5), (0, 1)],
[(4, 5), (0, 1, 2), (3, 6)],
[(4, 5), (0, 1, 3), (2, 6)],
[(4, 5), (0, 1, 6), (2, 3)],
[(4, 5), (0, 2, 3), (1, 6)],
[(4, 5), (0, 2, 6), (1, 3)],
[(4, 5), (0, 3, 6), (1, 2)],
[(4, 5), (1, 2, 3), (0, 6)],
[(4, 5), (1, 2, 6), (0, 3)],
[(4, 5), (1, 3, 6), (0, 2)],
[(4, 5), (2, 3, 6), (0, 1)],
[(4, 6), (0, 1, 2), (3, 5)],
[(4, 6), (0, 1, 3), (2, 5)],
[(4, 6), (0, 1, 5), (2, 3)],
[(4, 6), (0, 2, 3), (1, 5)],
[(4, 6), (0, 2, 5), (1, 3)],
[(4, 6), (0, 3, 5), (1, 2)],
[(4, 6), (1, 2, 3), (0, 5)],
[(4, 6), (1, 2, 5), (0, 3)],
[(4, 6), (1, 3, 5), (0, 2)],
[(4, 6), (2, 3, 5), (0, 1)],
[(5, 6), (0, 1, 2), (3, 4)],
[(5, 6), (0, 1, 3), (2, 4)],
[(5, 6), (0, 1, 4), (2, 3)],
[(5, 6), (0, 2, 3), (1, 4)],
[(5, 6), (0, 2, 4), (1, 3)],
[(5, 6), (0, 3, 4), (1, 2)],
[(5, 6), (1, 2, 3), (0, 4)],
[(5, 6), (1, 2, 4), (0, 3)],
[(5, 6), (1, 3, 4), (0, 2)],
[(5, 6), (2, 3, 4), (0, 1)]]
Generate the permutations and remove duplicates.
>>> import itertools
>>> Na = 2
>>> Nb = 2
>>> p = itertools.permutations(['R']*Na + ['B']*Nb)
>>> for perm in sorted(list(set(p)), reverse=True):
... print perm
...
('R', 'R', 'B', 'B')
('R', 'B', 'R', 'B')
('R', 'B', 'B', 'R')
('B', 'R', 'R', 'B')
('B', 'R', 'B', 'R')
('B', 'B', 'R', 'R')
You can solve that with itertools:
import itertools
last = None
result = []
for v in itertools.permutations(['A','A','B','B']):
key = "".join(v)
if key == last: continue
last = key
result.append(v)
print result
Here is one possible way of implementing:
def permutations(colors, l):
if l == 0:
yield []
else:
for i in range(len(colors)):
if colors[i]:
la = colors[:i]
lb = [colors[i][1:]]
lc = colors[i + 1:]
choice = colors[i][0]
for rest in permutations(la + lb + lc, l - 1):
yield [choice] + rest
Usage:
for choice in permutations([['R'] * 2, ['B'] * 2], 4):
print(choice)
['R', 'R', 'B', 'B']
['R', 'B', 'R', 'B']
['R', 'B', 'B', 'R']
['B', 'R', 'R', 'B']
['B', 'R', 'B', 'R']
['B', 'B', 'R', 'R']
I need to generate all possible pairings, but with the constraint that a particular pairing only occurs once in the results. So for example:
import itertools
for perm in itertools.permutations(range(9)):
print zip(perm[::2], perm[1::2])
generates all possible two-paired permutations; here's a small subset of the output:
...
[(8, 4), (7, 6), (5, 3), (0, 2)]
[(8, 4), (7, 6), (5, 3), (1, 0)]
[(8, 4), (7, 6), (5, 3), (1, 2)]
[(8, 4), (7, 6), (5, 3), (2, 0)]
[(8, 4), (7, 6), (5, 3), (2, 1)]
[(8, 5), (0, 1), (2, 3), (4, 6)]
[(8, 5), (0, 1), (2, 3), (4, 7)]
[(8, 5), (0, 1), (2, 3), (6, 4)]
[(8, 5), (0, 1), (2, 3), (6, 7)]
[(8, 5), (0, 1), (2, 3), (7, 4)]
[(8, 5), (0, 1), (2, 3), (7, 6)]
[(8, 5), (0, 1), (2, 4), (3, 6)]
[(8, 5), (0, 1), (2, 4), (3, 7)]
[(8, 5), (0, 1), (2, 4), (6, 3)]
...
How do I further filter it so that I only ever see (8,4) once (throughout all of the filtered permutations), and (8,5) only once, and (0,1) only once, and (4,7) only once, etc.?
Basically I want the permutations such that each two-element pairing happens only once.
I'll bet there's an additional itertool that would solve this but I'm not expert enough to know what it is.
Update: Gareth Rees is correct -- I was completely unaware that I was trying to solve the round-robin problem. I have an additional constraint which is that what I'm doing is grouping people for pair-programming exercises. Thus, if I have an odd number of people, I need to create a group of three to include an odd person for each exercise. My current thinking is to (1) make an even number of people by adding in an invisible person. Then, after the pairing, find the person paired with the invisible person and randomly place them into an existing group to form a team of three. However, I wonder if there isn't already an algorithm or adjustment to round-robin that does this in a better way.
Update 2: Theodros' solution produces exactly the right result without the inelegant futzing about I describe above. Everyone's been amazingly helpful.
I'd like to share a different implementation of round-robin scheduling that makes use of the deque-data structure from the Standard Library:
from collections import deque
def round_robin_even(d, n):
for i in range(n - 1):
yield [[d[j], d[-j-1]] for j in range(n/2)]
d[0], d[-1] = d[-1], d[0]
d.rotate()
def round_robin_odd(d, n):
for i in range(n):
yield [[d[j], d[-j-1]] for j in range(n/2)]
d.rotate()
def round_robin(n):
d = deque(range(n))
if n % 2 == 0:
return list(round_robin_even(d, n))
else:
return list(round_robin_odd(d, n))
print round_robin(5)
[[[0, 4], [1, 3]],
[[4, 3], [0, 2]],
[[3, 2], [4, 1]],
[[2, 1], [3, 0]],
[[1, 0], [2, 4]]]
print round_robin(2)
[[[0, 1]]]
It puts the objects(ints here) in the deque. Then it rotates and builds consecutive pairs taking from both ends towards the middle. One can imagine this as folding the deque in the middle back on itself. To make it clear:
Case uneven elements:
round 1 round 2 # pairs are those numbers that sit
---------- --------- # on top of each other
0 1 2 3 4 8 0 1 2 3
8 7 6 5 7 6 5 4
In case of even elements an additional step is required.
(I missed the first time cause I only checked the uneven case. This yielded a horribly wrong algorithm... which shows me how important it is to check edge cases when implementing an algorithm...)
This special step is that I swap the two leftmost elements (which are the first and last elements of the deque) before each rotation -- this means the 0 stays all the time upper left.
Case even elements:
round 1 round 2 # pairs are those numbers that sit
---------- --------- # on top of each other
0 1 2 3 0 7 1 2
7 6 5 4 6 5 4 3
What haunts me about this version is the amount of code duplication, but I couldn't find a way to improve while keeping it as readable. Here's my first implementation, which is less readable IMO:
def round_robin(n):
is_even = (n % 2 == 0)
schedule = []
d = deque(range(n))
for i in range(2 * ((n - 1) / 2) + 1):
schedule.append(
[[d[j], d[-j-1]] for j in range(n/2)])
if is_even:
d[0], d[-1] = d[-1], d[0]
d.rotate()
return schedule
Update to account for the updated question:
To allow in the uneven case for groups of three you just need to change round_robin_odd(d, n):
def round_robin_odd(d, n):
for i in range(n):
h = [[d[j], d[-j-1]] for j in range(n/2)]
h[-1].append(d[n/2])
yield h
d.rotate()
This gives:
print round_robin(5)
[[[0, 4], [1, 3, 2]],
[[4, 3], [0, 2, 1]],
[[3, 2], [4, 1, 0]],
[[2, 1], [3, 0, 4]],
[[1, 0], [2, 4, 3]]]
Pass the list to set to get make sure each tuple only exists once.
>>> from itertools import permutations
>>> set( [ zip( perm[::2], perm[1::2] ) for perm in permutations( range( 9 ) ) ] )
set([(7, 3), (4, 7), (1, 3), (4, 8), (5, 6), (2, 8), (8, 0), (3, 2), (2, 1), (6, 2), (1, 6), (5, 1), (3, 7), (2, 5), (8, 5), (0, 3), (5, 8), (4, 0), (1, 2), (3, 8), (3, 1), (6, 7), (2, 0), (8, 1), (7, 6), (3, 0), (6, 3), (1, 5), (7, 2), (3, 6), (0, 4), (8, 6), (3, 5), (4, 1), (6, 4), (5, 4), (2, 6), (8, 2), (2, 7), (7, 1), (4, 5), (8, 3), (1, 4), (6, 0), (7, 5), (2, 3), (0, 7), (8, 7), (4, 2), (1, 0), (0, 8), (6, 5), (4, 6), (0, 1), (5, 3), (7, 0), (6, 8), (3, 4), (6, 1), (5, 7), (5, 2), (0, 2), (7, 4), (0, 6), (1, 8), (4, 3), (1, 7), (0, 5), (5, 0), (7, 8), (2, 4), (8, 4)])
From your description you want each of the 2-tuple permutations of the range( 9 ) the above should give you all of the various permutations, based on your code. But, this is pretty inefficient.
However you can further simplify your code by doing the following:
>>> list( permutations( range( 9 ), 2 ) )
[(0, 1), (0, 2), (0, 3), (0, 4), (0, 5), (0, 6), (0, 7), (0, 8), (1, 0), (1, 2), (1, 3), (1, 4), (1, 5), (1, 6), (1, 7), (1, 8), (2, 0), (2, 1), (2, 3), (2, 4), (2, 5), (2, 6), (2, 7), (2, 8), (3, 0), (3, 1), (3, 2), (3, 4), (3, 5), (3, 6), (3, 7), (3, 8), (4, 0), (4, 1), (4, 2), (4, 3), (4, 5), (4, 6), (4, 7), (4, 8), (5, 0), (5, 1), (5, 2), (5, 3), (5, 4), (5, 6), (5, 7), (5, 8), (6, 0), (6, 1), (6, 2), (6, 3), (6, 4), (6, 5), (6, 7), (6, 8), (7, 0), (7, 1), (7, 2), (7, 3), (7, 4), (7, 5), (7, 6), (7, 8), (8, 0), (8, 1), (8, 2), (8, 3), (8, 4), (8, 5), (8, 6), (8, 7)]
The method permutations also takes a length argument that will allow you to specify the length of the tuple returned. So, you were using the correct itertool provided function, but missed the tuple length parameter.
itertools.permutations documentation
As MatthieuW says in this answer, it looks as if you are trying to generate a schedule for a round-robin tournament. This can be easily generated using this algorithm, the main difficulty being the handling of an odd number of teams (when each team gets a bye in one round).
def round_robin_schedule(n):
"""
Generate a round-robin tournament schedule for `n` teams.
"""
m = n + n % 2 # Round up to even number.
for r in xrange(m - 1):
def pairing():
if r < n - 1:
yield r, n - 1
for i in xrange(m // 2 - 1):
p, q = (r + i + 1) % (m - 1), (m + r - i - 2) % (m - 1)
if p < n - 1 and q < n - 1:
yield p, q
yield list(pairing())
For example, with nine teams:
>>> list(round_robin_schedule(9))
[[(0, 8), (2, 7), (3, 6), (4, 5)],
[(1, 8), (2, 0), (4, 7), (5, 6)],
[(2, 8), (3, 1), (4, 0), (6, 7)],
[(3, 8), (4, 2), (5, 1), (6, 0)],
[(4, 8), (5, 3), (6, 2), (7, 1)],
[(5, 8), (6, 4), (7, 3), (0, 1)],
[(6, 8), (7, 5), (0, 3), (1, 2)],
[(7, 8), (0, 5), (1, 4), (2, 3)],
[(0, 7), (1, 6), (2, 5), (3, 4)]]