Faro mescola un array


31

Un shuffle Faro è una tecnica spesso usata dai maghi per "mescolare" un mazzo. Per eseguire un shuffle Faro, devi prima tagliare il mazzo in 2 metà uguali, quindi interfogli le due metà. Per esempio

[1 2 3 4 5 6 7 8]

Faro è mischiato

[1 5 2 6 3 7 4 8]

Questo può essere ripetuto un numero qualsiasi di volte. Abbastanza interessante, se lo ripeti abbastanza volte, tornerai sempre alla matrice originale. Per esempio:

[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]

Notare che 1 rimane in basso e 8 rimane in alto. Questo rende questo un riordino esterno . Questa è una distinzione importante.

La sfida

Dato un array di numeri interi A e un numero N , genera l'array dopo che N Faro si mescola. A può contenere elementi ripetuti o negativi, ma avrà sempre un numero pari di elementi. Si può presumere che l'array non sarà vuoto. Puoi anche supporre che N sarà un numero intero non negativo, sebbene possa essere 0. Puoi prendere questi input in qualsiasi modo ragionevole. Vince la risposta più breve in byte!

Test 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]

E, un enorme caso di test:

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]

Dovrebbe produrre:

[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]  

L'array può contenere zero elementi?
Leaky Nun,

@LeakyNun Diremo di no, non devi gestire zero elementi.
DJMcMayhem



1
Qualsiasi permutazione di un set finito, se ripetuta abbastanza volte, finirà nel punto in cui è iniziata; questo non è speciale per i shuffle di Faro.
Greg Martin,

Risposte:


10

05AB1E , 5 byte

Codice:

F2äø˜

Spiegazione, input: N, array:

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

Utilizza la codifica CP-1252 . Provalo online! .


1
Accidenti, ero troppo lento!
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. Questa è forse la cosa più hacker che ho scritto per PPCG, e questo sta dicendo qualcosa.

L'input viene preso come N sulla prima riga seguita dagli elementi dell'array, ciascuno sulla propria riga.

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!

In realtà ho probabilmente trovato diversi bug vim mentre scrivevo questa risposta:

  • la registrazione di macro non è possibile all'interno di altre macro (quando si imposta il loro testo manualmente, non con q) o all'interno di :*maps.

  • :let @a='<C-v><cr>'<cr>i<C-r>a genera due nuove linee, non una, per qualunque ragione arcana.

Potrei indagare su quelli più tardi.

Grazie a Dr Green Eggs e Ham DJ per 3 byte!


4
Questo è bello e terrificante. Probabilmente non ho abbastanza pazienza per farlo in vim. :PInoltre, puoi togliere 2 byte facendo "rckinvece di vgg"rc, e puoi toglierne altri 5 facendo dw@"i@r<esc>invece diAA@R<C-v><esc><esc>0D@"
toglierne

@DrGreenEggsandHamDJ Non riesco a farlo per primo perché afferra anche una nuova riga finale, ma quella seconda ottimizzazione funziona. Grazie!
Maniglia della porta

7

Python 2, 59 byte

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

Un approccio diverso, leggermente più lungo rispetto alle altre risposte di Python. Funziona solo con numeri pari positivi di elementi.

ad es. per 1, [1,2,3,4,5,6,7,8], prendere l'array e aggiungere len(L)/2-1copie di se stesso meno il primo elemento, ad es

[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]

Quindi prendi ogni len(L)/2elemento th.

[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]
 ^       ^       ^       ^       ^       ^       ^       ^

6

Python, 68 57 byte

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

Grazie a @ Sp3000 per giocare a golf con 11 byte!

Provalo su Ideone .


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]]

Sia s = 2 · t la dimensione dell'elenco. L' i -esimo elemento della nuova lista si ottiene prendendo l' inserisci qui la descrizione dell'immagineennesimo elemento della vecchia lista, zero-indexed, modulo s .

Prova: se i = 2 · k è pari, allora

                                         inserisci qui la descrizione dell'immagine

e se i = 2 · k + 1 è dispari, allora

                        inserisci qui la descrizione dell'immagine

Pertanto i valori utilizzati per l'indicizzazione sono 0, t , 1, t + 1, 2, t + 2, ...


5

J - 12 byte

Avverbio (!) Che prende il numero di riordini a sinistra e l'array che si mescola a destra.

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

Il parser J ha regole per scrivere avverbi taciti , ma hanno una precedenza molto bassa: se si desidera utilizzare un treno di verbi come argomento sinistro, è possibile omettere un insieme di parentesi altrimenti necessario. Quindi quanto sopra è in realtà l'abbreviazione di (/:#/:@$0,#)^:, che prende il numero di riordini a sinistra come un avverbio, e quindi diventa una funzione monadica che porta l'array a rimescolare a destra.

Detto questo, mescoliamo come segue. #è la lunghezza dell'array, quindi 0,#è un elenco di due elementi: 0 seguito da qualcosa di diverso da zero. Quindi lo #/:@$replica in un elenco fino a quando l'array di input e prende il suo vettore di ordinamento .

Il vettore di ordinamento di un elenco è l'informazione su come ordinare l'elenco: l'invdex (basato su 0) dell'elemento più piccolo, seguito dall'indice del successivo più piccolo, e così via. Ad esempio, il vettore di ordinamento di0 1 0 1 ... sarà così 0 2 4 ... 1 3 5 ....

Se J adesso ordinasse questo tipo di vettore, Faro lo mescolerebbe; ma sarebbe banale, dato che 0 1 2 3 ...torneremmo. Quindi usiamo dyadic/: per ordinare l'array di input come se fosse 0 2 4 ... 1 3 5 ... , il che Faro lo mescola.

Esempio di utilizzo di seguito. Provalo tu stesso su 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

5

Pyth - 8 7 byte

salvato 1 byte grazie a @issacg

usCc2GE

Provalo online qui .


2
Hmm ... ci deve essere qualcosa di sbagliato nella risposta di Jelly se Pyth batte Jelly.
Leaky Nun,

2
Scambia l'ordine di input e rimuovi il Qper salvare un byte. Ci deve essere qualcosa di sbagliato nella risposta di Pyth se Jelly batte Pyth. :)
isaacg,

@isaacg maledetto, avrei giurato di averlo provato prima. Perché funziona? non dovrebbe agganciarsi al valore predefinito per ucon Nessuno e fare un punto fisso?
Maltysen,

@Maltysen Hai ragione, penso che abbia funzionato solo sull'un caso di test che ho provato. Mi dispiace per quello.
Isaacg,

@LeakyNun Grazie a @Dennis e @issacg , Pyth e Jelly sono ora uguali (7 byte). ; D
Kevin Cruijssen,

3

Gelatina, 9 7 byte

2 byte grazie a Dennis!

œs2ZFð¡

Provalo online!

Spiegazione

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

Versione precedente a 9 byte:

œs2ZF
Ç⁴¡

Provalo online!


2

JavaScript (ES6), 61 51 byte

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

Modifica l'array di input in atto e restituisce una copia dell'array originale. Se ciò è inaccettabile, è &&apossibile aggiungere il suffisso per restituire l'array modificato. Funziona solo per piccoli valori di a ncausa dei limiti dell'aritmetica intera di JavaScript. 61 versione ricorsiva a 60 byte che funziona con dimensioni maggiori n, basata sulla formula di @ Lynn:

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

2

MATL , 11 byte

w:"tn2/e!1e

Grazie a @Dennis per una correzione

Provalo online!

Spiegazione

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)

Perché è wnecessario?
David,

@ David Questa era la correzione. Senza di essa, per N = 0 il loop non viene inserito e il secondo input non viene eseguito
Luis Mendo

Ah, questo è fastidioso!
David,

2

J, 22 19 17 byte

3 byte grazie a @Gareth .

2 byte grazie a @algorithmshark .

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

uso

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

Dov'è >>STDIN e<< è STDOUT.

Versione precedente a 22 byte:

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

uso

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

Dov'è >>STDIN ed<< è STDOUT.


A causa delle regole di analisi di J , puoi rilasciare le parentesi esterne per 2 caratteri.
algoritmo

Alternativa usando un indice trasposto {~2,@|:@i.@,-:@#^:per 18 byte .
miglia,

Un'altra alternativa che utilizza 17 byte anche[:,@|:]]\~_2%~#^:
miglia

@miles Credo che funzioni ,@|:@$~2,-:@#^:per 15 byte
Giona

1

Mathematica 44 byte

Con 4 byte salvati grazie a @miles.

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

Riffle @@ TakeDrop[#, Length@#/2] &~Nest~## &[list, nShuffles]divide l'elenco in due liste secondarie uguali e le mescola ( Riffles).


 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, 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 }


Usando TakeDroppossiamo trovare una soluzione usando 40 byte come Riffle@@TakeDrop[#,Length@#/2]&~Nest~##&prendendo anche la sequenza ##da analizzare come argomenti aggiuntivi Nest.
miglia

@miglia. Ottimo uso di TakeDrop. Ed è meglio usare ##per inserire la sequenza.
DavidC,

1

APL, 23 21 caratteri

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

Senza il presupposto (grazie a Dennis) e 1 carattere più corto:

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

Provalo online .


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;}

Spiegazione: Esiste un modello di come gli elementi si muovono quando vengono mescolati faro:

lascia che x sia l'indice originale

lascia che sia il nuovo indice

lascia che L sia la lunghezza dell'array

  • y è doppio x
  • se x è maggiore o uguale alla metà di L, allora incrementa y
  • mantieni y entro i limiti dell'array

o come codice: y=(2*x+x/(L/2))%L

Ciò presuppone che le indicazioni inizino da 0. Ecco il codice ulteriormente spiegato:

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;
}  

vedi ideone per i casi di test


So che è passato più di un anno, ma puoi giocare a golf in alcune parti: 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 - la tua risposta attuale è di 119 btw, non 109, quindi -12 byte). Poiché si modifica l'array di input, non è necessario restituirlo, quindi è possibile modificarlo in un vuoto per ridurre i byte. Oh, e se ti converti in un lambda Java 8 con il curry potresti renderlo ancora più breve: 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

Provalo online!

Come funziona

Definiamo (ri) l'operatore binario \per questa attività. Sia a un array e n un numero intero non negativo.

Se n è positivo, mescoliamo l'array. Ciò si ottiene rimodellandolo in una matrice di lunghezza (a) ÷ 2 file e due colonne. 'traspone la matrice risultante, creando due righe, quindi appiattendo il risultato con [:]. Dal momento che Julia memorizza le matrici in ordine di colonna maggiore, questo interlaccia le due righe.

Successivamente, chiamiamo \ricorsivamente con i riordini a e n - 1 ( ~-n) come argomenti, eseguendo quindi riordini aggiuntivi. Quando n raggiunge 0 , restituiamo il valore corrente di a .


0

Pyke, 7 byte

VDlec,s

Provalo qui!

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, [])

0

In realtà, 15 byte

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

Provalo online!

Spiegazione:

`;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

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).

uso

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


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;}

Provalo online .

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.