Mélangez un jeu sans variables locales [fermé]


14

Le but de ce puzzle est de prendre un jeu de 52 cartes et de le mélanger pour que chaque carte soit dans une position aléatoire.

Donné:

  • Un tableau, deckde 52 entiers distincts représentant les cartes. Lorsque vous commencez, deckcontient exactement une de chaque carte dans un ordre inconnu.
  • Une fonction int rand(min, max),, qui renvoie un entier aléatoire entre les entiers minet max, inclus. Vous pouvez supposer que cette fonction est vraiment aléatoire.
  • Une fonction, void swap(x, y)qui échange deux cartes dans le jeu. Si vous appelez swap(x, y), les cartes aux positions xet ychangeront de place.

Quand:

  • Le programme appelle shuffle()(ou shuffle(deck)ou deck.shuffle()ou comme votre implémentation aime s'exécuter),

Alors:

  • deck doit contenir exactement une de chaque carte dans un ordre parfaitement aléatoire.

The Catch:

Vous ne pouvez déclarer aucune variable. Appelez swapet randautant que vous le souhaitez, mais vous ne pouvez pas déclarer vos propres variables. Cela inclut les forcompteurs de boucles - même ceux implicites comme dans a foreach.

Clarifications:

  • Vous pouvez modifier des détails mineurs en fonction de la langue choisie. Par exemple, vous pouvez écrire swappour commuter deux entiers par référence. Les changements devraient être de faire fonctionner cela avec votre langue, et non de rendre le puzzle plus facile.
  • deck peut être une variable globale, ou vous pouvez l'intégrer comme paramètre.
  • Vous pouvez faire tout ce que vous voulez sur le contenu deck, mais vous ne pouvez pas changer sa longueur.
  • Vos cartes peuvent être numérotées 0-51, 1-52 ou tout ce que vous voulez.
  • Vous pouvez écrire ceci dans n'importe quelle langue, mais sans tricher avec la fonction intégrée de votre langue shuffle.
  • Oui, vous pouvez écrire la même ligne 52 fois. Personne ne sera impressionné.
  • Le temps d'exécution n'a pas d'importance, mais le vrai hasard le fait.
  • Ce n'est pas vraiment du golf de code, mais n'hésitez pas à minimiser / obscurcir votre code.

Edit: code de chaudière et visualiseur

Si vous avez utilisé .NET ou JavaScript, voici un code de test qui peut vous être utile:

JavaScript:

C #:

Ce code trie et mélange le paquet plusieurs milliers de fois et effectue des tests d'intégrité de base: pour chaque mélange, il vérifie qu'il y a exactement 52 cartes dans le paquet sans répétition. Ensuite, le visualiseur trace la fréquence de chaque carte se terminant à chaque endroit du jeu, affichant une carte de chaleur en niveaux de gris.

La sortie du visualiseur doit ressembler à de la neige sans motif apparent. Évidemment, cela ne peut pas prouver le vrai hasard, mais c'est un moyen rapide et facile de vérifier par sondage. Je recommande de l'utiliser ou quelque chose comme ça, car certaines erreurs dans l'algorithme de brassage conduisent à des modèles très reconnaissables dans la sortie. Voici un exemple de la sortie de deux implémentations, l'une avec une faille commune:

Sortie du visualiseur

La version défectueuse mélange partiellement le jeu, donc pourrait bien paraître si vous avez examiné le tableau à la main. Le visualiseur permet de remarquer plus facilement un motif.


De nombreux langages modélisent les tableaux comme étant effectivement infinis, permettant ainsi à $ deck [52] et suivants d'être utilisés à la place des variables locales. Cela devrait peut-être aussi être interdit.
Timwi

2
Les fonctions sont-elles considérées comme variables? les paramètres de fonction sont-ils considérés comme des variables?
zzzzBov

1
@zzzzBov - Ce que j'avais en tête, c'est que les paramètres de fonction seraient considérés comme des variables, mais je n'ai pas précisé cela avant la réponse de @ mellamokb. Je sais que cela peut être fait sans aucun paramètre autre que decklui-même.
Justin Morgan

1
@eBusiness - C'est un problème avec moi, pas la question elle-même. Et je votais parce que le répondeur a trouvé une faille.
Justin Morgan

1
@user unknown - Je pense que je comprends. La réponse est essentiellement que vous pouvez assumer la mise en œuvre de swapvotre choix, tant qu'elle remplit son objectif de base. Une partie de ma raison de faire swapun don était pour que les gens puissent le traiter comme de la «magie» et se concentrer sur le problème principal sans avoir à se soucier qu'il fonctionne dans la langue de son choix. Vous pouvez le faire ou écrire le vôtre swap, c'est à vous de décider.
Justin Morgan

Réponses:


9

Javascript

Je crois que c'est la forme de solution envisagée, j'utilise la carte en position 0 pour suivre les progrès, en mélangeant uniquement les cartes qui ont déjà été utilisées comme compteur, cela atteint la norme 52! permutations avec une distribution égale parfaite. La procédure est compliquée par l'échange XOR qui ne permet pas qu'un élément soit échangé par lui-même.

Edit: J'ai intégré un tri qui trie chaque élément en place juste avant son utilisation, permettant ainsi à cela de fonctionner avec un tableau non trié. J'ai également abandonné les appels récursifs en faveur d'une boucle while.

deck=[]
for(a=0;a<52;a++){
    deck[a]=a
}
function swap(a,b){
    deck[a]=deck[b]^deck[a]
    deck[b]=deck[b]^deck[a]
    deck[a]=deck[b]^deck[a]
}
function rand(a,b){
    return Math.floor(Math.random()*(1+b-a))+a
}
function shuffle(){
    while(deck[0]!=0){ //Sort 0 into element 0
        swap(0,deck[0])
    }
    while(deck[0]<51){ //Run 51 times
        while(deck[deck[0]+1]!=deck[0]+1){ //Sort element deck[0]+1 into position deck[0]+1
            swap(deck[deck[0]+1],deck[0]+1)
        }
        swap(0,deck[0]+1) //Swap element deck[0]+1 into position 0, thus increasing the value of deck[0] by 1
        if(rand(0,deck[0]-1)){ //Swap the element at position deck[0] to a random position in the range 1 to deck[0]
            swap(deck[0],rand(1,deck[0]-1))
        }
    }
    if(rand(0,51)){ //Swap the element at position 0 to a random position
        swap(0,rand(1,51))
    }
}
for(c=0;c<100;c++){
    shuffle()
    document.write(deck+"<br>")
}

C'est exactement ce que j'avais en tête. Dès que je testerai cela, je voterai et j'accepterai probablement.
Justin Morgan

Semble bien fonctionner, même si, à y regarder de plus près, ce n'est pas exactement la même chose que la mienne. Accepté, et je posterai bientôt ma propre réponse.
Justin Morgan

Ceci est également connu sous le nom d'algorithme de lecture aléatoire de Knuth ( en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle ).
Bob

14

Haskell

Voici une implémentation sans point. Aucune variable, paramètre formel ou récursivité explicite. J'ai beaucoup utilisé la fonction de refactorisation de lambdabot@pl ("inutile").

import Data.List
import Control.Applicative
import Control.Monad
import System.Random

shuffle :: [a] -> IO [a]
shuffle = liftM2 (<$>) ((fst .) . foldl' (uncurry ((. flip splitAt) . (.) .
          (`ap` snd) . (. fst) . flip flip tail . (ap .) . flip flip head .
          ((.) .) . (. (++)) . flip . (((.) . (,)) .) . flip (:))) . (,) [])
          (sequence . map (randomRIO . (,) 0 . subtract 1) . reverse .
          enumFromTo 1 . length)

main = print =<< shuffle [1..52]

Voici ma procédure de test pour m'assurer que les nombres ont été uniformément distribués:

main = print . foldl' (zipWith (+)) (replicate 52 0)
       =<< replicateM 1000 (shuffle [1..52])

Voici l'algorithme d'origine:

shuffle :: [a] -> IO [a]
shuffle xs = shuffleWith xs <$>
             sequence [randomRIO (0, i - 1) | i <- reverse [1..length xs]]

shuffleWith :: [a] -> [Int] -> [a]
shuffleWith xs ns = fst $ foldl' f ([], xs) ns where
    f (a,b) n = (x:a, xs++ys) where
        (xs, x:ys) = splitAt n b

+1 pour Haskell. Maintenant, je dois apprendre Haskell pour pouvoir lire ceci. : P
Justin Morgan

Comment est enregistrée la progression?
aaaaaaaaaaaa

8
Je doute que quiconque, sauf les programmeurs Haskell, dira que leur code est inutile et en sera fier.
aaaaaaaaaaaa

4
Ceci ((.) .) . (. (++))et ceci (((.) . (,)) .)sont mes préférés. Wow lambdabot. Juste wow.
Dan Burton

2
@eBusiness "point free" n'est pas du tout la même chose que "inutile".
fredoverflow

6

J

Ignorer ce deck est une variable, il y a une évidence ...

52 ? 52

Bien sûr, si vous voulez vraiment une fonction, il y a celle-ci, qui fonctionnera même si vous oubliez de supprimer les jokers (ou essayez de mélanger autre chose que des cartes).

{~ (# ? #)

Pour que...

shuffle =: {~ (# ? #)
deck =: i. 52
shuffle deck

Ceci est probablement en dehors de l'intention de la question, qui serait d'implémenter vous-même le shuff de rand ( ?). Je pourrais le faire plus tard quand je ne suis pas censé travailler.

Explication

Explication de 52 ? 52:

  • x ? y est x éléments uniques aléatoires de y.

L'explication {~ (# ? #)est plus difficile à cause des fourches et des crochets . Fondamentalement, c'est la même chose queshuffle =: 3 : '((# y) ? (# y)) { y' , qui a un argument implicite ( y).

  • # y donne la longueur de y
  • Cela donne 52? 52 comme précédemment, qui est une permutation aléatoire de 0..51
  • x { y est l'élément de y dans l'index x, ou (dans ce cas) les éléments dans les index de x.
  • Cela vous permet de mélanger tout ce qui est passé, pas seulement les entiers.

Voir J Vocabulaire pour plus de détails sur les opérateurs, bien que la syntaxe et la sémantique soient assez délicates à cause de la programmation de rang et tacite.


+1: Je travaille sur le code-golf quand je suis censé travailler .. lol Je le suis aussi: P
mellamokb

1
Pouvez-vous expliquer ce que cela fait pour les personnes ayant une déficience intellectuelle? Je l'ai récemment entendu décrit comme une explosion dans une usine d'émoticônes ( codegolf.stackexchange.com/questions/1294/anagram-code-golf/… ), ce qui sonne à peu près juste.
Justin Morgan

@Justin: Explication ajoutée.
Jesse Millikan

Cela fonctionne également dans APL. La syntaxe est la même, donc je ne prendrai pas la peine d'ajouter une nouvelle réponse ( {52?⍵}est une fonction anonyme qui prend 52 éléments aléatoires de son argument, qui serait ici une liste de 52 entiers)
Arc676

4

Python

import random
def rand(x, y):
 return random.randrange(x, y+1)

def swap(deck, x, y):
 deck[x] ^= deck[y]
 deck[y] ^= deck[x]
 deck[x] ^= deck[y]

def shuffle(deck):
 if len(deck)>1:
  deck[1:]=shuffle(deck[1:])
  if rand(0,len(deck)-1)>0:swap(deck, 0, rand(1, len(deck)-1))
 return deck

print shuffle(range(52))

Qu'est-ce que cela [1:]signifie? Est-ce que cela revient sur un sous-tableau de deck?
Justin Morgan

Oui, [1:] signifie le sous-tableau de l'index 1 à la fin du tableau. Il réorganise donc récursivement tout sauf le premier élément, l'affecte (le copie) au même endroit dans le tableau d'origine, puis place de manière aléatoire le premier élément quelque part.
Keith Randall

Très intelligent. Je pense que c'est l'une des plus belles solutions ici, et il utilise correctement l'algorithme Fisher-Yates. +1. Cela a été une belle façon pour moi de voir la beauté des langues que je ne connais pas.
Justin Morgan

2
Vous pouvez aimer l' a, b = b, aastuce.
Ray

3

Utilisation de la représentation factorielle

Dans la représentation factorielle d'une permutation, un élément i prend des valeurs de 0 à Ni. Donc, une permutation aléatoire est juste rand(0,i)pour chaque Ni.

En J:

? |.>:i.52
2 39 20 26 ... 2 0 1 0 0 0

? xest rand(0,x-1)et |.>:i.52est52 51 ... 1

Ensuite, si ala valeur du ième factoradic, nous faisons l'échange: swap(deck[i], deck[i+a]). La liste des paires à échanger est:

(,. i.52) ,. (,. ((?|.>:i.52)+i.52))
0 33
1 20
2  3
...
49 50
50 50
51 51

L'échange que nous utiliserons fonctionne comme ceci:

deck
24 51 14 18 ...
deck =: 0 1 swap deck
51 24 14 18 ...

Ce n'est pas vraiment "par référence" mais il n'y a pas de fonctions réelles dans J.

Nous utiliserons la longueur du deck ( #deck) pour éviter d'utiliser une constante.

Programme complet en J:

deck =: 52 ? 52                           NB. Initial random deck
swap =: 4 : 'deck =: (x { y) (|.x) } y'   NB. Given swap "function"
f =: 3 : 0                                NB. function that calls the swap for a pair
({.y) swap deck
}.y
)
f^:(#deck) (,.,.[:,.]+[:?[:|.>:) i.#deck

3

C #

Voici ma propre réponse basée sur l'algorithme de Fisher-Yates . Devrait vous donner un mélange parfait si votre générateur de nombres aléatoires est assez bon.

Version anglaise:

  1. Échangez à plusieurs reprises la carte à deck[0]avec celle à deck[v], où vest la valeur nominale de la carte à deck[0]. Répétez jusqu'à ce que v == 0. Cela triera partiellement le jeu, mais cela n'a pas d'importance. Vous savez maintenant que la carte 0 est à l'avant du paquet, ce qui signifie que vous pouvez voler cet espace dans le tableau et l'utiliser comme compteur de boucles. C'est la clé "triche" pour le problème des variables locales.
  2. À partir de la position 1 (la deuxième carte du jeu), échangez la carte à iavec celle à rand(i, 51). Notez que vous avez besoin rand(i, 51), pas rand(1, 51) . Cela ne garantit pas que chaque carte est randomisée.
  3. Remettez deck[0]à 0. Maintenant, le paquet entier est mélangé à l'exception de la première carte, alors échangez deck[0]avec deck[rand(0, 51)]et vous avez terminé.

Version C #:

public static void shuffle(int[] deck)
{
    while (deck[0] > 0)
        swap(ref deck[0], ref deck[deck[0]]);

    for (deck[0] = 1; deck[0] < 52; deck[0]++)
        swap(ref deck[deck[0]], ref deck[rand(deck[0], 51)]);

    deck[0] = 0;
    swap(ref deck[0], ref deck[rand(0, 51)]);
}

Version Javascript:

while (deck[0] > 0)
    swap(0, deck[0]);

for (deck[0] = 1; deck[0] < 52; deck[0]++)
    swap(deck[0], rand(deck[0], 52));

deck[0] = 0;
swap(0, rand(0, 52));

... où swap(a, b)échange deck[a]avec deck[b].


2

Ruby, une ligne

Est-ce considéré comme de la triche? Cela devrait être aussi aléatoire que possible.

deck=(0..51).to_a # fill the deck
deck[0..51] = (0..51).map{deck.delete_at(rand deck.length)}

(La randméthode de Ruby ne prend qu'un seul argument, puis génère un nombre n tel que 0 <= nombre <argument.)

De plus - similaire à la solution Perl de sogart, mais pour autant que je sache, elle ne souffre pas du problème:

deck = deck.sort_by{rand}

Sort_by de Ruby est différent de sort - il génère d'abord la liste de valeurs pour trier le tableau, puis seulement le trie par eux. C'est plus rapide quand il est coûteux de trouver la propriété par laquelle nous sommes triés, un peu plus lent dans tous les autres cas. Il est également utile dans le golf de code: P


Je n'appellerais pas cela de la tricherie, en soi, mais deck[0..51]contourne quelque peu la règle "pas de variables" en utilisant une fonctionnalité du langage. C'est juste, je pense juste qu'il perd une partie du défi. :) Je ne connais pas Ruby; pouvez-vous expliquer la (0..51).map{deck.delete_at(rand deck.length)}partie? Est-ce que cela supprime les cartes deck?
Justin Morgan

@JustinMorgan oui, 52 fois il supprime une carte aléatoire decket l'ajoute à la liste interne des résultats qui maps'accumule. Puis, quand il ne reste plus rien dans deckle maprésultat, il est copié deck. Fondamentalement, il y a un temporaire, mais c'est une fonctionnalité de langage plutôt qu'une variable explicite :)
hobbs

deck.sort_by!{rand}est plus court.
Eric Duminil

1

Javascript

REMARQUE: cette solution n'est techniquement pas correcte car elle utilise un deuxième paramètre i, dans l'appel à shuffle, qui compte comme une variable externe.

function shuffle(deck, i) {
    if (i <= 0)
        return;
    else {
        swap(deck[rand(0,i-1)], deck[i-1]);
        shuffle(deck, i - 1);
    }
}

Appeler avec shuffle(deck,52)

Un exemple de travail complet (a dû être swaplégèrement modifié car il n'y a pas de référence par passage des entiers en JavaScript):

function rand(min, max) { return Math.floor(Math.random()*(max-min+1)+min); }
function swap(deck, i, j) {
    var t=deck[i];
    deck[i] = deck[j];
    deck[j] = t;
}

function shuffle(deck, i) {
    if (i <= 0)
        return;
    else {
        swap(deck, rand(0,i-1), i-1);
        shuffle(deck, i - 1);
    }
}

// create deck
var deck=[];
for(i=0;i<52;i++)deck[i]=i;
document.writeln(deck);
shuffle(deck,52);
document.writeln(deck);

Bien joué. Ce que j'avais en tête était de considérer les paramètres de shufflecomme variables, mais je ne l'ai pas spécifié ainsi +1. Belle utilisation de la récursivité aussi.
Justin Morgan

-1, ne génère pas toutes les permutations, c'est évident parce que l'élément 51 n'occupera jamais sa place d'origine, et parce que vous n'appelez que suffisamment de rand pour générer 51! permutations sur les 52 possibles!
aaaaaaaaaaaa

2
@eBusiness: Dans la spécification d'origine, le jeu est commandé arbitrairement, pas nécessairement dans l'ordre 1-52. Je l'ai utilisé parce que c'était le plus simple.
mellamokb

1
@eBusiness: J'ai modifié pour permettre la possibilité de laisser l'élément au même endroit, en utilisant à la deck[rand(0,i-1)]place de deck[rand(0,i-2)]. Échangez également jusqu'à i=0au lieu de vous arrêter à i=1. Est ce que ça aide?
mellamokb

Oui, cela devrait le faire, sauf que vous cassez maintenant la spécification de swap XOR.
aaaaaaaaaaaa

1

C ++

#include <cstdlib>
#include <ctime>
#include <iostream>

int deck[52];

void swap(int a, int b) {
    deck[a] ^= deck[b];
    deck[b] ^= deck[a];
    deck[a] ^= deck[b];
}

int r(int a, int b) {
    return a + (rand() % (b - a + 1));
}

void s(int *deck) {
    swap(1, r(2, 51));
    deck[0] *= 100;

    for(deck[0] += 2; (deck[0] % 100) < 51; deck[0]++) {
        swap(deck[0] % 100,
          r(0, 1) ? r(1, (deck[0] % 100) - 1) : r((deck[0] % 100) + 1, 51));
    }
    swap(51, r(1, 50)); 

    deck[0] = (deck[0] - 51) / 100;
    swap(r(1, 51), 0);
}

int main(int a, char** c)
{
    srand(time(0));

    for (int i = 0; i < 52; i++)
        deck[i] = i;

    s(deck);
    s(deck);

    for (int i = 0; i < 52; i++)
        std::cout << deck[i] << " ";
}

Évite d'échanger des éléments avec eux-mêmes, donc doit appeler deux fois pour être aléatoire.


swap(deck[rand(1, 51)], (deck[0] - 51) / 100);Comment swapsaurez où mettre la deuxième valeur? Vous manquez également un ).
Justin Morgan

Oups, merci. J'ai commencé à déplacer cette partie lors d'une révision et j'ai dû me distraire avant de la terminer: P
Matthew Read

Downvote n'était pas de moi, BTW. Je testerai quand je pourrai.
Justin Morgan

D'ACCORD. J'ai facilité le test en fournissant un programme complet.
Matthew Read

1
Très intelligent. Ma propre solution a été utilisée deck[0], mais pas comme vous l'avez fait.
Justin Morgan

1

shuffle(int[] d){
    while(d.length){
        if([rand(0,d.length-1)!=0)swap(d[0],d[rand(1,d.length-1)]);
        d=d[1..$];
    }
}

1

Une autre solution Perl, qui produit en fait une sortie uniformément distribuée:

sub shuffle_integers {
    map int, sort {$a-int $a <=> $b-int $b} map $_+rand, @_;
}

say join " ", shuffle_integers 1 .. 52;

Cette solution utilise Perl rand, qui renvoie un nombre aléatoire x dans la plage 0 ≤ x <1. Elle ajoute un tel nombre aléatoire à chaque entier dans l'entrée, trie les nombres en fonction de leurs parties fractionnaires, et finalement supprime à nouveau ces parties fractionnaires .

(Je crois que l'utilisation des variables spéciales $_, $aet $bs'inscrit dans l'esprit du défi, car ce sont la façon dont perl transmet l'entrée à mapet sort, et elles ne sont pas utilisées à d'autres fins dans le code. En tout cas, je crois ils sont en fait les homonymes des valeurs d'entrée, pas de copies indépendantes Ce n'est pas en fait un remaniement en place, bien que,. à la fois mapet de sortcréer des copies de l'entrée sur la pile).


1

Java

Je suis surpris que personne n'ait déclaré l'évidence: (je suppose que le swap (x, x) ne fait rien.

    static void shuffle(){
        swap(1,rand(0,1));
        swap(2,rand(0,2));
        swap(3,rand(0,3));
        swap(4,rand(0,4));
        swap(5,rand(0,5));
        swap(6,rand(0,6));
        swap(7,rand(0,7));
        swap(8,rand(0,8));
        swap(9,rand(0,9));
        swap(10,rand(0,10));
        swap(11,rand(0,11));
        swap(12,rand(0,12));
        swap(13,rand(0,13));
        swap(14,rand(0,14));
        swap(15,rand(0,15));
        swap(16,rand(0,16));
        swap(17,rand(0,17));
        swap(18,rand(0,18));
        swap(19,rand(0,19));
        swap(20,rand(0,20));
        swap(21,rand(0,21));
        swap(22,rand(0,22));
        swap(23,rand(0,23));
        swap(24,rand(0,24));
        swap(25,rand(0,25));
        swap(26,rand(0,26));
        swap(27,rand(0,27));
        swap(28,rand(0,28));
        swap(29,rand(0,29));
        swap(30,rand(0,30));
        swap(31,rand(0,31));
        swap(32,rand(0,32));
        swap(33,rand(0,33));
        swap(34,rand(0,34));
        swap(35,rand(0,35));
        swap(36,rand(0,36));
        swap(37,rand(0,37));
        swap(38,rand(0,38));
        swap(39,rand(0,39));
        swap(40,rand(0,40));
        swap(41,rand(0,41));
        swap(42,rand(0,42));
        swap(43,rand(0,43));
        swap(44,rand(0,44));
        swap(45,rand(0,45));
        swap(46,rand(0,46));
        swap(47,rand(0,47));
        swap(48,rand(0,48));
        swap(49,rand(0,49));
        swap(50,rand(0,50));
        swap(51,rand(0,51));
    }

OK, ok, ça peut être plus court:

package stackexchange;

import java.util.Arrays;

public class ShuffleDry1
{
    static int[] deck = new int[52];

    static void swap(int i, int j){
        if( deck[i]!=deck[j] ){
            deck[i] ^= deck[j];
            deck[j] ^= deck[i];
            deck[i] ^= deck[j];
        }
    }

    static int rand(int min, int max){
        return (int)Math.floor(Math.random()*(max-min+1))+min;
    }

    static void initialize(){
        for( int i=0 ; i<deck.length ; i++ ){
            deck[i] = i;
            swap(i,rand(0,i));
        }
    }

    static void shuffle(){
        while( deck[0]!=0 ) swap(0,deck[0]);
        for( deck[0]=52; deck[0]-->1 ; ) swap(deck[0],rand(deck[0],51));
        swap(0,rand(0,51));
    }

    public static void main(String[] args) {
        initialize();
        System.out.println("init: " + Arrays.toString(deck));
        shuffle();
        System.out.println("rand: " + Arrays.toString(deck));
    }

}

1

Burlesque

Ce que vous demandez réellement, c'est une permutation aléatoire d'une liste d'entiers? r@nous donnera toutes les permutations, et nous choisissons simplement une permutation aléatoire.

blsq ) {1 2 3}r@sp
1 2 3
2 1 3
3 2 1
2 3 1
3 1 2
1 3 2
blsq ) {1 2 3}r@3!!BS
2 3 1

Étant donné que nous avons besoin d'un vrai caractère aléatoire, quelque chose que Burlesque n'est pas capable de faire parce que Burlesque n'a pas de fonctionnalité d'E / S dont vous auriez besoin pour fournir une source de caractère aléatoire via STDIN.

C'est probablement quelque chose que je corrigerai dans la version ultérieure (c'est-à-dire générer une graine aléatoire au démarrage et la pousser vers la pile secondaire ou quelque chose comme ça, mais l'interpréteur Burlesque lui-même n'a pas d'E / S).


0

Javascript

Je ne sais pas si c'est "tricher" mais ma solution utilise le tableau local natif des arguments d'une fonction. J'ai inclus mes propres fonctions de rand() swap()et filldeck(). Fait intéressant, cela devrait fonctionner avec un jeu de n'importe quelle taille.

    var deck = [];

    function shuffle(){
        main(deck.length);
    }

    function main(){
        arguments[0] && swap( arguments[0]-=1, rand(0, deck.length-1) ), main(arguments[0]);
    }

        function rand(min, max){
            return Math.floor( Math.random()*(max-min+1) )+min;
        }

        function swap(x, y){
            var _x = deck[x], _y = deck[y];
            deck[x] = _y, deck[y] = _x;
        }


        function filldeck(dL){
            for(var i=0; i<dL; i++){
                var ran = rand(1,dL);
                while( deck.indexOf(ran) >= 0 ){
                    ran = rand(1,dL);
                }
                deck[i] = ran;
            }
        }

    filldeck(52);
    shuffle();

C'est de la triche, je pense. Cependant, c'est une tricherie très intelligente, donc un bon travail.
Justin Morgan

0

Tcl , 32 octets

timeFonction abusive qui sert à mesurer le temps passé par un script, mais peut également servir de mécanisme de boucle sans déclarer de variables.

time {lswap $D [rand] [rand]} 52

Essayez-le en ligne!


Ai-je raison de dire que cela n'effectue que 52 swaps aléatoires? Ce n'est pas suffisant pour un vrai remaniement. Je l'ai couru plusieurs fois et j'ai compté en moyenne 8 cartes encore dans leur position de départ, et la probabilité de cela avec un vrai mélange est d'environ 9x10 ^ -6 .
Justin Morgan

@JustinMorgan: Pouvez-vous m'expliquer mieux le calcul de probabilité?
sergiol

-1

perl - ce n'est pas un remaniement approprié comme expliqué dans les commentaires!

my @deck = (0..51);
@deck = sort {rand() <=> rand()} @deck;
print join("\n",@deck);

Je pense que je n'ai rien utilisé comme échange, etc. était-ce nécessaire dans le cadre du problème?


4
Cela fonctionnerait si le tri par une fonction aléatoire était un moyen de produire une distribution aléatoire uniforme. Mais ce n'est pas le cas. -1
aaaaaaaaaaaa

et pourquoi n'est-ce pas? pourriez-vous me donner un lien pour lire ???
sogart

2
La qualité du résultat variera considérablement en fonction de l'algorithme de tri, mais dans presque tous les cas, le résultat sera très loin d'une fonction aléatoire à distribution égale. Voici un article sur le sujet: sroucheray.org/blog/2009/11/…
aaaaaaaaaaaa

-1

JavaScript 4 lignes

function shuffle() {
  while(deck[0]!=0)swap(deck[0],rand(1,51))
  while(deck[0]++!=104)swap(deck[0]%51+1,rand(1,51))
  deck[0]=0
  swap(0,rand(0,51))
}

Réponse originale qui n'était pas assez aléatoire. L'échange n'était pas garanti de toucher chaque élément du jeu.

// shuffle without locals
function shuffle() {
  deck.map(function(){swap(deck[rand(0,51)],deck[rand(0,51)])});
}

Ne produit pas de véritable mélange aléatoire. Voici un test de visualiseur: jsfiddle.net/muk1bthm . J'ai shufflelégèrement changé votre code pour qu'il corresponde à mon swapimplémentation, mais le voici: textuellement: jsfiddle.net/m7km4u6g
Justin Morgan

Pour clarifier, le commentaire ci-dessus s'applique à la nouvelle version, qui n'est toujours pas aléatoire.
Justin Morgan
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.