5
$\begingroup$

I want to canonically reorganize (like Sort) a sequence of four objects seq[a,b,c,d], but the only manipulations allowed are RotateLeft (any number of times) and Reverse.

The element on the left should have the lowest value.

For example, seq[b,c,a,0] should go to seq[0,a,c,b]

(below are some more examples).

$(1)\enspace\{c,b,d,a\} \longrightarrow \{a,c,b,d\}\\ (2)\enspace \{d,a,b,a\} \longrightarrow \{a,b,a,d\}\\ (3)\enspace\{0,b,a,0\} \longrightarrow \{0,0,a,b\}$

Is there a built-in Mathematica function to do this? How can this be done efficiently in Mathematica?

$\endgroup$
9
$\begingroup$

You basically want to permute the elements of the list among some specified set of permutations, and find the ordering of the list among these permutations that is canonically "first". The set of permutations you're interested in is a subgroup of the permutation group $S_n$, generated by two generators, one of which rotates all elements one position to the left and the other of which reverses the elements.

We can use Mathematica's built-in group theory functions to do this. PermutationGroup specifies a group generated by any number of permutations, and GroupElements tells Mathematica to explicitly calculate all the elements of this group. We can then apply all of these permutations to the original list, apply Sort to that, and then take the first element of the sorted list of permuted lists. Like so:

rotrevsort[listin__] := 
 Module[{list = listin, n, permlist},
  n = Length[list];
  permlist = GroupElements[PermutationGroup[{PermutationCycles[RotateLeft[Range[n]]], 
                                             PermutationCycles[Reverse[Range[n]]]}]];
  First[Sort[Permute[list, #] & /@ permlist]]
 ]

rotrevsort[{c, b, d, a}]
rotrevsort[{d, a, b, a}]
rotrevsort[{0, b, a, 0}]

(* {a, c, b, d} *)
(* {a, b, a, d} *)
(* {0, 0, a, b} *)

By the way, your group is only of order $2n$, i.e., there are only $2n$ possible permutations of the list that you need to sort. (For those who know group theory, the subgroup of $S_n$ we're looking at is isomorphic to the dihedral group $D_n$.) So if we assume that Sort's algorithms don't take significantly longer to sort a list of $2n$ elements than they do a list of $n$ elements, I wouldn't expect that sorting the whole list of valid permutations would be significantly less efficient than sorting the elements of the list themselves.

$\endgroup$
  • $\begingroup$ I'd never heard of PermutationCylces, PermutationGroup and GroupElements. Very handy functions! $\endgroup$ – QuantumDot Jun 12 '15 at 19:40
  • 1
    $\begingroup$ @QuantumDot I believe you have but that's OK, I forget things too. ;^) $\endgroup$ – Mr.Wizard Jul 15 '15 at 1:49
  • $\begingroup$ Comparing two lists takes $O(n)$ time, though, so sorting the list of permutations should take $O(n^2\log n)$ compared to the $O(n\log n)$ time for sorting the original list. $\endgroup$ – Rahul Jan 27 '17 at 16:48
3
$\begingroup$

Just a small simplification of Michael Seifert's excellent answer, using the fact that you can pass a group directly to Permute as its second argument.

groupForN[n_Integer?Positive] :=
  PermutationGroup[
     {PermutationCycles@RotateLeft@#,
      PermutationCycles@Reverse@#}] &[Range@n];

smallestByRotRev[l_List] :=
  First@Sort[Permute[l, groupForN@Length@l]];

This gives the same answers:

smallestByRotRev[{c, b, d, a}]
(* {a, c, b, d} *)     

smallestByRotRev[{d, a, b, a}]
(* {a, b, a, d} *)     

smallestByRotRev[{0, b, a, 0}]
(* {0, 0, a, b} *)
$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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