5
$\begingroup$

Consider a list of even length, for example list={1,2,3,4,5,6,7,8}

what is the fastest way to accomplish both these operations ?

Operation 1: two by two element inversion, the output is:

{2,1,4,3,6,5,8,7}

A code that work is:

Flatten@(Reverse@Partition[list,2])

Operation 2: Two by two Reverse, the output is:

{7,8,5,6,3,4,1,2}

A code that work is:

Flatten@(Reverse@Partition[Reverse[list],2])

The real lists have length 16, no need for anything adapated to long lists

$\endgroup$
2
  • $\begingroup$ You want that to be done for many lists at once? $\endgroup$ Mar 18 '21 at 10:41
  • 1
    $\begingroup$ Not necessarily, but I could tweak my code to make it so, so yes why not ! $\endgroup$
    – yfs
    Mar 18 '21 at 10:44
8
$\begingroup$

We can achieve a speed up of approx. 2 by using Riffle:

list = {1, 2, 3, 4, 5, 6, 7, 8};

For the first problem:

Riffle[list[[2 ;; ;; 2]], list[[1 ;; ;; 2]]]

For the second problem:

Riffle[list[[-2 ;; 1 ;; -2]], list[[-1 ;; 2 ;; -2]]]
$\endgroup$
9
$\begingroup$
PermutationList[Cycles[Partition[list,2]]]
{2, 1, 4, 3, 6, 5, 8, 7}

Simply Reverse the output above to get your second list:

Reverse @ %
{7, 8, 5, 6, 3, 4, 1, 2}  

Alternatively, define a Cycles object that can used to Permute other lists:

cycles = Cycles[Partition[Range @ 8, 2]];

Permute[list, cycles]
{2, 1, 4, 3, 6, 5, 8, 7}  

or

 list[[PermutationList @ cycles]]
{2, 1, 4, 3, 6, 5, 8, 7}   

Reverse the input list and Permute:

Permute[Reverse @ list,cycles]
{7, 8, 5, 6, 3, 4, 1, 2}  
Permute[CharacterRange["A", "H"], cycles]
{"B", "A", "D", "C", "F", "E", "H", "G"}   
Permute[Reverse @ CharacterRange["A", "H"], cycles]
{"G", "H", "E", "F", "C", "D", "A", "B"} 
$\endgroup$
8
$\begingroup$

If you have the do that very often, store your lists in a packed matrix like a below (that's a good idea anyways!), use your current code to generate a permutation, and then use Part to apply the permutations on the columns of a

n = 16;
a = RandomInteger[{1, 100}, {1000000, n}];

p1 = Flatten@(Reverse@Partition[Range[n], 2]);
b1 = Map[Flatten@(Reverse@Partition[#, 2]) &, a]; // RepeatedTiming // First
c1 = a[[All, p1]]; // RepeatedTiming // First
b1 == c1

p2 = Flatten@(Reverse@Partition[Range[n, 1, -1], 2]);
b2 = Map[Flatten@(Reverse@Partition[Reverse[#], 2]) &, a]; // RepeatedTiming // First
c2 = a[[All, p2]]; // RepeatedTiming // First
b2 == c2

0.338

0.041

True

0.463

0.040

True

If you are still free to choose you data layout, then you may consider to store the lists in "structure of arrays" format (i.e., by using the transpose of a) in order to obtain a small percentage of extra performance:

aT = Transpose[a];
b1T = aT[[p1]]; // RepeatedTiming // First
b2T = aT[[p2]]; // RepeatedTiming // First

Transpose[b1] == b1T
Transpose[b2] == b2T

0.035

0.035

True

True

$\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.