7
$\begingroup$

In orden to list all derangements of five elements, I wrote the following (very ugly) code:

elementos = {Red, Blue, Green, Orange, Black};
permutaciones = Permutations[elementos];
desarreglos = Select[permutaciones, #[[1]]!=elementos[[1]]&&#[[2]]!=elementos[[2]]&&#[[3]]!=elementos[[3]]&&#[[4]]!=elementos[[4]]&&#[[5]]!=elementos[[5]]&]; 
Length[desarreglos];
desarreglos//Grid

I am unable to figure out how to avoid writing all the #[[i]]!=elementos[[i]] stuff.

Any help would be highly appreciated.

TIA.

$\endgroup$
3
  • 1
    $\begingroup$ You may use a recursive formula for the number of derangements in a set of length $n$: $ !n=(n-1)\big(!(n-1)+!(n-2)\big)$. $\endgroup$
    – yarchik
    Commented Nov 15 at 9:25
  • 2
    $\begingroup$ You can use this resource function: ResourceFunction["Derangements"] $\endgroup$
    – flinty
    Commented Nov 15 at 10:33
  • 3
    $\begingroup$ Related: Faster derangements? $\endgroup$
    – user1066
    Commented Nov 15 at 14:57

3 Answers 3

7
$\begingroup$

You can use MapThread like this:

elementos = {Red, Blue, Green, Orange, Black};
permutaciones = Permutations[elementos];
desarreglos = Select[permutaciones,And @@ MapThread[Not@*Equal, {elementos, #}] &];
Length[desarreglos]
desarreglos // Grid
$\endgroup$
2
  • 3
    $\begingroup$ You can replace Not @* Equal by Unequal. $\endgroup$ Commented Nov 15 at 10:31
  • $\begingroup$ Brilliant! Thanks!! $\endgroup$ Commented Nov 16 at 11:17
5
$\begingroup$

a slightly longer dfs method

(* Define the DFS-based derangement finder *)
FindDerangementsDFS[elements_List] := Module[
  {n = Length[elements], used, currentPerm, derangements, dfs},
  
  used = Table[False, {n}];
  currentPerm = {};
  derangements = {};
  
  dfs[pos_] := Module[{},
    (* If we've built a complete permutation *)
    If[pos == n + 1,
      AppendTo[derangements, currentPerm];
      Return[]
    ];
    
    (* Try placing each element at the current position *)
    Do[
      (* Skip if element is already used or would be in original position *)
      If[!used[[i]] && i != pos,
        used[[i]] = True;
        AppendTo[currentPerm, elements[[i]]];
        dfs[pos + 1];
        currentPerm = Most[currentPerm];
        used[[i]] = False;
      ],
      {i, 1, n}
    ];
  ];
  
  dfs[1];
  derangements
];

(* Example usage *)
elementos = {Red, Blue, Green, Orange, Black};
desarreglos = FindDerangementsDFS[elementos];

(* Print results *)
Print["Number of derangements: ", Length[desarreglos]];
Print["\nAll derangements:"];
desarreglos

enter image description here

$\endgroup$
5
$\begingroup$

Community Wiki

Wolfram Mathworld gives an interesting function for Derangement, which uses PermutationSupport, a modification of which is the following:

(With[{x = Length@elementos}, {y = Permutations[Range[x]]}, 
 Pick[y, Length@*PermutationSupport /@ y, x]] // Map[elementos[[#]] &])

Original code

elementos[[#]]& /@ Pick[#, Length@*PermutationSupport /@ #, Length@elementos]&
 @Permutations[Range@Length@elementos]

In addition

There is also PermutationLength, which should work just as well?

(With[{x = Length@elementos}, {y = Permutations[Range[x]]}, 
 Pick[y, PermutationLength /@ y, x]] // Map[elementos[[#]] &])

enter image description here

$\endgroup$

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