Baralhar um baralho sem variáveis ​​locais [fechado]


14

O objetivo deste quebra-cabeça é pegar um baralho de 52 cartas e embaralhá-lo para que cada carta esteja em uma posição aleatória.

Dado:

  • Uma matriz deckde 52 números inteiros distintos representando os cartões. Quando você inicia, deckcontém exatamente um de cada cartão em alguma ordem desconhecida.
  • Uma função int rand(min, max),, que retorna um número inteiro aleatório entre ints mine max, inclusive. Você pode assumir que esta função é verdadeiramente aleatória.
  • Uma função void swap(x, y)que troca duas cartas no baralho. Se você ligar swap(x, y), os cartões nas posições xe ytrocarão de lugar.

Quando:

  • O programa chama shuffle()(ou shuffle(deck)ou deck.shuffle()ou como sua implementação gosta de executar),

Então:

  • deck deve conter exatamente um de cada cartão em ordem perfeitamente aleatória.

A pegada:

Você não pode declarar nenhuma variável. Ligue swape randquantas vezes quiser, mas você não pode declarar nenhuma variável sua. Isso inclui forcontadores de loop - mesmo implícitos, como em a foreach.

Esclarecimentos:

  • Você pode alterar detalhes menores para se adequar ao idioma escolhido. Por exemplo, você pode escrever swappara alternar dois números inteiros por referência. As alterações devem ser para facilitar o trabalho no seu idioma, não para facilitar o quebra-cabeça.
  • deck pode ser uma variável global ou você pode aceitá-la como um parâmetro.
  • Você pode fazer o que quiser com o conteúdo deck, mas não pode alterar o comprimento.
  • Seus cartões podem ser numerados de 0 a 51, 1-52 ou qualquer coisa que você desejar.
  • Você pode escrever isso em qualquer idioma, mas sem trapacear com a função interna do seu idioma shuffle.
  • Sim, você pode escrever a mesma linha 52 vezes. Ninguém ficará impressionado.
  • O tempo de execução não importa, mas a verdadeira aleatoriedade importa.
  • Isso não é realmente um código de golfe, mas fique à vontade para minimizar / ofuscar seu código.

Edit: Visualizador de código e visualizador

Se você usou .NET ou JavaScript, aqui estão alguns códigos de teste que podem ser úteis:

JavaScript:

C #:

Esse código classifica e embaralha o baralho milhares de vezes e realiza alguns testes básicos de sanidade: Para cada baralhamento, verifica se há exatamente 52 cartas no baralho sem repetições. Em seguida, o visualizador plota a frequência de cada cartão que termina em cada local do baralho, exibindo um mapa de calor em escala de cinza.

A saída do visualizador deve parecer neve sem padrão aparente. Obviamente, não pode provar a verdadeira aleatoriedade, mas é uma maneira rápida e fácil de verificar. Eu recomendo usá-lo ou algo parecido, porque certos erros no algoritmo de reprodução aleatória levam a padrões muito reconhecíveis na saída. Aqui está um exemplo da saída de duas implementações, uma com uma falha comum:

Saída do visualizador

A versão defeituosa embaralha parcialmente o baralho, portanto, pode parecer bem se você examinar a matriz manualmente. O visualizador facilita a observação de um padrão.


Matrizes de modelos de muitos idiomas são efetivamente infinitas, permitindo assim que $ deck [52] e a partir de agora sejam usados ​​no lugar de variáveis ​​locais. Talvez isso deva ser proibido também.
Timwi

2
As funções são consideradas variáveis? os parâmetros de função são considerados variáveis?
zzzzBov

1
@zzzzBov - O que eu tinha em mente era que os parâmetros de função seriam considerados variáveis, mas não especifiquei isso antes da resposta de @ mellamokb. Eu sei que isso pode ser feito sem nenhum parâmetro que não seja deckele próprio.
Justin Morgan

1
@eBusiness - Isso é um problema para mim, não a pergunta em si. E eu estava votando porque o atendente encontrou uma brecha.
Justin Morgan

1
@ usuário desconhecido - acho que entendo. A resposta é basicamente que você pode assumir qualquer implementação que swapdesejar, desde que cumpra seu objetivo básico. Parte da minha razão de dar swapum certo foi para que as pessoas pudessem tratá-lo como 'mágico' e se concentrar no problema principal sem ter que se preocupar com o fato de ele funcionar no idioma de sua escolha. Você pode fazer isso ou escrever o seu próprio swap, é com você.
Justin Morgan

Respostas:


9

Javascript

Eu acredito que esta é a forma pretendida de solução, eu uso o cartão na posição 0 para acompanhar o progresso, apenas embaralhando os cartões que já foram usados ​​como contador, isso atinge o padrão 52! permutações com uma distribuição igual perfeita. O procedimento é complicado pela troca de XOR, não permitindo que um elemento seja trocado por si só.

Edit: Eu construí uma classificação que classifica cada elemento no lugar imediatamente antes de ser usado, permitindo que isso funcione com uma matriz não classificada. Também abandonei as chamadas recursivas em favor de um loop 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>")
}

Isso é exatamente o que eu tinha em mente. Assim que eu testar, voto e provavelmente aceito.
Justin Morgan

Parece funcionar bem, embora em uma inspeção mais detalhada não seja exatamente igual à minha. Aceito, e postarei minha própria resposta em breve.
Justin Morgan

Isso também é conhecido como algoritmo de reprodução aleatória de Knuth ( en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle ).
19411 Bob

14

Haskell

Aqui está uma implementação sem pontos. Sem variáveis, parâmetros formais ou recursão explícita. Eu costumava lambdabot 's @pl( 'inútil') recurso de refatoração um pouco.

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]

Aqui está o meu procedimento de teste para garantir que os números foram distribuídos uniformemente:

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

Aqui está o algoritmo original:

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 para Haskell. Agora eu tenho que aprender Haskell para que eu possa ler isso. : P
Justin Morgan

Como o progresso é armazenado?
Aaaaaaaaaaaa

8
Duvido que alguém, exceto os programadores da Haskell, diga que seu código não faz sentido e se orgulhe dele.
Aaaaaaaaaaaa

4
Este ((.) .) . (. (++))e este (((.) . (,)) .)são os meus favoritos. Uau lambdabot. Apenas Uau.
Dan Burton

2
@eBusiness "ponto livre" não é o mesmo que "inútil".
Fredoverflow 01/03

6

J

Ignorar esse baralho é uma variável, há o óbvio ...

52 ? 52

Obviamente, se você realmente deseja uma função, existe isso, que funcionará mesmo se você esquecer de remover os curingas (ou tentar embaralhar algo diferente de cartões).

{~ (# ? #)

De modo a...

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

Provavelmente, isso está fora da intenção da pergunta, que seria implementar o embaralhamento de rand ( ?). Eu poderia fazer isso mais tarde, quando não deveria estar trabalhando.

Explicação

Explicação de 52 ? 52:

  • x ? y é x itens únicos aleatórios de y.

A explicação de {~ (# ? #)é mais difícil por causa de garfos e ganchos . Basicamente, é o mesmo que shuffle =: 3 : '((# y) ? (# y)) { y', que possui um argumento implícito ( y).

  • # y dá o comprimento de y
  • Isso dá 52? 52 como antes, que é uma permutação aleatória de 0..51
  • x { y é o item de y no índice x, ou (nesse caso) itens nos índices em x.
  • Isso permite que você embaralhe o que for passado, não apenas números inteiros.

Consulte J Vocabulary para obter detalhes dos operadores, embora a sintaxe e a semântica sejam um pouco complicadas devido à programação tácita e de classificação.


+1: Trabalhando no code-golf quando deveria estar trabalhando .. lol eu também: P
mellamokb

1
Você pode explicar o que isso faz para os com deficiência de J? Recentemente, ouvi-o descrito como uma explosão em uma fábrica de emoticons ( codegolf.stackexchange.com/questions/1294/anagram-code-golf/… ), que parece estar certa.
Justin Morgan

@ Justin: Explicação adicionada.
precisa

Isso funciona também no APL. A sintaxe é a mesma, por isso não vou incomodar adicionando uma nova resposta ( {52?⍵}é uma função anônima que leva 52 itens aleatórios de seu argumento, que aqui seria uma lista de 52 números inteiros)
Arc676

4

Pitão

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

O que [1:]significa isso? Isso ocorre em uma sub-matriz de deck?
Justin Morgan

Sim, [1:] significa a sub-matriz do índice 1 até o final da matriz. Portanto, ele recursivamente embaralha tudo, exceto o primeiro elemento, atribui (copia) de volta ao mesmo local na matriz original e coloca aleatoriamente o primeiro elemento em algum lugar.
Keith Randall

Muito esperto. Eu acho que essa é uma das soluções mais bonitas aqui e usa o algoritmo Fisher-Yates corretamente. +1. Essa tem sido uma ótima maneira de ver a beleza das línguas com as quais não estou familiarizado.
Justin Morgan

2
Você pode gostar do a, b = b, atruque.
Ray

3

Usando representação fatorádica

Na representação fatorádica de uma permutação, um elemento i leva valores de 0 a Ni. Portanto, uma permutação aleatória é apenas rand(0,i)para todo Ni.

Em J:

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

onde ? xé rand(0,x-1)e |.>:i.52é52 51 ... 1

Então, se aé o valor do om factoradic, nós fazemos o swap: swap(deck[i], deck[i+a]). A lista de pares a serem trocados são:

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

A troca que usaremos funciona assim:

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

Não é realmente "por referência", mas não há funções reais em J.

Usaremos o comprimento do deck ( #deck) para evitar o uso de uma constante.

Programa completo em 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 #

Aqui está minha própria resposta baseada no algoritmo de Fisher-Yates . Você deve embaralhar perfeitamente se o gerador de números aleatórios for bom o suficiente.

Versão em inglês:

  1. Troque repetidamente o cartão em deck[0]pelo deck[v]que vestá em , onde está o valor nominal do cartão em deck[0]. Repita até v == 0. Isso classificará parcialmente o baralho, mas isso não importa. Agora você sabe que o cartão 0 está na frente do baralho, o que significa que você pode roubar esse espaço na matriz e usá-lo como um contador de loop. Esta é a chave "trapaça" para o problema de variáveis ​​locais.
  2. Começando na posição 1 (a segunda carta do baralho), troque a carta icom a que está em rand(i, 51). Note que você precisa rand(i, 51), NÃO rand(1, 51) . Isso não garante que cada cartão seja randomizado.
  3. Set deck[0]de volta a 0. Agora, todo o baralho é embaralhado exceto para o primeiro cartão, então troca deck[0]com deck[rand(0, 51)]e está feito.

Versão 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)]);
}

Versão 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));

... onde swap(a, b)swaps deck[a]com deck[b].


2

Ruby, uma linha

Isso é considerado trapaça? Deve ser o mais aleatório possível.

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

(O randmétodo Ruby usa apenas um argumento e gera um número n tal que 0 <= número <argumento.)

Além disso - semelhante à solução Perl da sogart, mas até onde eu sei, ela não sofre com o problema:

deck = deck.sort_by{rand}

O sort_by de Ruby é diferente de sort - ele primeiro gera a lista de valores para classificar a matriz e somente depois a classifica por eles. É mais rápido quando é caro descobrir a propriedade pela qual estamos classificando, um pouco mais lento em todos os outros casos. Também é útil no código de golfe: P


Eu não chamaria isso de trapaça, por si só, mas deck[0..51]evita um pouco a regra "sem variáveis" usando um recurso do idioma. É justo, acho que perde um pouco do desafio. :) Eu não conheço Ruby; você pode explicar a (0..51).map{deck.delete_at(rand deck.length)}parte? Isso exclui os cartões deck?
23811 Justin Morgan

@JustinMorgan sim, 52 vezes ele exclui um cartão aleatório decke o adiciona à lista interna de resultados que mapestá acumulando. Então, quando não há mais nada deckno mapresultado é copiado para deck. Basicamente há um temporária, mas é um recurso de linguagem, em vez de uma variável explícita :)
Hobbs

deck.sort_by!{rand}é mais curto.
22617 Eric Duminil

1

Javascript

NOTA: Esta solução tecnicamente não está correta porque usa um segundo parâmetro i, na chamada para shuffle, que conta como uma variável externa.

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

Ligue com shuffle(deck,52)

Um exemplo de trabalho completo (teve que ser modificado swapum pouco porque não há passagem por referência de ints no 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);

Bem feito. O que eu tinha em mente era considerar parâmetros shufflecomo variáveis, mas não especifiquei isso com +1. Bom uso de recursão também.
Justin Morgan

-1, não gera todas as permutações, isso é óbvio porque o elemento 51 nunca ocupará seu lugar original e porque você só chama rand o suficiente para gerar 51! permutações fora do possível 52!
Aaaaaaaaaaaa

2
@eBusiness: na especificação original, o deck é ordenado arbitrariamente, não necessariamente na ordem de 1 a 52. Eu apenas usei isso porque era o mais fácil.
mellamokb

1
@eBusiness: modifiquei para permitir a possibilidade de deixar o elemento no mesmo local, usando em deck[rand(0,i-1)]vez de deck[rand(0,i-2)]. Troque também todo o caminho em i=0vez de parar em i=1. Isso ajuda?
mellamokb

Sim, isso deve ser feito, exceto que você agora quebra a especificação de troca 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] << " ";
}

Evita a troca de elementos entre si, portanto, é necessário chamar duas vezes para ser aleatório.


swap(deck[rand(1, 51)], (deck[0] - 51) / 100);Como swapsaberá onde colocar o segundo valor? Você também está faltando ).
Justin Morgan

Opa, obrigado. Comecei a mover essa parte durante uma revisão e devo ter me distraído antes de terminá-la: P
Matthew Leia

O voto negativo não era de mim, aliás. Vou testar quando puder.
perfil completo de Justin Morgan

ESTÁ BEM. Facilitei o teste fornecendo um programa completo.
Matthew Leia

1
Muito esperto. Minha própria solução usada deck[0], mas não da maneira que você tem.
Justin Morgan

1

D

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

Outra solução Perl, que na verdade produz resultados uniformemente distribuídos:

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

say join " ", shuffle_integers 1 .. 52;

Esta solução usa Perl rand, que retorna um número aleatório x no intervalo de 0 ≤ x <1. Ele adiciona um número aleatório a cada número inteiro na entrada, classifica os números de acordo com suas partes fracionárias e, finalmente, retira essas partes fracionárias novamente .

(Eu acredito que o uso das variáveis especiais $_, $ae $binsere-se no espírito do desafio, já que esses são como perl passa a entrada para mape sort, e eles não são usados para qualquer outro propósito no código. Em qualquer caso, eu acredito eles são realmente aliases para os valores de entrada, não cópias independentes Este não é realmente um shuffle no lugar, embora,. tanto mape sortcriar cópias de entrada na pilha).


1

Java

Estou surpreso que ninguém tenha declarado o óbvio: (presumo que a troca (x, x) não faça nada.

    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, pode ser mais curto:

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

O que você está realmente pedindo é uma permutação aleatória de uma lista de números inteiros? r@nos dará todas as permutações, e apenas selecionamos uma aleatória.

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

Como precisamos da verdadeira aleatoriedade, algo que o Burlesque não é capaz de fazer porque o Burlesque não possui funcionalidade de E / S, você precisará fornecer uma fonte de aleatoriedade através do STDIN.

Provavelmente isso é algo que eu corrigirei na versão posterior (ou seja, gere uma semente aleatória na inicialização e envie-a para a pilha secundária ou algo parecido, mas o próprio Burlesque Interpreter não possui E / S).


0

Javascript

Não tenho certeza se está "trapaceando", mas minha solução usa a matriz local nativa dos argumentos de uma função. Eu incluí minhas funções criadas por si rand() swap()e de filldeck(). De nota interessante, isso deve funcionar com um deck de qualquer tamanho.

    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();

Está enganando, eu acho. No entanto, é uma trapaça muito inteligente, um trabalho tão bom.
Justin Morgan

0

Tcl , 32 bytes

timeFunção de abuso que serve para medir quanto tempo é gasto em um script, mas também pode servir como um mecanismo de loop sem declarar nenhuma variável.

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

Experimente online!


Estou certo de que isso realiza apenas 52 swaps aleatórios? Isso não é suficiente para um verdadeiro embaralhamento. Corri-o algumas vezes e contei uma média de 8 cartas ainda em suas posições iniciais, e a probabilidade disso com um baralhamento verdadeiro é de cerca de 9x10 ^ -6 .
Justin Morgan

@JustinMorgan: Você pode me explicar melhor o cálculo da probabilidade?
sergiol

-1

perl - este não é um shuffle adequado, como explicado nos comentários!

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

Eu acho que não usei nada como troca, etc. foi necessário como parte do problema?


4
Isso funcionaria se a classificação por uma função aleatória fosse uma maneira de produzir uma distribuição aleatória uniforme. No entanto, não é. -1
aaaaaaaaaaaa

e por que não é? você poderia me dar um link para ler ???
sogart

2
A qualidade do resultado variará bastante, dependendo do algoritmo de classificação, mas em quase todos os casos o resultado estará muito longe de uma função aleatória de distribuição igual. Aqui está um artigo sobre o assunto: sroucheray.org/blog/2009/11/…
aaaaaaaaaaaa

-1

JavaScript 4 linhas

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

Resposta original que não foi aleatória o suficiente. A troca não era garantida para tocar em cada item no baralho.

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

Não produz uma verdadeira aleatória aleatória. Aqui está um teste do visualizador: jsfiddle.net/muk1bthm . Mudei o seu shufflecódigo ligeiramente para coincidir com a minha swapaplicação, mas aqui é textualmente: jsfiddle.net/m7km4u6g
Justin Morgan

Para esclarecer, o comentário acima se aplica à nova versão, que ainda não é aleatória.
23415 Justin Justin2 de
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.