Faro mélange un tableau

31

Un shuffle Faro est une technique fréquemment utilisée par les magiciens pour "shuffle" un deck. Pour effectuer un shuffle Faro, vous devez d'abord couper le jeu en 2 moitiés égales, puis vous entrelacer les deux moitiés. Par exemple

[1 2 3 4 5 6 7 8]

Faro est mélangé

[1 5 2 6 3 7 4 8]

Cela peut être répété autant de fois que nécessaire. Chose intéressante, si vous répétez cela suffisamment de fois, vous vous retrouverez toujours dans le tableau d'origine. Par exemple:

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

Notez que 1 reste en bas et 8 reste en haut. Cela en fait un mélange externe . Cette distinction est importante.

Le défi

Étant donné un tableau d'entiers A et un nombre N , sortez le tableau après N Faro mélange. Un peut contenir des éléments répétés ou négatifs, mais il aura toujours un nombre pair d'éléments. Vous pouvez supposer que le tableau ne sera pas vide. Vous pouvez également supposer que N sera un entier non négatif, bien qu'il puisse être 0. Vous pouvez prendre ces entrées de toute manière raisonnable. La réponse la plus courte en octets gagne!

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]

Et, un cas de test massif:

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]

Devrait produire:

[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
la source
Le tableau peut-il contenir zéro élément?
Leaky Nun
@LeakyNun Nous dirons non, vous n'avez pas à gérer zéro élément.
DJMcMayhem
En relation
Peter Taylor
1
Toute permutation d'un ensemble fini, si elle est répétée suffisamment de fois, se terminera là où elle a commencé; ce n'est pas spécial pour les mélanges de Faro.
Greg Martin

Réponses:

10

05AB1E , 5 octets

Code:

F2äø˜

Explication, entrée: N, array:

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

Utilise le codage CP-1252 . Essayez-le en ligne! .

Adnan
la source
1
Merde, j'étais trop lent!
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@"

Sensationnel. C'est probablement la chose la plus bizarre que j'ai écrite pour PPCG, et cela veut dire quelque chose.

L'entrée est considérée comme N sur la première ligne suivie par les éléments du tableau, chacun sur sa propre ligne.

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!

En fait, j'ai peut-être trouvé plusieurs bogues vim en écrivant cette réponse:

  • l'enregistrement de macros n'est pas possible dans d'autres macros (lors de la définition manuelle de leur texte, pas avec q) ou dans :*maps.

  • :let @a='<C-v><cr>'<cr>i<C-r>a génère deux nouvelles lignes, pas une, pour une raison quelconque.

Je pourrais approfondir ces questions plus tard.

Merci au Dr Green Eggs et Ham DJ pour 3 octets!

Poignée de porte
la source
4
C'est beau et horrible. Je n'ai probablement pas assez de patience pour le faire à Vim. :PEn outre, vous pouvez retirer 2 octets en faisant à la "rckplace de vgg"rc, et vous pouvez en retirer 5 autres en faisant à la dw@"i@r<esc>place deAA@R<C-v><esc><esc>0D@"
DJMcMayhem
@DrGreenEggsandHamDJ Ne peut pas faire cela en premier car cela récupère également une nouvelle ligne de fin, mais cette seconde optimisation fonctionne. Merci!
Poignée de porte
7

Python 2, 59 octets

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

Une approche différente, légèrement plus longue que les autres réponses Python. Fonctionne uniquement pour des nombres pairs positifs d'éléments.

par exemple pour 1, [1,2,3,4,5,6,7,8], prendre le tableau et ajouter des len(L)/2-1copies de lui-même moins le premier élément, par exemple

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

Prenez ensuite chaque len(L)/2e élément.

[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
la source
6

Python, 68 57 octets

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

Merci à @ Sp3000 pour avoir joué 11 octets!

Testez-le sur Ideone .

Dennis
la source
6

Haskell, 62 octets

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

Soit s = 2 · t la taille de la liste. Le i- ème élément de la nouvelle liste est obtenu en prenant le- entrez la description de l'image icième élément de l'ancienne liste, indexé zéro, modulo s .

Preuve: si i = 2 · k est pair, alors

                                         entrez la description de l'image ici

et si i = 2 · k + 1 est impair, alors

                        entrez la description de l'image ici

Ainsi les valeurs utilisées pour l'indexation sont 0, t , 1, t + 1, 2, t + 2,…

Lynn
la source
5

J - 12 octets

Adverbe (!) Prenant le nombre de shuffles à gauche et le tableau à shuffle à droite.

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

L'analyseur J a des règles pour écrire des adverbes tacites , mais leur priorité est très faible: si vous voulez utiliser un train de verbes comme argument de gauche, vous pouvez omettre un ensemble de parenthèses autrement nécessaire. Donc, ce qui précède est en fait l'abréviation de (/:#/:@$0,#)^:, qui prend le nombre de shuffles à gauche comme adverbe, puis devient une fonction monadique prenant le tableau à shuffle à droite.

Cela dit, nous mélangeons comme suit. #est la longueur du tableau, tout 0,#comme une liste de deux éléments: 0 suivi de quelque chose de différent de zéro. #/:@$Réplique ensuite cela dans une liste tant que le tableau d'entrée et prend son vecteur de tri .

Le vecteur de tri d'une liste est l'information sur la façon de trier la liste: l'invdex (basé sur 0) du plus petit élément, suivi de l'index du plus petit suivant, et ainsi de suite. Par exemple, le vecteur de tri de 0 1 0 1 ...sera donc 0 2 4 ... 1 3 5 ....

Si J devait maintenant trier ce vecteur de tri, il le mélangerait avec Faro; mais ce serait trivial, puisque nous 0 1 2 3 ...reviendrions. Nous utilisons donc dyadique/: pour trier le tableau d'entrée comme s'il l'était 0 2 4 ... 1 3 5 ... , ce qui le mélange de façon Faro.

Exemple d'utilisation ci-dessous. Essayez-le vous-même sur 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
algorithmeshark
la source
5

Pyth - 8 7 octets

sauvé 1 octet grâce à @issacg

usCc2GE

Essayez-le en ligne ici .

Maltysen
la source
2
Hmm ... il doit y avoir quelque chose de mal dans la réponse Jelly si Pyth bat Jelly.
Leaky Nun
2
Échangez l'ordre d'entrée et supprimez le Qpour enregistrer un octet. Il doit y avoir quelque chose de mal avec la réponse Pyth si Jelly bat Pyth. :)
isaacg
@isaacg sacrément, j'aurais juré avoir déjà essayé ça. Pourquoi ça marche? cela ne devrait-il pas s'accrocher à la valeur par défaut uavec None et faire un point fixe?
Maltysen
@Maltysen Vous avez raison, je pense que cela n'a fonctionné que sur le seul cas de test que j'ai essayé. Désolé pour ça.
isaacg
@LeakyNun Grâce à @Dennis et @issacg , Pyth et Jelly sont désormais égaux (7 octets). ; D
Kevin Cruijssen
3

Gelée, 9 7 octets

2 octets grâce à Dennis!

œs2ZFð¡

Essayez-le en ligne!

Explication

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

Version précédente de 9 octets:

œs2ZF
Ç⁴¡

Essayez-le en ligne!

Fuite, nonne
la source
2

JavaScript (ES6), 61 51 octets

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

Modifie le tableau d'entrée en place et renvoie une copie du tableau d'origine. Si cela est inacceptable, &&apeut être suffixé pour renvoyer le tableau modifié. Fonctionne uniquement pour les petites valeurs en nraison des limitations de l'arithmétique des entiers JavaScript. 61 Version récursive de 60 octets qui fonctionne avec une plus grande n, basée sur la formule de @ Lynn:

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

MATL , 11 octets

w:"tn2/e!1e

Merci à @Dennis pour une correction

Essayez-le en ligne!

Explication

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
la source
Pourquoi est-ce wnécessaire?
David
@David C'était la correction. Sans cela, pour N = 0, la boucle n'est pas entrée et la deuxième entrée n'est pas prise
Luis Mendo
Ahh c'est ennuyeux!
David
2

J, 22 19 17 octets

3 octets grâce à @Gareth .

2 octets grâce à @algorithmshark .

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

Usage

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

>>est STDIN et <<STDOUT.

Version précédente de 22 octets:

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

Usage

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

>>est STDIN et <<STDOUT.

Fuite, nonne
la source
En raison des règles d'analyse de J , vous pouvez supprimer les parens externes pour 2 caractères.
algorithmshark
Alternative utilisant un index transposé {~2,@|:@i.@,-:@#^:pour 18 octets .
miles
Une autre alternative qui utilise 17 octets également[:,@|:]]\~_2%~#^:
miles
@milesJe crois que ça ,@|:@$~2,-:@#^:marche pour 15 octets
Jonah
1

Mathematica 44 octets

Avec 4 octets enregistrés grâce à @miles.

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

Riffle @@ TakeDrop[#, Length@#/2] &~Nest~## &[list, nShuffles]divise la liste en deux sous-listes égales et les mélange 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, 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
la source
En utilisant, TakeDropnous pouvons trouver une solution en utilisant 40 octets comme Riffle@@TakeDrop[#,Length@#/2]&~Nest~##&tout en prenant la séquence ##à analyser comme arguments supplémentaires Nest.
miles
@miles. Très belle utilisation de TakeDrop. Et il vaut mieux utiliser ##pour insérer la séquence.
DavidC
1

APL, 23 21 caractères

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

Sans l'hypothèse (Merci à Dennis) et 1 caractère plus court:

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

Essayez-le en ligne .

user2070206
la source
1

java, 109 octets

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

Explication: Il existe un modèle de déplacement des éléments lorsqu'ils sont mélangés de loin:

soit x l'index d'origine

que y soit le nouvel indice

soit L la longueur du tableau

  • y est double x
  • si x est supérieur ou égal à la moitié de L alors incrémenter y
  • garder y dans les limites du tableau

ou comme code: y=(2*x+x/(L/2))%L

Cela suppose que les indices commencent à 0. Voici le code expliqué plus en détail:

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

voir ideone pour les cas de test

Jack Ammo
la source
Je sais que cela fait plus d'un an, mais vous pouvez jouer au golf en quelques parties: 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 octets - votre réponse actuelle est 119 btw, pas 109, donc -12 octets). Puisque vous modifiez le tableau d'entrée, il n'est pas nécessaire de le renvoyer, vous pouvez donc le changer en vide pour réduire les octets. Oh, et si vous vous convertissez en lambda Java 8 avec curry, vous pourriez le rendre encore plus court: 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 octets )
Kevin Cruijssen
1

Julia, 45 42 octets

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

Essayez-le en ligne!

Comment ça marche

Nous (re) définissons l'opérateur binaire \pour cette tâche. Soit a un tableau et n un entier non négatif.

Si n est positif, on mélange le tableau. Ceci est réalisé en le remodelant en une matrice de longueur (a) ÷ 2 lignes et deux colonnes. 'transpose la matrice résultante, créant deux lignes, puis aplatissant le résultat avec [:]. Étant donné que Julia stocke les matrices dans l'ordre des colonnes principales, cela entrelace les deux lignes.

Ensuite, nous appelons \récursivement avec le shuffled a et n - 1 ( ~-n) comme arguments, réalisant ainsi les remaniements supplémentaires. Une fois que n atteint 0 , nous retournons la valeur actuelle de a .

Dennis
la source
0

Pyke, 7 octets

VDlec,s

Essayez-le ici!

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, [])
Bleu
la source
0

En fait, 15 octets

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

Essayez-le en ligne!

Explication:

`;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
la source
0

Prolog, 116 octets

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

Usage

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

PHP, 98 octets

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

Essayez-le en ligne .

Titus
la source