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$

2 Answers 2

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$
3
  • $\begingroup$ I'd never heard of PermutationCylces, PermutationGroup and GroupElements. Very handy functions! $\endgroup$
    – QuantumDot
    Jun 12, 2015 at 19:40
  • 1
    $\begingroup$ @QuantumDot I believe you have but that's OK, I forget things too. ;^) $\endgroup$
    – Mr.Wizard
    Jul 15, 2015 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$
    – user484
    Jan 27, 2017 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 and acknowledge that you have read and understand our privacy policy and code of conduct.

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