Faro shuffle an array
vim, 62 59 54
qrma50%mb:norm@q<cr>ggqOjdd'apjma'b@q<esc>0"qDJ<C-a>D@"i@r<esc>xxdd@"
Wow. This is possibly the hackiest thing I've written for PPCG, and that's saying something.
Input is taken as N on the first line followed by the elements of the array, each on its own line.
qr first, we're going to record the contents of the @r macro. this is
the macro which does the faro-shuffle operation.
ma set the mark 'a at the beginning of the file
50% move to the 50% point of the file (i.e. halfway down)
mb set another mark here
:norm@q evaluate the recursive macro @q. we'll get to what that does later,
but the interesting part here is that it's :norm@q instead of @q.
this is because a recursive macro terminates at the end of the
file, which means when @q terminates, @r would also abort, which
would make calling it with a count impossible. running @q under
:norm prevents this.
gg move back to the top of the file for the next iteration
q end recording
O now we're inserting contents of the @q macro, the recursive part
we can't record it directly because it's destructive
j move to line directly below mark 'b (which was just set before @q)
dd delete this line and bring it...
'ap up after mark 'a (which starts on line 1, bringing the N/2th line
directly below line 1, aka line 2)
jma replace mark 'a one line below this so that the next time we call
'ap, the line from the second half is interleaved with the lines
from the first half
'b jump back to mark 'b (remember, 'b is the last line of the first
half of the file, originally reached via 50%)
@q call ourselves, causing the macro to run until hitting EOF
0"qD delete this into register "q
J delete the empty line that remains
<C-a> here's another interesting bit: we want to run @r N times. but 0@r
means "go to column 0, and then run @r once." so we have to
increment the input number...
D@" and then *that* many times...
i@r insert @r...
xx ... and finally, delete two characters, which is the extra @r from
the increment
dd delete the sequence of @rs into the "" register...
@" and run it!
I actually possibly found several vim bugs while writing this answer:
recording macros is not possible within other macros (when setting their text manually, not with
q
) or within:*map
s.:let @a='<C-v><cr>'<cr>i<C-r>a
outputs two newlines, not one, for whatever arcane reason.
I might investigate those further later.
Thanks to Dr Green Eggs and Ham DJ for 3 bytes!
05AB1E, 5 bytes
Code:
F2äø˜
Explanation, input: N
, array
:
F # Do the following N times
2ä # Split the array into 2 pieces
ø # Zip
˜ # Deep flatten
Uses the CP-1252 encoding. Try it online!.
Python, 68 57 bytes
f=lambda n,x:n and f(n-1,sum(zip(x,x[len(x)/2:]),()))or x
Thanks to @Sp3000 for golfing off 11 bytes!
Test it on Ideone.