4
$\begingroup$

I have 4 different items {1, 2, 3, 4}. I want to obtain all possible pairs of two of the items. I have written:

n = 4;
x1 = Tuples[Range@n, n];

Cases[x1, {a_, a_, b_, b_} /; a != b]

gives the desired result:

{{1, 1, 2, 2}, {1, 1, 3, 3}, {1, 1, 4, 4}, {2, 2, 1, 1}, {2, 2, 3, 3}, {2, 2, 4, 4}, {3, 3, 1, 1}, {3, 3, 2, 2}, {3, 3, 4, 4}, {4, 4, 1, 1}, {4, 4, 2, 2}, {4, 4, 3, 3}}

Now I choose

n = 6;
x2 = Tuples[Range@n, n];

Cases[x2, {a_, a_, b_, b_, c_, c_} /; a != b && a != c && b != c];
% // Short

{{1,1,2,2,3,3},{1,1,2,2,4,4},<<116>>,{6,6,5,5,3,3},{6,6,5,5,4,4}}

again gives the desired result.

How would you automate this (for even n)?

Are there better alternatives?

$\endgroup$
2
  • $\begingroup$ @Szabolcs Well almost, but not quite. For Subsets you'll need to generate additional permutations in order to get the desired output, and for Tuples you'll need to throw away cases of repeated pairs. $\endgroup$ Jul 16, 2014 at 17:49
  • $\begingroup$ @Öska Thanks for the edit and Short $\endgroup$
    – eldo
    Jul 16, 2014 at 19:47

2 Answers 2

4
$\begingroup$

This is another approach:

pairRiffle[n_?EvenQ] := Riffle[#, #] & /@ (Permutations[Range@n, {n/2}])

pairRiffle[4]
(* {{1, 1, 2, 2}, {1, 1, 3, 3}, {1, 1, 4, 4}, {2, 2, 1, 1}, {2, 2, 3, 
  3}, {2, 2, 4, 4}, {3, 3, 1, 1}, {3, 3, 2, 2}, {3, 3, 4, 4}, {4, 4, 
  1, 1}, {4, 4, 2, 2}, {4, 4, 3, 3}} *)

Edit: in fact I could do without the Riffle and just use the transformation rule in @Teake Nutma's answer

pairHybrid[n_?EvenQ] :=  Permutations[Range@n, {n/2}] /. x_Integer -> Sequence[x, x]

pairHybrid[10] == Sort@AllPairs[10]
(* True *)
pairRiffle[10] == Sort@AllPairs[10]
(* True *)
$\endgroup$
4
  • 1
    $\begingroup$ +1 for the second argument of Permutations. $\endgroup$ Jul 16, 2014 at 19:14
  • $\begingroup$ Thanks! +1 to you too for the inspiration. $\endgroup$
    – seismatica
    Jul 16, 2014 at 19:16
  • $\begingroup$ @seismatica +1 A funny development :) $\endgroup$
    – eldo
    Jul 16, 2014 at 19:18
  • $\begingroup$ Nice use of Riffle! That's my favorite way to double elements. $\endgroup$
    – Mr.Wizard
    Jul 22, 2014 at 2:54
6
$\begingroup$

This should do the job:

AllPairs[n_?EvenQ] := 
   Flatten[Permutations /@ Subsets[Range[n], {n/2}], 1] /. x_Integer :> Sequence[x, x]

AllPairs[4]
{
  {1, 1, 2, 2}, {2, 2, 1, 1}, {1, 1, 3, 3}, {3, 3, 1, 1}, 
  {1, 1, 4, 4}, {4, 4, 1, 1}, {2, 2, 3, 3}, {3, 3, 2, 2}, 
  {2, 2, 4, 4}, {4, 4, 2, 2}, {3, 3, 4, 4}, {4, 4, 3, 3}
}
$\endgroup$
0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.