Faro mengocok array

31

Sebuah Faro mengocok adalah teknik yang sering digunakan oleh para penyihir untuk "shuffle" dek. Untuk melakukan Faro shuffle, pertama-tama Anda memotong dek menjadi 2 bagian yang sama maka Anda memotong bagian kedua. Sebagai contoh

[1 2 3 4 5 6 7 8]

Faro yang dikocok adalah

[1 5 2 6 3 7 4 8]

Ini dapat diulang beberapa kali. Cukup menarik, jika Anda mengulangi ini cukup banyak, Anda akan selalu berakhir kembali di array asli. Sebagai contoh:

[1 2 3 4 5 6 7 8]
[1 5 2 6 3 7 4 8]
[1 3 5 7 2 4 6 8]
[1 2 3 4 5 6 7 8]

Perhatikan bahwa 1 tetap di bawah dan 8 tetap di atas. Itu membuat ini menjadi shuffle luar . Ini adalah perbedaan penting.

Tantangan

Diberikan array bilangan bulat A , dan angka N , output array setelah N Faro mengocok. A mungkin mengandung elemen berulang atau negatif, tetapi akan selalu memiliki jumlah elemen genap. Anda dapat menganggap array tidak akan kosong. Anda juga dapat mengasumsikan bahwa N akan menjadi bilangan bulat non-negatif, meskipun mungkin 0. Anda dapat mengambil input ini dengan cara yang masuk akal. Jawaban terpendek dalam byte menang!

Tes IO:

#N, A,                                              Output
1,  [1, 2, 3, 4, 5, 6, 7, 8]                        [1, 5, 2, 6, 3, 7, 4, 8]
2,  [1, 2, 3, 4, 5, 6, 7, 8]                        [1, 3, 5, 7, 2, 4, 6, 8]
7,  [-23, -37, 52, 0, -6, -7, -8, 89]               [-23, -6, -37, -7, 52, -8, 0, 89]
0,  [4, 8, 15, 16, 23, 42]                          [4, 8, 15, 16, 23, 42]
11, [10, 11, 8, 15, 13, 13, 19, 3, 7, 3, 15, 19]    [10, 19, 11, 3, 8, 7, 15, 3, 13, 15, 13, 19]

Dan, ujian besar-besaran:

23, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100]

Haruskah output:

[1, 30, 59, 88, 18, 47, 76, 6, 35, 64, 93, 23, 52, 81, 11, 40, 69, 98, 28, 57, 86, 16, 45, 74, 4, 33, 62, 91, 21, 50, 79, 9, 38, 67, 96, 26, 55, 84, 14, 43, 72, 2, 31, 60, 89, 19, 48, 77, 7, 36, 65, 94, 24, 53, 82, 12, 41, 70, 99, 29, 58, 87, 17, 46, 75, 5, 34, 63, 92, 22, 51, 80, 10, 39, 68, 97, 27, 56, 85, 15, 44, 73, 3, 32, 61, 90, 20, 49, 78, 8, 37, 66, 95, 25, 54, 83, 13, 42, 71, 100]  
DJMcMayhem
sumber
Bisakah array mengandung elemen nol?
Leaky Nun
@ LeakyNun Kami akan mengatakan tidak, Anda tidak perlu menangani elemen nol.
DJMcMayhem
Terkait
Peter Taylor
1
Permutasi set terbatas, jika diulang cukup kali, akan berakhir di tempat dimulainya; ini tidak spesial untuk Faro shuffles.
Greg Martin

Jawaban:

10

05AB1E , 5 byte

Kode:

F2äø˜

Penjelasan, masukan: N, array:

F      # Do the following N times
 2ä    # Split the array into 2 pieces
   ø   # Zip
    ˜  # Deep flatten

Menggunakan pengkodean CP-1252 . Cobalah online! .

Adnan
sumber
1
Sial, aku terlalu lambat!
George Gibson
19

vim, 62 59 54

qrma50%mb:norm@q<cr>ggqOjdd'apjma'b@q<esc>0"qDJ<C-a>D@"i@r<esc>xxdd@"

Wow. Ini mungkin hal yang paling hacki yang saya tulis untuk PPCG, dan itu mengatakan sesuatu.

Input diambil sebagai N pada baris pertama diikuti oleh elemen-elemen array, masing-masing pada barisnya sendiri.

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!

Saya sebenarnya mungkin menemukan beberapa bug vim saat menulis jawaban ini:

  • merekam makro tidak dimungkinkan dalam makro lain (saat mengatur teks mereka secara manual, tidak dengan q ) atau di dalam :*maps.

  • :let @a='<C-v><cr>'<cr>i<C-r>a menghasilkan dua baris baru, bukan satu, untuk alasan misterius apa pun.

Saya mungkin akan menyelidiki lebih lanjut nanti.

Terima kasih kepada Dr Green Eggs dan Ham DJ selama 3 byte!

Gagang pintu
sumber
4
Ini indah dan mengerikan. Saya mungkin tidak memiliki cukup kesabaran untuk melakukan ini di vim. :PAnda juga dapat melepas 2 byte dengan melakukan "rckalih - alih vgg"rc, dan Anda dapat melepas 5 byte dengan melakukan alih - dw@"i@r<esc>alihAA@R<C-v><esc><esc>0D@"
DJMcMayhem
@DrGreenEggsandHamDJ Tidak dapat melakukan yang pertama karena itu mengambil baris baru juga, tetapi optimasi kedua itu berfungsi. Terima kasih!
Gagang pintu
7

Python 2, 59 byte

def f(n,L):exec"l=len(L)/2;L=(L+L[1:]*~-l)[::l];"*n;print L

Pendekatan yang berbeda, sedikit lebih panjang dari jawaban Python lainnya. Hanya berfungsi untuk sejumlah elemen positif.

misal untuk 1, [1,2,3,4,5,6,7,8], ambil array dan tambahkan len(L)/2-1salinannya sendiri dikurangi elemen pertama, mis

[1,2,3,4,5,6,7,8,2,3,4,5,6,7,8,2,3,4,5,6,7,8,2,3,4,5,6,7,8]

Kemudian ambil setiap len(L)/2elemen.

[1,2,3,4,5,6,7,8,2,3,4,5,6,7,8,2,3,4,5,6,7,8,2,3,4,5,6,7,8]
 ^       ^       ^       ^       ^       ^       ^       ^
Sp3000
sumber
6

Python, 68 57 byte

f=lambda n,x:n and f(n-1,sum(zip(x,x[len(x)/2:]),()))or x

Terima kasih kepada @ Sp3000 untuk bermain golf 11 byte!

Cobalah Ideone .

Dennis
sumber
6

Haskell, 62 byte

0!a=a
n!a|s<-length a=(n-1)![a!!mod(div(s*i+i)2)s|i<-[0..s-1]]

Biarkan s = 2 · t menjadi ukuran daftar. The i elemen -th dari daftar baru diperoleh dengan mengambil masukkan deskripsi gambar di siniunsur -th dari daftar lama, nol-diindeks, modulo s .

Bukti: jika i = 2 · k genap, maka

                                         masukkan deskripsi gambar di sini

dan jika i = 2 · k +1 adalah ganjil, maka

                        masukkan deskripsi gambar di sini

Dengan demikian nilai yang digunakan untuk pengindeksan adalah 0, t , 1, t + 1, 2, t + 2,…

Lynn
sumber
5

J - 12 byte

Adverb (!) Mengambil jumlah shuffles di sebelah kiri dan array untuk shuffle di sebelah kanan.

/:#/:@$0,#^:

J parser memiliki aturan untuk menulis adverbia diam-diam , tetapi mereka memiliki prioritas yang sangat rendah: jika Anda ingin menggunakan kereta kata kerja sebagai argumen kiri, Anda dapat menghilangkan satu set tanda kurung yang diperlukan. Jadi di atas sebenarnya adalah kependekan dari (/:#/:@$0,#)^:, yang mengambil jumlah shuffles di sebelah kiri sebagai kata keterangan, dan kemudian menjadi fungsi monadik mengambil array untuk mengocok di sebelah kanan.

Yang mengatakan, kami mengocok sebagai berikut. #adalah panjang array, begitu 0,#juga daftar dua elemen: 0 diikuti oleh sesuatu yang bukan nol. Kemudian #/:@$mereplikasi itu ke dalam daftar selama input array, dan mengambil vektor pengurutannya .

Vektor pengurutan daftar adalah informasi untuk cara mengurutkan daftar: invdex (berbasis-0) dari elemen terkecil, diikuti oleh indeks berikutnya-terkecil, dan seterusnya. Sebagai contoh, vektor semacam 0 1 0 1 ...akan demikian0 2 4 ... 1 3 5 ... .

Jika J sekarang menyortir vektor semacam ini, itu akan Faro-shuffle; tapi itu akan sepele, karena kita akan 0 1 2 3 ...kembali. Jadi kami menggunakan diad/: untuk mengurutkan array input seolah-olah itu 0 2 4 ... 1 3 5 ... , yang Faro-mengocoknya.

Contoh penggunaan di bawah ini. Coba sendiri di tryj.tk !

   1 (/:#/:@$0,#^:) 1 2 3 4 5 6 7 8
1 5 2 6 3 7 4 8

   f =: /:#/:@$0,#^:

   2  f  1 2 3 4 5 6 7 8
1 3 5 7 2 4 6 8

   7  f  _23 _37 52 0 _6 _7 _8 89   NB. "negative 1" is spelled _1
_23 _6 _37 _7 52 _8 0 89

   1  f  0 0 0 0 1 1 1              NB. odd-length lists
0 1 0 1 0 1 0
algoritme hiu
sumber
5

Pyth - 8 7 byte

disimpan 1 byte berkat @issacg

usCc2GE

Cobalah online di sini .

Maltysen
sumber
2
Hmm ... pasti ada yang salah dalam jawaban Jelly jika Pyth mengalahkan Jelly.
Leaky Nun
2
Tukar urutan input dan hapus Quntuk menyimpan byte. Pasti ada yang salah dengan jawaban Pyth jika Jelly mengalahkan Pyth. :)
isaacg
@isaacg sialan, bisa bersumpah aku sudah mencobanya sebelumnya. Mengapa itu berhasil? bukankah seharusnya itu menghubungkan ke default untuk udengan None dan melakukan fixed point?
Maltysen
@Maltysen Anda benar, saya pikir itu hanya bekerja pada satu test case yang saya coba. Maaf soal itu.
isaacg
@ LeakyNun Terima kasih kepada @Dennis dan @issacg , Pyth dan Jelly sekarang sama (7 byte). ; D
Kevin Cruijssen
3

Jelly, 9 7 byte

2 byte berkat Dennis!

œs2ZFð¡

Cobalah online!

Penjelasan

œs2ZFð¡  Main dyadic chain. Arguments: x,y
      ¡  Repeat the following y time:
œs2          Split into two.
   Z         Transpose.
    F        Flatten.

Versi 9 byte sebelumnya:

œs2ZF
Ç⁴¡

Cobalah online!

Biarawati Bocor
sumber
2

JavaScript (ES6), 61 51 byte

(n,a)=>[...a].map((e,i)=>a[(i<<n)%~-a.length||i]=e)

Mengubah array input pada tempatnya dan mengembalikan salinan array asli. Jika ini tidak &&adapat diterima, dapat diakhiri dengan mengembalikan array yang dimodifikasi. Hanya berfungsi untuk nilai kecil nkarena keterbatasan aritmatika integer JavaScript. 61 versi rekursif 60 byte yang bekerja dengan lebih besar n, berdasarkan rumus @ Lynn:

f=(n,a,l=a.length)=>n?f(n-1,a.map((_,i)=>a[(i*-~l>>1)%l])):a
Neil
sumber
2

MATL , 11 byte

w:"tn2/e!1e

Berkat @ Dennis untuk koreksi

Cobalah online!

Penjelasan

w         % Take the two inputs N and A. Swap them
:         % Generate [1 2 ... N]
"         % Repeat N times
  tn2/    %   Duplicate A. Number of elements divided by 2
  e       %   Reshape to that number of rows
  !       %   Transpose
  1e      %   Reshape to one row
          % End (implicit)
          % Display (implicit)
Luis Mendo
sumber
Mengapa itu wperlu?
David
@ David Itu koreksi. Tanpanya, untuk N = 0 loop tidak dimasukkan dan input kedua tidak diambil
Luis Mendo
Ahh itu menyebalkan!
David
2

J, 22 19 17 byte

3 byte terima kasih kepada @Gareth .

2 byte berkat @algorithmshark .

-:@#({.,@,.}.)]^:

Pemakaian

>> f =: -:@#({.,@,.}.)]^:
>> 2 f 1 2 3 4 5 6 7 8
<< 1 3 5 7 2 4 6 8

Dimana >> STDIN dan<<STDOUT.

Versi 22 byte sebelumnya:

({~[:,/@|:@i.2,-:@#)^:

Pemakaian

>> f =: ({~[:,/@|:@i.2,-:@#)^:
>> 2 f 1 2 3 4 5 6 7 8
<< 1 3 5 7 2 4 6 8

Di mana >>STDIN dan <<STDOUT.

Biarawati Bocor
sumber
Karena aturan parsing J , Anda dapat menjatuhkan parens luar selama 2 karakter.
algorithmshark
Alternatif menggunakan indeks transposisi {~2,@|:@i.@,-:@#^:untuk 18 byte .
miles
Alternatif lain yang menggunakan 17 byte juga[:,@|:]]\~_2%~#^:
mil
@milesI percaya ,@|:@$~2,-:@#^:bekerja selama 15 byte
Jonah
1

Mathematica 44 byte

Dengan 4 byte disimpan berkat @miles.

Riffle@@TakeDrop[#,Length@#/2]&~Nest~##&

Riffle @@ TakeDrop[#, Length@#/2] &~Nest~## &[list, nShuffles]membagi daftar menjadi dua sublists yang sama dan mengocoknya Riffle.


 Riffle @@ TakeDrop[#, Length@#/2] &~Nest~## &[Range@8, 1]

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


Riffle @@ TakeDrop[#, Length@#/2] &~Nest~## &[Range@100, 23]

{1, 30, 59, 88, 18, 47, 76, 6, 35, 64, 93, 23, 52, 81, 11, 40, 69, 98, 28, 57, 86, 16, 45, 74, 4 , 33, 62, 91, 21, 50, 79, 9, 38, 67, 96, 26, 55, 84, 14, 43, 72, 2, 31, 60, 89, 19, 48, 77, 7, 36 , 65, 94, 24, 53, 82, 12, 41, 70, 99, 29, 58, 87, 17, 46, 75, 5, 34, 63, 92, 22, 51, 80, 80, 10, 39, 68 , 97, 27, 56, 85, 15, 44, 73, 3, 32, 61, 90, 20, 49, 78, 8, 37, 66, 95, 25, 54, 83, 13, 42, 71, 100 }

DavidC
sumber
Menggunakan TakeDropkita dapat menemukan solusi menggunakan 40 byte sebagai Riffle@@TakeDrop[#,Length@#/2]&~Nest~##&sambil mengambil urutan ##untuk diuraikan sebagai argumen tambahan Nest.
mil
@miles. Penggunaan yang sangat bagus TakeDrop. Dan lebih baik digunakan ##untuk memasukkan urutan.
DavidC
1

APL, 23 21 karakter

({⊃,/⍵(↑,¨↓)⍨2÷⍨⍴⍵}⍣N)A

Tanpa asumsi (Terima kasih kepada Dennis) dan 1 char lebih pendek:

({{∊,⌿2(2÷⍨≢⍵)⍴⍵}⍣⎕)⎕

Cobalah secara online .

pengguna2070206
sumber
1

java, 109 byte

int[]f(int[]a,int n){for(int x,q=a.length,d[];0<n--;a=d){d=new int[q];for(x=0;x<q;x++)d[(2*x+2*x/q)%q]=a[x];}return a;}

Penjelasan: Ada pola bagaimana elemen bergerak ketika mereka dikocok secara jauh:

biarkan x menjadi indeks asli

biarkan y menjadi indeks baru

biarkan L menjadi panjang array

  • y adalah x ganda
  • jika x lebih besar dari atau sama dengan setengah dari L maka kenaikan y
  • simpan y dalam batas array

atau sebagai kode: y=(2*x+x/(L/2))%L

Ini mengasumsikan bahwa indeks mulai dari 0. Inilah kode yang dijelaskan lebih lanjut:

int[] faroShuffle( int[] array, int numberOfShuffles ) {
    //repeat the faro shuffle n times
    for( int index, length=array.length, destination[]; 0<numberOfShuffles--; array=destination ) {
        //new array to copy over the elements
        destination=new int[length];
        //copy the elements into the new array
        for( index=0; index<length; index++ )
            destination[(2*index+2*index/length)%length]=array[index];
        //at the end of each loop, copy the reference to the new array and use it going forward
    }
    return array;
}  

lihat ideone untuk test case

Jack Ammo
sumber
Saya tahu ini sudah lebih dari setahun, tetapi Anda dapat bermain golf beberapa bagian: void f(int[]a,int n){for(int x,q=a.length,d[];0<n--;a=d)for(d=new int[q],x=0;x<q;)d[(2*x+2*x/q)%q]=a[x++];}( 107 byte - jawaban Anda saat ini adalah 119 btw, bukan 109, jadi -12 byte). Karena Anda memodifikasi array input, Anda tidak perlu mengembalikannya, jadi Anda bisa mengubahnya menjadi void untuk mengurangi byte. Oh, dan jika Anda mengonversi ke lambda Java 8 dengan kari, Anda bisa membuatnya lebih pendek: a->n->{for(int x,q=a.length,d[];0<n--;a=d){d=new int[q];for(x=0;x<q;x++)d[(2*x+2*x/q)%q]=a[x];}}( 96 byte )
Kevin Cruijssen
1

Julia, 45 42 byte

a\n=n>0?reshape(a,endof(a)÷2,2)'[:]\~-n:a

Cobalah online!

Bagaimana itu bekerja

Kami (kembali) mendefinisikan operator biner \untuk tugas ini. Biarkan a menjadi array dan n bilangan bulat non-negatif.

Jika n positif, kami mengocok array. Ini dicapai dengan membentuk kembali menjadi matriks panjang (a) ÷ 2 baris dan dua kolom. 'mentransposasikan matriks yang dihasilkan, membuat dua baris, lalu meratakan hasilnya dengan [:]. Karena Julia menyimpan matriks dalam urutan kolom-utama, ini menyisipkan dua baris.

Setelah itu, kami memanggil \secara rekursif dengan mengocok a dan n - 1 ( ~-n) sebagai argumen, sehingga melakukan pengocokan tambahan. Setelah n mencapai 0 , kami mengembalikan nilai saat ini dari a .

Dennis
sumber
0

Pyke, 7 byte

VDlec,s

Coba di sini!

V       - Repeat N times:
 D      -  a,b = a (2nd arg first time round)
  le    -  b = len(b)//2
    c   -  a = chunk(a,b)
     ,  -  a = zip(*a)
      s -  a = sum(a, [])
Biru
sumber
0

Sebenarnya, 15 byte

`;l½≈@│t)HZ♂i`n

Cobalah online!

Penjelasan:

`;l½≈@│t)HZ♂i`n
`            `n  do the following n times:
 ;l½≈              push half the length of the array
     @             swap
      │            duplicate entire stack
       t)H         last L//2 elements, first L//2 elements
          Z♂i      zip, flatten each element
Mego
sumber
0

Prolog, 116 byte

a([],[[],[]]).
a([H,I|T],[[H|U],[I|V]]):-a(T,[U,V]).
f(X,0,X).
f(X,N,Y):-N>0,M is N-1,f(X,M,Z),a(Z,[A,B]),append(A,B,Y).

Pemakaian

?- f([1,2,3,4,5,6,7,8],2,X).
X = [1, 5, 2, 6, 3, 7, 4, 8] ;
false.
Biarawati Bocor
sumber
0

PHP, 98 byte

function($a,$n){while($n--)for($z=count($a)/2;$z;)array_splice($a,$z--,0,array_pop($a));return$a;}

Cobalah online .

Titus
sumber