Kocok deck tanpa variabel lokal [ditutup]

14

Tujuan dari teka-teki ini adalah untuk mengambil setumpuk 52 kartu dan mengocoknya sehingga setiap kartu berada dalam posisi acak.

Diberikan:

  • Array,, deckdari 52 bilangan bulat berbeda yang mewakili kartu. Ketika Anda mulai, deckberisi persis satu dari setiap kartu dalam urutan yang tidak diketahui.
  • Fungsi,, int rand(min, max)yang mengembalikan bilangan bulat acak antara int mindan max, inklusif. Anda dapat mengasumsikan bahwa fungsi ini benar-benar acak.
  • Suatu fungsi, void swap(x, y)yang menukar dua kartu di dek. Jika Anda menelepon swap(x, y), kartu di posisi xdan yakan berpindah tempat.

Kapan:

  • Program panggilan shuffle()(atau shuffle(deck)atau deck.shuffle()atau Namun implementasi Anda suka untuk menjalankan),

Kemudian:

  • deck harus berisi tepat satu dari setiap kartu dalam urutan acak sempurna.

Tangkapan:

Anda tidak dapat mendeklarasikan variabel apa pun. Panggil swapdan randsebanyak yang Anda suka, tetapi Anda tidak dapat mendeklarasikan variabel Anda sendiri. Ini termasuk forpenghitung lingkaran - bahkan yang tersirat seperti dalam a foreach.

Klarifikasi:

  • Anda dapat mengubah detail kecil agar sesuai dengan bahasa pilihan Anda. Misalnya, Anda dapat menulis swapuntuk mengganti dua bilangan bulat dengan referensi. Perubahan seharusnya membuat ini berfungsi dengan bahasa Anda, bukan untuk membuat teka-teki lebih mudah.
  • deck bisa menjadi variabel global, atau Anda bisa menganggapnya sebagai parameter.
  • Anda dapat melakukan apa saja yang Anda inginkan deck, tetapi Anda tidak dapat mengubah panjangnya.
  • Kartu Anda dapat diberi nomor 0-51, 1-52, atau apa pun yang Anda suka.
  • Anda dapat menulis ini dalam bahasa apa pun, tetapi jangan curang dengan shufflefungsi bawaan bahasa Anda .
  • Ya, Anda bisa menulis baris yang sama 52 kali. Tidak ada yang akan terkesan.
  • Waktu eksekusi tidak penting, tetapi keacakan yang sebenarnya tidak penting.
  • Ini bukan kode golf, tapi jangan ragu untuk memperkecil / mengaburkan kode Anda.

Sunting: Kode dan visualizer Boilerplate

Jika Anda menggunakan .NET atau JavaScript, berikut ini beberapa kode uji yang mungkin berguna bagi Anda:

JavaScript:

C #:

Kode ini mengurutkan dan mengocok deck beberapa ribu kali dan melakukan beberapa pengujian kewarasan dasar: Untuk setiap shuffle, kode ini memverifikasi bahwa ada tepat 52 kartu di dalam deck tanpa pengulangan. Kemudian visualizer memplot frekuensi setiap kartu berakhir di setiap tempat di geladak, menampilkan peta panas skala abu-abu.

Output visualizer akan terlihat seperti salju tanpa pola yang jelas. Jelas itu tidak dapat membuktikan keacakan yang sebenarnya, tetapi ini adalah cara yang cepat dan mudah untuk melakukan pemeriksaan spot. Saya sarankan menggunakannya atau sesuatu seperti itu, karena kesalahan tertentu dalam algoritma pengocokan menyebabkan pola yang sangat dikenali dalam output. Berikut adalah contoh dari output dari dua implementasi, satu dengan kelemahan umum:

Output Visualizer

Versi cacat sebagian mengocok dek, jadi mungkin terlihat baik jika Anda memeriksa array dengan tangan. Visualizer memudahkan untuk melihat suatu pola.

Justin Morgan
sumber
Banyak bahasa memodel array sebagai infinite efektif, sehingga memungkinkan $ deck [52] dan seterusnya digunakan sebagai pengganti variabel lokal. Mungkin ini harus dilarang juga.
Timwi
2
Apakah fungsi dianggap variabel? apakah parameter fungsi dianggap variabel?
zzzzBov
1
@zzzzBov - Apa yang ada dalam pikiran saya adalah bahwa parameter fungsi akan dianggap variabel, tapi saya tidak menentukan itu sebelum jawaban @ mellamokb. Saya tahu itu bisa dilakukan tanpa parameter selain deckitu sendiri.
Justin Morgan
1
@ eBusiness - Itu masalah dengan saya, bukan pertanyaannya sendiri. Dan saya kecewa karena penjawab menemukan celah.
Justin Morgan
1
@ pengguna tidak diketahui - saya pikir saya mengerti. Jawabannya pada dasarnya adalah bahwa Anda dapat mengasumsikan implementasi apa pun yang swapAnda suka, asalkan memenuhi tujuan dasarnya. Bagian dari alasan saya swapmemberikan sesuatu adalah agar orang-orang dapat memperlakukannya sebagai 'sihir' dan berkonsentrasi pada masalah utama tanpa harus khawatir itu berfungsi dalam bahasa pilihan mereka. Anda dapat melakukannya atau menulis sendiri swap, terserah Anda.
Justin Morgan

Jawaban:

9

JavaScript

Saya percaya ini adalah bentuk solusi yang dimaksudkan, saya menggunakan kartu pada posisi 0 untuk melacak kemajuan, hanya mengocok kartu yang telah digunakan sebagai penghitung, ini mencapai standar 52! permutasi dengan distribusi sama sempurna. Prosedurnya rumit oleh XOR swap yang tidak memungkinkan elemen ditukar dengan sendirinya.

Sunting: Saya membuat penyortiran yang menyortir setiap elemen ke tempatnya tepat sebelum digunakan, sehingga memungkinkan ini bekerja dengan array yang tidak disortir. Saya juga menjatuhkan panggilan rekursif yang mendukung loop sementara.

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>")
}
aaaaaaaaaaaa
sumber
Itulah yang ada dalam pikiran saya. Segera setelah saya menguji ini, saya akan menjawab dan mungkin menerima.
Justin Morgan
Tampaknya bekerja dengan baik, meskipun pada pemeriksaan lebih dekat itu tidak persis sama dengan milik saya. Diterima, dan saya akan segera mengirimkan jawaban saya sendiri.
Justin Morgan
Ini juga dikenal sebagai algoritma Knuth shuffle ( en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle ).
Bob
14

Haskell

Berikut ini adalah implementasi bebas poin. Tidak ada variabel, parameter formal, atau rekursi eksplisit. Aku digunakan lambdabot 's @pl( 'sia-sia') refactoring fitur cukup sedikit.

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]

Inilah prosedur pengujian saya untuk memastikan angka-angka itu terdistribusi secara seragam:

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

Berikut adalah algoritma aslinya:

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
Joey Adams
sumber
+1 untuk Haskell. Sekarang saya harus belajar Haskell sehingga saya bisa membaca ini. : P
Justin Morgan
Bagaimana kemajuan disimpan?
aaaaaaaaaaaa
8
Saya ragu siapa pun kecuali programmer Haskell akan mengatakan bahwa kode mereka tidak ada gunanya dan bangga akan hal itu.
aaaaaaaaaaaa
4
Ini ((.) .) . (. (++))dan ini (((.) . (,)) .)adalah favorit saya. Wow, lambdabot. Cuma wow.
Dan Burton
2
@eBusiness "point free" sama sekali tidak sama dengan "pointless".
fredoverflow
6

J

Mengabaikan dek itu variabel, ada yang jelas ...

52 ? 52

Tentu saja, jika Anda benar-benar menginginkan suatu fungsi, ada ini, yang akan berfungsi bahkan jika Anda lupa menghapus pelawak (atau mencoba mengocok sesuatu selain kartu).

{~ (# ? #)

Yang seperti itu...

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

Ini mungkin di luar maksud pertanyaan, yang akan mengimplementasikan shuffle diri Anda dari rand ( ?). Saya mungkin melakukannya nanti ketika saya tidak seharusnya bekerja.

Penjelasan

Penjelasan tentang 52 ? 52:

  • x ? y adalah x item unik acak dari y.

Penjelasan {~ (# ? #)lebih sulit karena garpu dan kait . Pada dasarnya, ini sama dengan shuffle =: 3 : '((# y) ? (# y)) { y', yang memiliki satu argumen implisit ( y).

  • # y memberi panjang y
  • Ini memberi 52? 52 seperti sebelumnya, yang merupakan permutasi acak 0..51
  • x { y adalah item y dalam indeks x, atau (dalam hal ini) item dalam indeks dalam x.
  • Ini memungkinkan Anda mengacak apa pun yang dilewatkan, bukan hanya bilangan bulat.

Lihat J Vocabulary untuk perincian operator, meskipun sintaks dan semantiknya agak rumit karena pemrograman peringkat dan diam-diam.

Jesse Millikan
sumber
+1: Bekerja pada kode-golf ketika seharusnya bekerja .. lol Saya juga: P
mellamokb
1
Bisakah Anda jelaskan apa yang dilakukan untuk orang yang cacat? Baru-baru ini saya mendengarnya digambarkan sebagai ledakan di pabrik emoticon ( codegolf.stackexchange.com/questions/1294/anagram-code-golf/… ), yang terdengar benar.
Justin Morgan
@Justin: Penjelasan ditambahkan.
Jesse Millikan
Ini bekerja di APL juga. Sintaksnya sama, jadi saya tidak akan repot menambahkan jawaban baru ( {52?⍵}adalah fungsi anonim yang mengambil 52 item acak dari argumennya, yang di sini akan menjadi daftar 52 bilangan bulat)
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))
Keith Randall
sumber
Apa [1:]artinya? Apakah itu berulang pada sub-array deck?
Justin Morgan
Ya, [1:] berarti subarray dari indeks 1 ke akhir array. Jadi secara acak mengocok semuanya kecuali elemen pertama, menugaskan (salinan) kembali ke tempat yang sama dalam array asli, lalu secara acak menempatkan elemen pertama di suatu tempat.
Keith Randall
Sangat pintar. Saya pikir ini adalah salah satu solusi tercantik di sini, dan menggunakan algoritma Fisher-Yates dengan benar. +1. Ini merupakan cara yang baik bagi saya untuk melihat keindahan bahasa yang tidak saya kenal.
Justin Morgan
2
Anda mungkin suka a, b = b, atriknya.
Ray
3

Menggunakan representasi faktoradik

Dalam representasi faktoradik permutasi, elemen i mengambil nilai dari 0 hingga Ni. Jadi permutasi acak hanya rand(0,i)untuk setiap Ni.

Dalam J:

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

di mana ? xadalah rand(0,x-1)dan |.>:i.52adalah52 51 ... 1

Lalu, jika anilai ith factoradic, kita lakukan swap:swap(deck[i], deck[i+a]) . Daftar pasangan yang akan ditukar adalah:

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

Swap kami akan menggunakan karya seperti ini:

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

Ini tidak benar-benar "dengan referensi" tetapi tidak ada fungsi nyata di J.

Kami akan menggunakan panjang dek (#deck ) untuk menghindari penggunaan konstanta.

Program lengkap dalam 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
Eelvex
sumber
3

C #

Ini jawaban saya sendiri berdasarkan algoritma Fisher-Yates . Seharusnya memberi Anda shuffle sempurna jika generator angka acak Anda cukup baik.

Versi bahasa Inggris:

  1. Tukar kartu berulang kali deck[0]dengan yang ada di deck[v], di mana vnilai nominal kartu tersebut berada deck[0]. Ulangi sampaiv == 0 . Ini akan mengurutkan sebagian deck, tetapi itu tidak masalah. Anda sekarang tahu bahwa Kartu 0 ada di bagian depan geladak, yang berarti Anda dapat mencuri ruang itu dalam array dan menggunakannya sebagai penghitung lingkaran. Ini adalah kunci "cheat" untuk masalah variabel lokal.
  2. Mulai dari posisi 1 (kartu kedua di geladak), tukar kartu idengan yang di rand(i, 51). Perhatikan bahwa Anda perlu rand(i, 51), BUKAN rand(1, 51) . Itu tidak akan memastikan bahwa setiap kartu diacak.
  3. Atur deck[0]kembali ke 0. Sekarang seluruh dek dikocok kecuali untuk kartu pertama, jadi tukar deck[0]dengan deck[rand(0, 51)]dan Anda selesai.

Versi 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)]);
}

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

... di mana swap(a, b)bertukar deck[a]dengan deck[b].

Justin Morgan
sumber
2

Ruby, satu baris

Apakah ini dianggap curang? Itu harus acak seperti yang didapat.

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

( randMetode Ruby hanya membutuhkan satu argumen dan kemudian menghasilkan angka n sehingga 0 <= angka <argumen.)

Selain itu - mirip dengan solusi Perl sogart, tetapi sejauh yang saya tahu itu tidak menderita masalah:

deck = deck.sort_by{rand}

Sort_by Ruby berbeda dari sort - Ruby pertama-tama menghasilkan daftar nilai untuk mengurutkan array, dan hanya kemudian mengurutkannya. Lebih cepat ketika mahal untuk mengetahui properti yang kami sortir, agak lambat dalam semua kasus lainnya. Ini juga berguna dalam kode golf: P

Matma Rex
sumber
Saya tidak akan menyebutnya kecurangan, tapi saya deck[0..51]tidak mengesampingkan aturan "no variable" dengan menggunakan fitur bahasa. Itu adil, saya hanya berpikir itu kehilangan beberapa tantangan. :) Saya tidak tahu Ruby; dapatkah Anda menjelaskan (0..51).map{deck.delete_at(rand deck.length)}bagian itu? Apakah itu menghapus kartu deck?
Justin Morgan
@JustinMorgan ya, 52 kali menghapus kartu acak dari deckdan menambahkannya ke daftar internal hasil yang mapterakumulasi. Kemudian ketika ada yang tersisa di deckdalam maphasil akan disalin ke dalam deck. Pada dasarnya ada sementara, tetapi ini adalah fitur bahasa daripada variabel eksplisit :)
hobbs
deck.sort_by!{rand}lebih pendek.
Eric Duminil
1

JavaScript

CATATAN: Solusi ini secara teknis tidak benar karena menggunakan parameter kedua i,, dalam panggilan ke shuffle, yang dianggap sebagai variabel eksternal.

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

Telepon dengan shuffle(deck,52)

Contoh kerja yang lengkap (harus memodifikasi swapsedikit karena tidak ada pass-by-referensi ints di 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);
mellamokb
sumber
Sudah selesai dilakukan dengan baik. Apa yang ada dalam pikiran saya mempertimbangkan parameter shufflesebagai variabel, tapi saya tidak menentukan itu jadi +1. Penggunaan rekursi yang bagus juga.
Justin Morgan
-1, tidak menghasilkan semua permutasi, ini jelas karena elemen 51 tidak akan pernah menempati tempat asalnya, dan karena Anda hanya memanggil cukup rand untuk menghasilkan 51! permutasi dari kemungkinan 52!
aaaaaaaaaaaa
2
@ eBusiness: Dalam spek asli, geladak dipesan sewenang-wenang, tidak harus dalam urutan 1-52. Saya hanya menggunakan itu karena itu yang paling mudah.
mellamokb
1
@ eBusiness: Saya dimodifikasi untuk memungkinkan kemungkinan meninggalkan elemen di tempat yang sama, dengan menggunakan deck[rand(0,i-1)]alih-alih deck[rand(0,i-2)]. Juga bertukar semua cara i=0daripada berhenti i=1. Apakah itu membantu?
mellamokb
Yup, itu harus dilakukan, kecuali Anda sekarang melanggar spesifikasi 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] << " ";
}

Hindari bertukar elemen dengan diri mereka sendiri, jadi harus memanggil dua kali untuk menjadi acak.

Matius Baca
sumber
swap(deck[rand(1, 51)], (deck[0] - 51) / 100);Bagaimana swaptahu di mana harus meletakkan nilai kedua? Anda juga kehilangan a ).
Justin Morgan
Ups, terima kasih. Saya mulai menggerakkan bagian itu selama revisi dan pasti terganggu sebelum menyelesaikannya: P
Matthew Read
Downvote bukan dari saya, BTW. Saya akan menguji kapan saya bisa.
Justin Morgan
BAIK. Saya membuatnya lebih mudah untuk menguji dengan menyediakan program lengkap.
Matius Baca
1
Sangat pintar. Solusi saya sendiri digunakan deck[0], tetapi tidak dengan cara yang Anda miliki.
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..$];
    }
}
aneh ratchet
sumber
1

Solusi Perl lainnya, yang benar-benar menghasilkan keluaran yang terdistribusi secara merata:

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

say join " ", shuffle_integers 1 .. 52;

Solusi ini menggunakan Perl rand, yang mengembalikan angka acak x dalam kisaran 0 ≤ x <1. Ia menambahkan bilangan acak ke setiap bilangan bulat dalam input, mengurutkan angka sesuai dengan bagian fraksinya, dan akhirnya menghilangkan bagian fraksional itu lagi. .

(Saya percaya penggunaan variabel khusus $_, $adan $bberada dalam semangat tantangan, karena itu adalah bagaimana perl melewati input ke mapdan sort, dan mereka tidak digunakan untuk tujuan lain dalam kode. Dalam kasus apa pun, saya percaya mereka sebenarnya alias dengan nilai input, bukan salinan independen. Ini sebenarnya bukan in-place shuffle; keduanya mapdan sortmembuat salinan input pada stack.)

Ilmari Karonen
sumber
1

Jawa

Saya terkejut tidak ada yang menyatakan yang jelas: (Saya akan menganggap swap (x, x) tidak melakukan apa-apa.

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

OKE, OKE, bisa lebih pendek:

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

}
Florian F
sumber
1

Bahan tertawaan

Apa yang sebenarnya Anda minta adalah permutasi acak dari daftar bilangan bulat? r@akan memberi kita semua permutasi, dan kami hanya memilih yang acak.

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

Karena kita membutuhkan keacakan yang sebenarnya, sesuatu yang Burlesque tidak mampu lakukan karena Burlesque tidak memiliki fungsi I / O Anda perlu menyediakan beberapa sumber keacakan melalui STDIN.

Itu mungkin sesuatu yang akan saya perbaiki dalam versi yang lebih baru (yaitu menghasilkan seed acak saat startup dan mendorongnya ke tumpukan sekunder atau sesuatu seperti itu, tetapi Burlesque Interpreter sendiri tidak memiliki I / O).

mroman
sumber
0

Javascript

Saya tidak yakin apakah itu "curang" tetapi solusi saya menggunakan array lokal asli dari argumen fungsi. Saya menyertakan fungsi buatan saya sendirirand() swap() dan filldeck(). Dari catatan yang menarik, ini harus bekerja dengan setumpuk ukuran apa pun.

    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();
path411
sumber
Itu curang, saya pikir. Namun, itu kecurangan yang sangat pintar, pekerjaan yang sangat bagus.
Justin Morgan
0

Tcl , 32 byte

Menyalahgunakan timeFungsi yang berfungsi untuk mengukur berapa banyak waktu yang dihabiskan skrip berjalan, tetapi juga dapat berfungsi sebagai mekanisme pengulangan tanpa mendeklarasikan variabel apa pun.

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

Cobalah online!

sergiol
sumber
Apakah saya benar bahwa ini hanya melakukan 52 swap acak? Itu tidak cukup untuk shuffle sejati. Saya menjalankannya beberapa kali dan menghitung rata-rata 8 kartu masih dalam posisi awal mereka, dan kemungkinan itu dengan shuffle yang benar adalah sekitar 9x10 ^ -6 .
Justin Morgan
@JustinMorgan: Bisakah Anda jelaskan saya lebih baik perhitungan probabilitas?
sergiol
-1

perl - ini bukan shuffle yang tepat seperti dijelaskan dalam komentar!

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

Saya pikir saya tidak menggunakan apa pun sebagai swap dll. Apakah itu diperlukan sebagai bagian dari masalah?

sogart
sumber
4
Itu akan berhasil jika mengurutkan berdasarkan fungsi acak adalah cara menghasilkan distribusi yang bahkan acak. Namun tidak demikian. -1
aaaaaaaaaaaa
dan mengapa tidak? bisakah Anda memberi saya tautan untuk dibaca ???
sogart
2
Kualitas hasil akan sangat bervariasi tergantung pada algoritma pengurutan, tetapi dalam hampir semua kasus hasilnya akan sangat jauh dari fungsi acak distribusi yang sama. Berikut ini adalah artikel tentang masalah ini: sroucheray.org/blog/2009/11/…
aaaaaaaaaaaa
-1

JavaScript 4 baris

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

Jawaban asli yang tidak cukup acak. Swap tidak dijamin untuk menyentuh setiap item di geladak.

// shuffle without locals
function shuffle() {
  deck.map(function(){swap(deck[rand(0,51)],deck[rand(0,51)])});
}
wolfhammer
sumber
Tidak menghasilkan acak acak. Inilah tes visualizer: jsfiddle.net/muk1bthm . Saya mengubah shufflekode Anda sedikit agar sesuai dengan swapimplementasi saya , tetapi ini dia kata demi kata: jsfiddle.net/m7km4u6g
Justin Morgan
Untuk memperjelas, komentar di atas berlaku untuk versi baru, yang masih belum acak.
Justin Morgan