In the related question โGenerating all unique pairwise permutationsโ ( here ), an algorithm is provided for creating a cyclic graph for any given n. That is, every possible set of matches / pairs for n teams.
So, for n = 4 (assuming exceptional) this will be:
[0, 3], [1, 2] [0, 2], [3, 1] [0, 1], [2, 3]
Now we have each of these sections, we just need to find their permutations to get a complete list of pairs. those. [0, 3], [1, 2] is a member of a group of four: [0, 3], [1, 2] (itself) and [3, 0], [1, 2] and [0, 3], [2, 1] and [3, 0], [2, 1] .
To get all members of a group from one member, you take a permutation where each pair can be upside down or not upside down (if they were, for example, n-tuples instead of pairs, then there will be n! Options for each). Since you have two pairs and options, each section gives 2 ^ 2 pairs. So you have only 12.
The code for this is where round_robin (n) returns a list of lists of pairs. So round_robin (4) โ [[[[0, 3], [1, 2]], [[0, 2], [3, 1]], [[0, 1], [2, 3]]] .
def pairs(n): for elem in round_robin(n): for first in [elem[0], elem[0][::-1]]: for second in [elem[1], elem[1][::-1]]: print (first, second)
This method generates less than you want, and then goes up instead of generating more than you want and getting rid of the bundle, so it should be more efficient. ([:: - 1] is voodoo for changing the list permanently).
And here is a circular algorithm from another publication (written by Theodros Zelleke)
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))