Yerel değişkenleri olmayan bir desteyi karıştır [kapalı]


14

Bu bulmacanın amacı 52 kartlık bir desteyi almak ve karıştırmaktır, böylece her kart rastgele bir konumdadır.

Verilen:

  • deckKartları temsil eden 52 farklı tamsayıdan oluşan bir dizi . Başladığınızda, deckbilinmeyen bir sırada her karttan tam olarak birini içerir.
  • int rand(min, max)Ints minile maxkapsayıcı arasında rastgele bir tamsayı döndüren bir işlev . Bu işlevin gerçekten rastgele olduğunu varsayabilirsiniz.
  • void swap(x, y)Destedeki iki kartı değiştiren bir işlev . Eğer ararsanız swap(x, y), kartlar pozisyonlarda xve yyer değiştirir.

Ne zaman:

  • Program çağırır shuffle()(veya shuffle(deck)veya deck.shuffle()veya uygulamanız çalışmayı sever),

Sonra:

  • deck her karttan tam olarak birini rasgele sırada içermelidir.

Yakalayış:

Herhangi bir değişken bildiremezsiniz. İstediğiniz kadar arayın swapve randkendinize ait herhangi bir değişken bildiremezsiniz. Bu, fordöngü sayaçlarını içerir - a foreach.

Açıklamalar:

  • Küçük ayrıntıları seçtiğiniz dile uyacak şekilde değiştirebilirsiniz. Örneğin, swapbaşvuru ile iki tamsayıyı değiştirmek için yazabilirsiniz . Değişiklikler, bu bulmacayı kolaylaştırmak için değil, dilinizle çalışacak şekilde yapılmalıdır.
  • deck global bir değişken olabilir veya parametre olarak kabul edebilirsiniz.
  • İçeriğinde istediğiniz her şeyi yapabilirsiniz deck, ancak uzunluğunu değiştiremezsiniz.
  • Kartlarınız 0-51, 1-52 veya istediğiniz herhangi bir şekilde numaralandırılabilir.
  • Bunu herhangi bir dilde yazabilirsiniz, ancak dilinizin yerleşik shuffleişleviyle hile yapamazsınız .
  • Evet, aynı satırı 52 kez yazabilirsiniz. Hiç kimse etkilenmeyecek.
  • Yürütme zamanı önemli değil, ama gerçek rastgelelik önemlidir.
  • Bu gerçekten kod golf değil, ancak kodunuzu en aza indirgemek / gizlemek için çekinmeyin.

Düzenleme: Ortak kod ve görselleştirici

.NET veya JavaScript kullandıysanız, yararlı bulabileceğiniz bazı test kodları aşağıda verilmiştir:

JavaScript:

C #:

Bu kod desteyi birkaç bin kez sıralar ve karıştırır ve bazı temel sağlık testi yapar: Her karıştırma için destede tam olarak 52 kartın tekrarlanmadığını doğrular. Daha sonra görüntüleyici, destedeki her yerde biten her kartın frekansını çizerek gri tonlamalı bir ısı haritası görüntüler.

Görüntüleyicinin çıktısı, belirgin bir deseni olmayan kar gibi görünmelidir. Açıkçası gerçek bir rastlantısallığı kanıtlayamaz, ancak bu nokta kontrol etmenin hızlı ve kolay bir yoludur. Karıştırma algoritmasındaki bazı hatalar çıktıda çok tanınabilir kalıplara yol açtığından, bunu veya bunun gibi bir şeyi kullanmanızı öneririm. Aşağıda, biri ortak bir kusuru olan iki uygulamadan elde edilen çıktıya bir örnek verilmiştir:

Görselleştirici çıkışı

Kusurlu sürüm güverteyi kısmen karıştırır, bu yüzden diziyi elle incelerseniz iyi görünebilir. Görüntüleyici, bir patern fark etmeyi kolaylaştırır.


Birçok dil dizileri etkili bir şekilde sonsuz olarak modellemekte, böylece $ deck [52] ve sonrasında yerel değişkenler yerine kullanılabilmektedir. Belki de bu yasaklanmalıdır.
Timwi

2
Fonksiyonlar değişken kabul edilir mi? parametreleri değişken olarak kabul edilir mi?
zzzzBov

1
@zzzzBov - Aklımda olan şey, işlev parametrelerinin değişkenler olarak kabul edileceğiydi, ancak @ mellamokb'un cevabından önce bunu belirtmedim. deckKendisinden başka herhangi bir parametre olmadan yapılabileceğini biliyorum .
Justin Morgan

1
@ eBusiness - Bu benim için bir sorun, sorunun kendisi değil. Ve cevap veriyordum çünkü cevap veren bir boşluk buldular.
Justin Morgan

1
@ kullanıcı bilinmiyor - sanırım anlıyorum. Cevap, swaptemel amacını yerine getirdiği sürece , istediğiniz herhangi bir uygulamayı varsayabileceğinizdir . swapVerilen bir şeyi yapma nedenimin bir kısmı, insanların ona 'sihir' olarak davranabilmeleri ve tercih ettikleri dilde çalıştıklarından endişe etmeden ana soruna konsantre olabilmeleriydi. Bunu yapabilir veya kendiniz yazabilirsiniz, swapsize kalmış.
Justin Morgan

Yanıtlar:


9

JavaScript

Bunun amaçlanan çözüm biçimi olduğuna inanıyorum, ilerlemeyi izlemek için kartı 0 konumunda kullanıyorum, sadece sayaç olarak kullanılmış olan kartları karıştırıyorum, bu standart 52'ye ulaşıyor! mükemmel eşit dağılımlı permütasyonlar. Prosedür, bir elemanın kendi başına değiştirilmesine izin vermeyecek şekilde XOR takas ile karmaşıktır.

Düzenleme: Ben kullanılmadan hemen önce her öğeyi yerine sıralayan, böylece sıralanmamış bir dizi ile çalışmasına izin veren bir sıralama inşa. Ayrıca bir while döngüsü lehine özyinelemeli çağrı bıraktı.

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

Aklıma gelen de buydu. Kısa bir süre sonra bunu test ederken oyumu kaldırır ve muhtemelen kabul ederim.
Justin Morgan

İyi çalışıyor gibi görünüyor, ancak daha yakından incelendiğinde benimkiyle tam olarak aynı değil. Kabul edildi ve yakında kendi cevabımı göndereceğim.
Justin Morgan

Bu aynı zamanda Knuth shuffle algoritması olarak da bilinir ( en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle ).
Bob

14

Haskell

İşte noktadan bağımsız bir uygulama. Değişkenler, resmi parametreler veya açık özyineleme yok. Kendimi kullanılmış lambdabot 'ın @pl( 'anlamsız') üstlenmeden özelliği biraz.

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]

Sayıların eşit olarak dağıtıldığından emin olmak için test prosedürüm:

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

İşte orijinal algoritma:

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

Haskell için +1. Şimdi bunu okuyabilmek için Haskell'i öğrenmem gerekiyor. : P
Justin Morgan

İlerleme nasıl saklanır?
aaaaaaaaaaaa

8
Haskell programcıları dışında hiç kimsenin kodlarının anlamsız olduğunu ve bundan gurur duyacağını söyleyeceğim.
aaaaaaaaaaaa

4
Bu ((.) .) . (. (++))ve bu (((.) . (,)) .)benim favorim. Vay lambdabot. Vay canına.
Dan Burton

2
@eBusiness "point free", "anlamsız" ile aynı değildir.
fredoverflow

6

J

Bu güverte bir değişkeni görmezden gelmek, belli ki ...

52 ? 52

Tabii ki, gerçekten bir işlev istiyorsanız, jokerleri kaldırmayı (veya kartlardan başka bir şey karıştırmaya çalışsanız bile) işe yarayacak olan bu var.

{~ (# ? #)

Böylece...

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

Bu muhtemelen, shuffle'ı rand ( ?) ' dan uygulamak olacak sorunun niyetinin dışındadır . Daha sonra çalışmamam gerektiğinde bunu yapabilirim.

açıklama

Açıklama 52 ? 52:

  • x ? y x, y'den rastgele rastgele benzersiz öğelerdir.

Çatal ve kancalar{~ (# ? #) nedeniyle açıklaması daha zordur . Temel olarak , bir örtük argümana ( ) sahip olanla aynıdır .shuffle =: 3 : '((# y) ? (# y)) { y'y

  • # y y uzunluğunu verir
  • Bu 52 verir mi? 52 daha önce olduğu gibi, 0..51 rastgele bir permütasyon
  • x { y , x dizinindeki y öğesidir veya (bu örnekte) x dizinindeki öğelerdir.
  • Bu, yalnızca tamsayıları değil, geçirilenleri karıştırmanıza izin verir.

Operatörlerin ayrıntıları için J Kelime haznesine bakın , ancak sözdizimi ve anlambilim, sıralama ve örtük programlama nedeniyle biraz zor.


+1: Çalışması gerektiğinde kod
golfü

1
Bunun J-engelliler için ne yaptığını açıklayabilir misiniz? Geçenlerde bir ifade fabrikasında ( codegolf.stackexchange.com/questions/1294/anagram-code-golf/… ) bir patlama olarak tanımlandığını duydum .
Justin Morgan

@ Justin: Açıklama eklendi.
Jesse Millikan

Bu APL'de de çalışır. Sözdizimi aynıdır, bu yüzden yeni bir cevap eklemeye zahmet etmeyeceğim ( {52?⍵}argümanından 52 rastgele öğe alan anonim bir işlevdir, burada 52 tamsayının bir listesi olacaktır)
Arc676 6:17

4

piton

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

Ne anlama [1:]geliyor? Bu alt dizinin alt dizisi üzerinde geçerli deckmi?
Justin Morgan

Evet, [1:] dizin 1'den dizinin sonuna kadar olan alt dizi anlamına gelir. Bu nedenle, ilk öğe dışındaki her şeyi tekrar tekrar karıştırır, orijinal dizideki aynı yere atar (kopyalar), sonra ilk öğeyi rastgele bir yere yerleştirir.
Keith Randall

Çok zeki. Buradaki en güzel çözümlerden biri olduğunu düşünüyorum ve Fisher-Yates algoritmasını doğru kullanıyor. +1. Bu, aşina olmadığım dillerin güzelliğini görmem için güzel bir yol oldu.
Justin Morgan

2
a, b = b, aHile gibi olabilir .
Ray

3

Factoradic gösterimi kullanma

Gelen factoradic temsil bir permütasyon bir elemanı i, 0 dan Ni değerleri alır. Yani rastgele bir permütasyon sadece rand(0,i)her Ni için.

J dilinde:

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

nerede ? xolduğunu rand(0,x-1)ve |.>:i.52bir52 51 ... 1

Sonra, ai'inci factoradic değeridir, biz takas yapın: swap(deck[i], deck[i+a]). Değiştirilecek çiftlerin listesi:

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

Kullanacağımız takas şu şekilde çalışır:

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

Gerçekten "referans olarak" değil ama J'de gerçek bir işlev yok.

#deckSabit kullanmaktan kaçınmak için deste uzunluğunu ( ) kullanacağız.

J'deki programı tamamlayın:

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 #

İşte Fisher-Yates algoritmasına dayanan kendi cevabım . Rastgele sayı üreteciniz yeterince iyi ise size mükemmel bir karışıklık vermelidir.

İngilizce versiyon:

  1. Kartı, deck[0]üzerindeki kartın nominal değerinin deck[v]olduğu kart ile arka arkaya değiştirin . Tarihine kadar tekrarlayın . Bu, güverteyi kısmen sıralar, ancak bu önemli değildir. Artık Kart 0'ın destenin önünde olduğunu biliyorsunuz, yani dizideki boşluğu çalabilir ve bir döngü sayacı olarak kullanabilirsiniz. Bu, yerel değişkenler için "hile" anahtardır.vdeck[0]v == 0
  2. 1. pozisyondan (destedeki ikinci kart) başlayarak kartı at iile değiştirin rand(i, 51). İhtiyacınız unutmayın rand(i, 51), DEĞİL rand(1, 51) . Bu, her kartın rastgele seçilmesini sağlamaz.
  3. Set deck[0]0'a geri Şimdi bütün güverte takas böylece, ilk karta hariç karıştırılan deck[0]ile deck[rand(0, 51)]bitirdiniz ve.

C # sürümü:

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

Javascript sürümü:

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

... nerede swap(a, b)takasları deck[a]ile deck[b].


2

Ruby, bir satır

Bu hile olarak kabul edilir mi? Olabildiğince rastgele olmalı.

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

(Ruby'nin randyöntemi yalnızca bir bağımsız değişken alır ve sonra 0 <= sayı <bağımsız değişken olacak şekilde bir n sayısı oluşturur.)

Ek olarak - sogart'ın Perl çözümüne benzer, ancak bildiğim kadarıyla sorundan muzdarip değil:

deck = deck.sort_by{rand}

Ruby'nin sort_by öğesi sıralamadan farklıdır - önce diziyi sıralamak için değerler listesini oluşturur ve ancak ondan sonra sıralar. Sıraladığımız mülkü bulmak pahalı olduğunda daha hızlıdır, diğer tüm durumlarda biraz daha yavaştır. Ayrıca kod golfü için de yararlıdır: P


Ben kendi başına hile demezdim, ama deck[0..51]dilin bir özelliğini kullanarak "değişken yok" kuralını biraz etek. Bu adil, sanırım sadece bazı zorlukları kaybediyor. :) Ruby bilmiyorum; Parçayı açıklayabilir misin (0..51).map{deck.delete_at(rand deck.length)}? Bu karttan kart siliyor deckmu?
Justin Morgan

@ JustinMorgan evet, 52 kez rastgele bir kartı siler deckve mapbiriken sonuçların dahili listesine ekler . Sonra kalan şey yokken sonucu içine kopyalanır . Temelde bir geçici var, ama açık bir değişken yerine bir dil özelliği :)deckmapdeck
hobbs

deck.sort_by!{rand}daha kısadır.
Eric Duminil

1

JavaScript

NOT: Bu çözüm teknik olarak doğru değildir, çünkü içağrıda shuffleharici bir değişken olarak sayılan ikinci bir parametre kullanır .

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

İle ara shuffle(deck,52)

Tam bir çalışma örneği ( swapJavaScript'te girişlerin at-referansı olmadığı için biraz değişiklik yapmak zorunda kaldı ):

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

Aferin. Aklımdaki shuffledeğişkenleri parametreler olarak değerlendiriyordum , ama bunu + 1 olarak belirtmedim. Özyineleme de güzel kullanımı.
Justin Morgan

-1, tüm permütasyonları üretmez, bu açıktır çünkü 51. element asla orijinal yerini işgal etmeyecektir ve sadece 51'i üretmek için rand'ı çağırdığınız için! 52 olası permütasyon!
aaaaaaaaaaaa

2
@eBusiness: Orijinal spesifikasyonda, güverte 1-52 sırasına göre değil, keyfi olarak sipariş edilir. Sadece kullandım çünkü en kolayı buydu.
mellamokb

1
@ eBusiness: Öğeyi deck[rand(0,i-1)]yerine kullanarak aynı noktada bırakma olasılığına izin vermek için değiştirdim deck[rand(0,i-2)]. Ayrıca i=0adresinde durmak yerine sonuna kadar değiştirin i=1. Bu yardımcı olur mu?
mellamokb

Evet, bunu yapmalı, ancak şimdi XOR takas şartnamesini kırmanız gerekiyor.
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] << " ";
}

Öğeleri kendileriyle değiştirmekten kaçınır, bu yüzden rastgele olmak için iki kez çağırmak gerekir.


swap(deck[rand(1, 51)], (deck[0] - 51) / 100);swapİkinci değeri nereye koyacağımızı nasıl bileceksin? Ayrıca eksik ).
Justin Morgan

Hata! Bir revizyon sırasında bu parçayı hareket ettirmeye başladım ve bitirmeden önce dikkatini dağıtmış olmalıydım: P
Matthew

Downvote benden değildi, BTW. Ne zaman yapabileceğimi test edeceğim.
Justin Morgan

TAMAM. Tam bir program sağlayarak test etmeyi kolaylaştırdım.
Matthew

1
Çok zeki. Kendi çözümüm kullanıldı deck[0], ama sahip olduğunuz şekilde değil.
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

Eşit olarak dağıtılmış çıktı üreten başka bir Perl çözümü:

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

say join " ", shuffle_integers 1 .. 52;

Bu çözüm, 0 ≤ x <1 aralığında randrasgele bir sayı x döndüren Perl kullanır. Girdideki her tam sayıya bu kadar rasgele bir sayı ekler, sayıları kesirli kısımlarına göre sıralar ve son olarak bu kesirli kısımları tekrar ayırır .

(Ben özel değişkenlerin kullanımını inanıyoruz $_, $ave $bbu perl girdi nasıl geçtiğini olduğundan, mücadele ruhu içinde düşer mapve sortve bunlar kodda başka bir amaç için de kullanılmaz. Her durumda, inanıyorum bunlar aslında giriş değerlerinin takma adlarıdır, bağımsız kopyalar değildir. Bu aslında yerinde bir karışıklık değildir; her ikisi de mapve sortyığındaki girdinin kopyalarını oluşturur.)


1

Java

Kimsenin bariz olduğunu söylemesine şaşırdım: (takas (x, x) hiçbir şey yapmadığını varsayacağım.

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

Tamam, tamam, daha kısa olabilir:

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

vodvil

Aslında istediğin tamsayılar listesinin rastgele permütasyonu mu? r@bize tüm permütasyonları verecek ve biz sadece rastgele bir tane seçelim.

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

Gerçek rasgeleliğe ihtiyacımız olduğundan, Burlesque'nin yapamayacağı bir şey var, çünkü Burlesque'in STDIN aracılığıyla bazı rasgelelik kaynağı sağlamanız gereken I / O işlevselliği yok.

Muhtemelen daha sonraki sürümde düzelteceğim bir şey (başlangıçta rastgele bir tohum üretip ikincil yığına veya bunun gibi bir şeye itin, ancak Burlesque Tercüman'ın kendisinde G / Ç yok).


0

JavaScript

"Hile" olup olmadığından emin değilim ama benim çözümüm bir işlevin argümanlarının yerel yerel dizisini kullanıyor. Ben benim kendini yetiştirmiş fonksiyonları dahil rand() swap()ve filldeck(). İlginç bir not, bu herhangi bir boyutta bir deste ile çalışmalıdır.

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

Sanırım aldatıyor. Ancak, çok zeki bir hile, çok güzel bir iş.
Justin Morgan

0

Tcl , 32 bayt

timeBir betiğin ne kadar zaman harcandığını ölçmeye yarayan kötüye kullanım işlevi, aynı zamanda herhangi bir değişken bildirmeden döngüsel bir mekanizma işlevi görebilir.

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

Çevrimiçi deneyin!


Bunun yalnızca 52 rasgele takas gerçekleştirdiğini düzeltir miyim? Bu gerçek bir karışıklık için yeterli değil. Birkaç kez koştum ve başlangıç ​​pozisyonlarında hala ortalama 8 kart saydım ve gerçek bir shuffle ile bunun olasılığı yaklaşık 9x10 ^ -6 .
Justin Morgan

@JustinMorgan: Olasılık hesaplamasını bana daha iyi açıklayabilir misiniz?
sergiol

-1

perl - Bu açıklamalarda açıklandığı gibi uygun bir shuffle değil!

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

Sanırım bir şey takas olarak kullanmadım. Sorunun bir parçası olarak gerekli miydi?


4
Rastgele bir işleve göre sıralama, hatta rastgele bir dağıtım üretmenin bir yolu olsaydı bu işe yarar. Ancak öyle değil. -1
aaaaaaaaaaaa

ve neden olmasın? bana okumak için bir link verebilir misiniz ???
sogart

2
Sonucun kalitesi, sıralama algoritmasına bağlı olarak büyük ölçüde değişecektir, ancak hemen hemen tüm durumlarda sonuç, eşit dağılımlı rastgele bir işlevden çok uzak olacaktır. İşte konuyla ilgili bir makale: sroucheray.org/blog/2009/11/…
aaaaaaaaaaaa

-1

JavaScript 4 satır

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

Orijinal cevap yeterince rastgele değildi. Takasın destedeki her öğeye dokunacağı garanti edilmedi.

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

Gerçek bir rastgele karıştırma üretmez. İşte bir görselleştirici testi: jsfiddle.net/muk1bthm . shuffleKodumu swapuygulamamla eşleşecek şekilde biraz değiştirdim , ama işte burada: kelimesi kelimesine: jsfiddle.net/m7km4u6g
Justin Morgan

Açıklığa kavuşturmak için, yukarıdaki yorum hala rastgele olmayan yeni sürüm için geçerlidir.
Justin Morgan
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.