Python: creating all pairwise unique pairings

I am looking for the Pythonic method for generating all pairwise unique unique pairs (where pairing is a system consisting of pairs, and pairwise unique indicates that (a,b) โ‰  (b,a) ) for a set containing even numbers of n elements .

I like the code here :

 for perm in itertools.permutations(range(n)): print zip(perm[::2], perm[1::2]) 

except that it generates all unique pairwise unique pairs, or (n/2)! times more pairs than I want (redundancy) which, although I can filter out, are really afraid of my program as a whole n .

That is, for n = 4 , I am looking for the following result (12 unique pairs):

 [(0, 1), (2, 3)] [(0, 1), (3, 2)] [(1, 0), (2, 3)] [(1, 0), (3, 2)] [(1, 2), (0, 3)] [(1, 2), (3, 0)] [(1, 3), (0, 2)] [(2, 0), (1, 3)] [(2, 0), (3, 1)] [(3, 1), (0, 2)] [(0, 3), (2, 1)] [(3, 0), (2, 1)] 

Note that (a,b) โ‰  (b,a) .

Is it possible? I also support a function that generates 3 unpaired unique pairings for n = 4 , where (a,b) = (b,a) , since direct switching is what I need from there. My main goal is to avoid unnecessary rearrangements of the order of pairs in pairing.

Thank you in advance for your help and suggestions - I really appreciate it.

+6
source share
3 answers

I think this gives you the basic pairs that you need: 1, when N=2 ; 3 when N=4 ; 15 when N=6 ; 105 when n=8 etc.

 import sys def pairings(remainder, partial = None): partial = partial or [] if len(remainder) == 0: yield partial else: for i in xrange(1, len(remainder)): pair = [[remainder[0], remainder[i]]] r1 = remainder[1:i] r2 = remainder[i+1:] for p in pairings(r1 + r2, partial + pair): yield p def main(): n = int(sys.argv[1]) items = list(range(n)) for p in pairings(items): print p main() 
+2
source

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)) 
0
source

I'm not sure if I understood the problem well, anyway, here is my solution:

 import itertools n = 4 out = set() for perm in itertools.permutations(range(n)): pairs = tuple(sorted(zip(perm[::2], perm[1::2]))) out.add(pairs) for i, p in enumerate(sorted(out)): print i,p 

it returns 12 unique pairs for n = 4 and 120 for n = 6.

0
source

Source: https://habr.com/ru/post/944826/


All Articles