ローカル変数なしでデッキをシャッフルする[終了]


14

このパズルの目的は、52枚のカードのデッキを取り、各カードがランダムな位置になるようにシャッフルすることです。

与えられた:

  • deckカードを表す52個の異なる整数の配列。開始時にdeckは、不明な順序で各カードが1枚ずつ含まれています。
  • int rand(min, max)int minとの間のランダムな整数を返す関数max。この関数は本当にランダムであると仮定できます。
  • void swap(x, y)デッキ内の2枚のカードを交換する機能。を呼び出すswap(x, y)と、カードの位置xと位置yが切り替わります。

いつ:

  • プログラム呼び出しshuffle()shuffle(deck)またはdeck.shuffle()または実装が実行したい場合)。

次に:

  • deck 完全にランダムな順序で各カードを正確に1つ含める必要があります。

キャッチ:

変数を宣言することはできません。swaprandを好きなだけ呼び出しますが、独自の変数を宣言することはできません。これもforループカウンターがますforeach

明確化:

  • 選択した言語に合わせてマイナーな詳細を変更できます。たとえば、次のように書くことができますswap参照によって2つの整数を切り替えるます。変更は、パズルを簡単にするためではなく、あなたの言語でこの作業を行うべきです。
  • deck グローバル変数にすることも、パラメーターとして受け取ることもできます。
  • あなたは何でもやりたいことができます deck、その長さは変更できません。
  • カードには、0〜51、1〜52などの番号を付けることができます。
  • これは任意の言語で記述できますが、言語の組み込みshuffle関数をごまかすことはできません。
  • はい、同じ行を52回書くことができます。誰も感動しません。
  • 実行時間は重要ではありませんが、真のランダム性は重要です。
  • これは実際にはゴルフのコードではありませんが、コードを最小化/難読化してください。

編集:定型コードとビジュアライザー

.NETまたはJavaScriptを使用している場合、次のテストコードが役立ちます。

JavaScript:

C#:

このコードは、デッキを数千回並べ替えてシャッフルし、いくつかの基本的な健全性テストを実行します。各シャッフルについて、繰り返しのないデッキに正確に52枚のカードがあることを確認します。次に、ビジュアライザーがデッキの各場所で終わる各カードの頻度をプロットし、グレースケールのヒートマップを表示します。

ビジュアライザーの出力は、明らかなパターンのない雪のように見えるはずです。明らかに、真のランダム性を証明することはできませんが、スポットチェックを行うための迅速かつ簡単な方法です。シャッフリングアルゴリズムの特定のミスが出力に非常に認識可能なパターンをもたらすため、このようなものを使用することを推奨します。次に、2つの実装からの出力の例を示します。1つには一般的な欠陥があります。

ビジュアライザーの出力

欠陥のあるバージョンはデッキを部分的にシャッフルするため、アレイを手作業で調べた場合は問題なく見えるかもしれません。ビジュアライザーを使用すると、パターンを簡単に認識できます。


多くの言語は、配列を事実上無限にモデル化するため、ローカル変数の代わりに$ deck [52]以降を使用できます。おそらくこれも禁止されるべきです。
ティムウィ

2
関数は変数と見なされますか?関数パラメーターは変数と見なされますか?
zzzzBov

1
@zzzzBov-私が念頭に置いていたのは、関数パラメーターは変数と見なされるということでしたが、@ mellamokbの答えの前にそれを指定しませんでした。それ以外のパラメータなしで実行できることは知っていますdeck
ジャスティンモーガン

1
@eBusiness-それは問題であり、質問そのものではありません。そして、回答者が抜け穴を見つけたので、私は賛成でした。
ジャスティンモーガン

1
@ユーザー不明-私は理解していると思います。答えはswap、基本的な目的を達成する限り、基本的にあなたが好きな実装を想定できるということです。swap与えられた私の理由の一部は、人々がそれを「魔法」として扱い、選択した言語で動作することを心配することなく主要な問題に集中できるようにすることでした。あなたはそれをするか、自分swapで書くことができます、それはあなた次第です。
ジャスティンモーガン

回答:


9

JavaScript

私はこれが解決策の意図された形であると信じています、私は進行状況を追跡するために位置0でカードを使用し、すでにカウンターとして使用されたカードのみをシャッフルします、これは標準52を達成します!完全に等しい分布を持つ順列。この手順は、要素がそれ自体でスワップされることを許可しないXORスワップによって複雑になります。

編集:使用する直前に各要素を所定の場所に並べ替える並べ替えを組み込み、並べ替えられていない配列でこれが機能するようにします。また、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>")
}

それはまさに私が念頭に置いていたものです。私がこれをテストするとすぐに、私は賛成し、おそらく受け入れます。
ジャスティンモーガン

うまく動作しているように見えますが、よく調べてみると私のものとまったく同じではありません。受け入れられました。すぐに回答を投稿します。
ジャスティンモーガン

これは、Knuthシャッフルアルゴリズム(en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle)としても知られています。
ボブ

14

ハスケル

これがポイントフリーの実装です。変数、仮パラメータ、または明示的な再帰はありません。私は使ったlambdabot@pl(「無意味な」)リファクタリング機能をかなり。

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]

数値が均一に分布していることを確認するためのテスト手順は次のとおりです。

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

元のアルゴリズムは次のとおりです。

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の場合は+1。これを読むために、Haskellを学ばなければなりません。:P
ジャスティンモーガン

進捗はどのように保存されますか?
aaaaaaaaaaaa

8
Haskellプログラマ以外は誰も疑わない。彼らのコードは無意味だと言って、誇りに思うだろう。
aaaaaaaaaaaa

4
これ((.) .) . (. (++))とこれ(((.) . (,)) .)は私のお気に入りです。うわー、lambdabot。ただ、すごい。
ダンバートン

2
@eBusinessの「ポイントフリー」は、「ポイントレス」とはまったく異なります。
fredoverflow 14年

6

J

そのデッキが変数であることを無視すると、明らかなことがあります...

52 ? 52

もちろん、本当に機能が必要な場合は、これがあります。これは、ジョーカーを削除するのを忘れた場合(またはカード以外のものをシャッフルしようとした場合)でも機能します。

{~ (# ? #)

そのため...

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

これは、おそらく質問の意図の範囲外です。これは、自分でrandからシャッフルを実装することです(?)です。仕事をすることになっていないときに、後でそうするかもしれません。

説明

説明52 ? 52

  • x ? y yからのx個のランダムな一意のアイテムです。

の説明は{~ (# ? #)フォークとフックのためにより困難です。基本的に、shuffle =: 3 : '((# y) ? (# y)) { y'1つの暗黙的な引数(y)を持つ、と同じです。

  • # y yの長さを与える
  • これは52を与える?前と同様、52。0..51のランダム順列です。
  • x { y は、インデックスxのyのアイテム、または(この場合)xのインデックスのアイテムです。
  • これにより、整数だけでなく、渡されたものをシャッフルできます。

参照してくださいJ語彙の演算子の詳細については、構文と意味があるため、ランクと暗黙のプログラミングのかなりトリッキーですけれども。


+1:働くことになっているときにコードゴルフに取り組む.. lol私も:P
mellamokb

1
J障害のある人のためにこれが何をするのか説明できますか?最近、絵文字工場(codegolf.stackexchange.com/questions/1294/anagram-code-golf/…)の爆発として説明されているのを聞いたが、それはほぼ正しいように聞こえる。
ジャスティンモーガン

@ジャスティン:説明が追加されました。
ジェシーミリカン

これはAPLでも機能します。構文は同じなので、新しい回答を追加することはありません({52?⍵}引数から52のランダムアイテムを
取得

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

どういう[1:]意味ですか?それはサブ配列で再帰しdeckますか?
ジャスティンモーガン

はい、[1:]は、インデックス1から配列の最後までのサブ配列を意味します。そのため、最初の要素以外のすべてを再帰的にシャッフルし、元の配列の同じ場所に割り当て(コピー)、最初の要素をランダムにどこかに配置します。
キースランドール

非常に賢い。これはここで最も美しい解決策の1つであり、Fisher-Yatesアルゴリズムを正しく使用していると思います。+1。これは、私がなじみのない言語の美しさを見る良い方法でした。
ジャスティンモーガン

2
あなたはa, b = b, aトリックが好きかもしれません。
レイ14

3

階乗表現を使用する

factoradic表現順列の要素iが0からNiに対する値をとります。したがって、ランダム置換はrand(0,i)すべてのNiに対してです。

Jで:

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

どこ? xrand(0,x-1)|.>:i.52あります52 51 ... 1

次に、aがi番目の因子の値である場合、スワップを実行しますswap(deck[i], deck[i+a])。スワップするペアのリストは次のとおりです。

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

使用するスワップは次のように機能します。

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

実際には「参照」ではありませんが、Jには実際の関数はありません。

デッキの長さ(#deck)を使用して、定数の使用を避けます。

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#

Fisher-Yatesアルゴリズムに基づく私自身の答えは次のとおりです。乱数ジェネレーターで十分であれば、完璧なシャッフルが得られます。

英語版:

  1. 繰り返しにカードを交換するdeck[0]1つを有するdeck[v]vでカードの額面ですdeck[0]。繰り返すまでv == 0ます。これによりデッキが部分的にソートされますが、それは問題ではありません。これで、カード0がデッキの前面にあることがわかりました。つまり、アレイ内のそのスペースを盗んで、ループカウンターとして使用できます。これは、ローカル変数の問題の重要な「チート」です。
  2. 位置1(デッキの2番目のカード)から開始し、のカードをのカードと交換irand(i, 51)ます。必要rand(i, 51)ではない ことに注意してくださいrand(1, 51)。それは、各カードがランダム化されることを保証しません。
  3. セットdeck[0]0に戻って今全体のデッキは、最初のカードを除いてシャッフルし、そのスワップれるdeck[0]deck[rand(0, 51)]、あなたは完了です。

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

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

...でswap(a, b)スワップdeck[a]する場所deck[b]


2

Ruby、1行

これは不正行為と見なされますか?それは取得するのと同じくらいランダムでなければなりません。

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

(Rubyのrandメソッドは1つの引数のみを取り、0 <= number <引数となるような数nを生成します。)

さらに-sogartのPerlソリューションに似ていますが、私が知る限り、問題の影響を受けません:

deck = deck.sort_by{rand}

Rubyのsort_byはsortとは異なります。最初に値のリストを生成して配列をソートし、その後でのみソートします。並べ替えの対象となるプロパティを見つけるのに費用がかかる場合は高速になりますが、他のすべての場合では多少遅くなります。また、コードゴルフで便利です:P


私はそれを不正行為とは呼びませんdeck[0..51]が、言語の機能を使用することにより、「変数なし」ルールをある程度回避します。それは公平です、私はそれが挑戦のいくつかを失うと思うだけです。:)私はRubyを知りません。その(0..51).map{deck.delete_at(rand deck.length)}部分を説明できますか?それはからカードを削除しdeckますか?
ジャスティンモーガン

@JustinMorganはい、52回ランダムカードを削除し、蓄積しているdeck結果の内部リストに追加しmapます。次にdeckmap結果に何も残っていない場合、にコピーされdeckます。基本的には一時的なものですが、明示的な変数ではなく言語機能です:)
hobbs 14

deck.sort_by!{rand}短いです。
エリックドゥミニル

1

JavaScript

注:このソリューションは、外部変数としてカウントされるのi呼び出しで2番目のパラメーターを使用するため、技術的には正しくありませんshuffle

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

で呼び出す shuffle(deck,52)

完全な作業例(swapJavaScriptにはintの参照渡しがないため、少し変更する必要がありました):

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

よくやった。私が念頭に置いていたのはshuffle、変数としてのパラメーターを考慮することでしたが、そのように指定しませんでした+1。再帰もうまく利用できます。
ジャスティンモーガン

-1はすべての順列を生成しません。要素51が元の場所を占有することはなく、51を生成するのに十分なrandしか呼び出さないため、これは明らかです。可能な52のうちの順列!
aaaaaaaaaaaa

2
@eBusiness:元の仕様では、デッキの順序は任意であり、必ずしも1〜52の順序ではありません。一番簡単だったので、それを使用しました。
mellamokb

1
@eBusiness:のdeck[rand(0,i-1)]代わりにを使用して、要素を同じ場所に残すことができるように修正しましたdeck[rand(0,i-2)]。また、i=0で停止するのではなく、にすべてスワップしi=1ます。それは役立ちますか?
mellamokb

そうです、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] << " ";
}

要素を自分自身と交換することを避けるため、ランダムに呼び出すには2回呼び出す必要があります。


swap(deck[rand(1, 51)], (deck[0] - 51) / 100);swap2番目の値を配置する場所をどのように知るのでしょうか?また、がありません)
ジャスティンモーガン

おっと、ありがとう。私は改正時にその部分を動かし始め、それを終了する前に気を取られてしまっている必要があります:P
マシュー・リードを

ところで、Downvoteは私からではありませんでした。できるときにテストします。
ジャスティンモーガン

OK。完全なプログラムを提供することで、テストしやすくしました。
マシュー

1
非常に賢い。私自身のソリューションが使用されましたがdeck[0]、あなたのやり方ではありませんでした。
ジャスティンモーガン


1

実際に均一に分散された出力を生成する別のPerlソリューション:

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

say join " ", shuffle_integers 1 .. 52;

このソリューションでは、Perlを使用し、0≤の範囲のrand乱数xを返します X <1。これは、入力の各整数を、このような乱数は、その端数部分に応じて番号をソートし、最後に再び離れるもの小数部分を取り除き追加。

(私は特別な変数を使用することを信じて$_$aそして$bそれらはperlがに入力を渡す方法なので、チャレンジ精神に収まるmapsort、それらがコード内の他の目的に使用していない。いずれにせよ、私は信じています。彼らは、これは、実際にその場でシャッフルではないですが、実際には入力値ではなく、独立したコピーのエイリアスです。両方mapsort、スタック上の入力のコピーを作成します)。


1

Java

誰も明らかなことを言っていないことに驚いています:(swap(x、x)は何もしないと仮定します。

    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、もっと短くてもいい:

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

バーレスク

実際に求めているのは、整数のリストのランダムな置換ですか?r@すべての順列が与えられ、ランダムな順列が選択されます。

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

真のランダム性が必要なため、バーレスクにはSTDINを介してランダム性のソースを提供する必要があるI / O機能がないため、バーレスクにはできません。

これはおそらく後のバージョンで修正するものです(つまり、起動時にランダムシードを生成してセカンダリスタックなどにプッシュしますが、バーレスクインタープリター自体にはI / Oがありません)。


0

Javascript

それが「不正」であるかどうかはわかりませんが、私のソリューションは関数の引数のネイティブなローカル配列を使用します。私は私の自作の機能が含まれてrand() swap()filldeck()。興味深いことに、これはあらゆるサイズのデッキで機能するはずです。

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

不正行為だと思います。しかし、それは非常に巧妙な不正行為なので、素晴らしい仕事です。
ジャスティンモーガン

0

Tcl、32バイト

timeスクリプトの実行に費やされた時間を測定するのに役立つ乱用関数ですが、変数を宣言せずにループメカニズムとしても機能できます。

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

オンラインでお試しください!


これは52のランダムスワップのみを実行することを修正しますか?それは本当のシャッフルには十分ではありません。私はそれを数回実行し、まだ開始位置にある平均8枚のカードをカウントしました。真のシャッフルで確率は約9x10 ^ -6です。
ジャスティンモーガン

@JustinMorgan:確率の計算についてもっと詳しく説明してもらえますか?
セルジオ

-1

perl-コメントで説明されているように、これは適切なシャッフルではありません!

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

私はスワップなどとして何も使用しなかったと思います。それは問題の一部として必要でしたか?


4
ランダム関数によるソートが偶数のランダム分布を生成する方法である場合、それは機能します。しかし、そうではありません。-1
aaaaaaaaaaaa

そして、なぜそうではないのですか?読むためのリンクを教えていただけますか?
-sogart

2
結果の品質は、ソートアルゴリズムによって大きく異なりますが、ほとんどすべての場合、結果は等分布のランダム関数から非常に遠くなります。この件に関する記事は次のとおり
aaaaaaaaaaaa

-1

JavaScript 4行

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

ランダムではなかった元の答え。スワップは、デッキの各アイテムに触れることが保証されていませんでした。

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

真のランダムシャッフルは生成されません。ビジュアライザーテストは次のとおりです:jsfiddle.net/muk1bthm 実装shuffleに合わせてコードを少し変更しましたswapが、ここでは逐語的です:jsfiddle.net/m7km4u6g-
ジャスティンモーガン

明確にするために、上記のコメントは新しいバージョンに適用されますが、まだランダムではありません。
ジャスティンモーガン
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.