지역 변수없이 데크 섞기 [닫기]


14

이 퍼즐의 목적은 52 장의 카드를 가져 와서 섞어서 각 카드가 임의의 위치에 있도록하는 것입니다.

주어진:

  • deck카드를 나타내는 52 개의 고유 정수로 구성된 배열 입니다. 시작할 때, deck알 수없는 순서로 각 카드 중 하나를 정확히 포함합니다.
  • 함수, int rand(min, max)즉 수익률의 int 사이의 임의의 정수 minmax포함,. 이 기능이 실제로 임의라고 가정 할 수 있습니다.
  • void swap(x, y)갑판에서 두 장의 카드를 교환 하는 기능 입니다. 당신이 호출 할 경우 swap(x, y), 위치에서 카드 xy장소를 전환합니다.

언제:

  • 이 프로그램은 전화 shuffle()(또는 shuffle(deck)또는 deck.shuffle()또는 그러나 구현이 실행 좋아)

그때:

  • deck 각 카드 중 하나를 정확히 임의의 순서로 포함해야합니다.

캐치 :

변수를 선언 할 수 없습니다. 전화 swaprand만큼 당신이 원하는대로,하지만 당신은 당신의 자신의 변수를 선언 할 수 없습니다. 여기에는 for루프 카운터와 같은 암시 적 카운터가 포함됩니다 foreach.

설명 :

  • 선택한 언어에 맞게 사소한 세부 사항을 변경할 수 있습니다. 예를 들어, swap참조로 두 정수를 전환하도록 작성할 수 있습니다 . 퍼즐을 쉽게 만들지 말고 언어로 작업 할 수 있도록 변경해야합니다.
  • deck 전역 변수이거나 매개 변수로 사용할 수 있습니다.
  • 의 내용에 대해 원하는 작업을 수행 deck할 수 있지만 길이는 변경할 수 없습니다.
  • 카드 번호는 0-51, 1-52 또는 원하는 번호로 지정할 수 있습니다.
  • 어떤 언어로도 작성할 수 있지만 언어의 내장 shuffle함수를 사용하여 부정 행위를 할 수는 없습니다 .
  • 예, 같은 줄을 52 번 쓸 수 있습니다. 아무도 감동하지 않을 것입니다.
  • 실행 시간은 중요하지 않지만 진정한 임의성은 중요합니다.
  • 이것은 실제로 코드 골프는 아니지만 코드를 최소화 / 난독 화 할 수 있습니다.

편집 : 상용구 코드 및 시각화 프로그램

.NET 또는 JavaScript를 사용한 경우 유용한 테스트 코드가 있습니다.

자바 스크립트 :

씨#:

이 코드는 덱을 수천 번 분류하고 섞으며 기본적인 위생 테스트를 수행합니다. 각 셔플마다 덱에 반복없이 정확히 52 개의 카드가 있는지 확인합니다. 그런 다음 비주얼 라이저는 데크의 각 위치에서 끝나는 각 카드의 빈도를 플롯하여 회색조 히트 맵을 표시합니다.

비주얼 라이저의 출력은 명백한 패턴이없는 눈처럼 보입니다. 분명히 그것은 임의의 무작위성을 증명할 수는 없지만 빠르고 쉽게 스팟 확인하는 방법입니다. 셔플 링 알고리즘의 특정 실수로 인해 출력에서 ​​인식 가능한 패턴이 생길 수 있으므로 이와 같은 것을 사용하는 것이 좋습니다. 다음은 일반적인 결함이있는 두 가지 구현의 출력 예입니다.

시각화 출력

결함이있는 버전은 데크를 부분적으로 섞기 때문에 어레이를 직접 살펴보면 괜찮아 보일 수 있습니다. 비주얼 라이저를 사용하면 패턴을보다 쉽게 ​​확인할 수 있습니다.


많은 언어가 효과적으로 배열을 모델링하여 지역 변수 대신 $ deck [52] 이상을 사용할 수 있습니다. 아마도 이것도 금지되어야합니다.
Timwi

2
함수는 가변적 인 것으로 간주됩니까? 함수 매개 변수가 변수로 간주됩니까?
zzzzBov

1
@zzzzBov-내가 생각한 것은 함수 매개 변수가 변수로 간주된다는 것이지만 @mellamokb의 대답 전에 그것을 지정하지 않았습니다. deck자체 이외의 매개 변수없이 수행 할 수 있다는 것을 알고 있습니다.
저스틴 모건

1
@eBusiness-그것은 문제 자체가 아니라 저에게 문제입니다. 그리고 응답자가 허점을 발견했기 때문에 투표를했습니다.
저스틴 모건

1
@user unknown-이해합니다. 대답은 기본적으로 swap기본 목적을 달성하는 한 원하는 구현을 가정 할 수 있다는 것입니다. swap주어진 것을 만든 나의 이유 중 일부는 사람들이 그것을 '매직'으로 취급하고 그들이 선택한 언어로 작동하는 것에 대해 걱정할 필요없이 주요 문제에 집중할 수 있도록하기 위해서였습니다. 당신이 할 수 있거나 자신의 것을 쓸 수 있습니다 swap, 그것은 당신에게 달려 있습니다.
저스틴 모건

답변:


9

자바 스크립트

나는 이것이 솔루션의 의도 된 형태라고 생각하고, 진행 상황을 추적하기 위해 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>")
}

바로 내가 생각한 것입니다. 내가 이것을 테스트하자마자 나는 찬성하고 아마 받아 들일 것이다.
저스틴 모건

면밀히 살펴보면 내 것과 정확히 같지는 않지만 잘 작동하는 것처럼 보입니다. 수락하고 곧 답변을 게시하겠습니다.
Justin Morgan

이것을 Knuth shuffle 알고리즘이라고합니다 ( en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle ).
Bob

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

하스켈 +1 이제 이것을 읽을 수 있도록 Haskell을 배워야합니다. : P
Justin Morgan

진행 상황은 어떻게 저장됩니까?
aaaaaaaaaaaa

8
Haskell 프로그래머가 아닌 사람은 자신의 코드가 무의미하고 자랑스러워한다고 말할 것입니다.
aaaaaaaaaaaa

4
이것 ((.) .) . (. (++))과 이것은 (((.) . (,)) .)내가 가장 좋아하는 것입니다. 와우 lambdabot. 와우
Dan Burton

2
@eBusiness "point free"는 "pointless"와 전혀 다릅니다.
fredoverflow

6

제이

그 갑판이 변수라는 것을 무시하고 명백한 것이 있습니다 ...

52 ? 52

물론, 실제로 기능을 원한다면 조커를 제거하는 것을 잊어 버려도 (또는 카드 이외의 것을 섞으려고 시도해도) 이것이 작동합니다.

{~ (# ? #)

그래서...

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

이것은 아마도 질문의 의도를 벗어난 것일 수 있으며, 랜드 ( ?) 에서 셔플을 직접 구현하는 것 입니다. 나중에 일하지 않아야 할 때 그렇게 할 수 있습니다.

설명

설명 52 ? 52:

  • x ? y y의 x 임의의 고유 항목입니다.

포크와 후크로{~ (# ? #) 인해 설명 이 더 어렵습니다 . 기본적으로 는 하나의 암시 적 인수 ( )가 있는와 동일 합니다.shuffle =: 3 : '((# y) ? (# y)) { y'y

  • # y y의 길이를 준다
  • 이것은 52를 준다? 이전과 마찬가지로 52는 0의 랜덤 순열입니다.
  • x { y 인덱스 x에서 y의 항목이거나 x의 인덱스에서 (이 경우) 항목입니다.
  • 이를 통해 정수뿐만 아니라 전달 된 모든 것을 섞을 수 있습니다.

구문과 의미는 순위 및 암묵적인 프로그래밍으로 인해 약간 까다 롭지 만 연산자에 대한 자세한 내용은 J 어휘 를 참조하십시오 .


+1 : 코드 골프 작업 중일 때 .. lol 나도 : P
mellamokb

1
이것이 J- 장애인에게 무엇을하는지 설명 할 수 있습니까? 나는 최근에 이모티콘 공장 ( codegolf.stackexchange.com/questions/1294/anagram-code-golf/… ) 에서 폭발로 묘사되었다고 들었습니다 .
저스틴 모건

@Justin : 설명이 추가되었습니다.
Jesse Millikan

이것은 APL에서도 작동합니다. 구문은 동일하므로 새 답변을 추가하지 않아도됩니다 ( {52?⍵}여기서 52 개의 정수 목록이되는 인수에서 52 개의 임의 항목을 가져 오는 익명 함수 임)
Arc676

4

파이썬

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에서 배열 끝까지의 하위 배열을 의미합니다. 따라서 첫 번째 요소를 제외한 모든 요소를 ​​재귀 적으로 섞고 원래 배열의 동일한 위치에 다시 할당 (복사) 한 다음 첫 번째 요소를 임의로 어딘가에 배치합니다.
Keith Randall

매우 영리한. 나는 이것이 여기에서 가장 예쁜 솔루션 중 하나라고 생각하며 Fisher-Yates 알고리즘을 올바르게 사용합니다. +1. 이것은 내가 익숙하지 않은 언어의 아름다움을 볼 수있는 좋은 방법이었습니다.
저스틴 모건

2
당신은 a, b = b, a트릭을 좋아할 것 입니다.
Ray

3

계승 표현 사용

순열 의 계승 표현 에서 원소 i는 0에서 Ni까지의 값을 취합니다. 따라서 임의 순열은 rand(0,i)모든 Ni에 대해서만 적용됩니다.

J에서 :

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

? x이다 rand(0,x-1)하고 |.>:i.52있다52 51 ... 1

그런 다음 ai 번째 인수가 값이면 swap :을 수행합니다 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

씨#

Fisher-Yates 알고리즘을 기반으로 내 대답은 다음과 같습니다 . 난수 생성기가 충분하면 완벽한 셔플을 제공해야합니다.

영문판:

  1. 반복의 카드를 교환 deck[0]의 하나 deck[v], v의 카드의 액면이다 deck[0]. 때까지 반복v == 0 . 이렇게하면 데크가 부분적으로 정렬되지만 중요하지 않습니다. 이제 카드 0이 데크의 앞쪽에 있다는 것을 알았습니다. 즉, 어레이의 해당 공간을 훔쳐 루프 카운터로 사용할 수 있습니다. 이것이 지역 변수 문제의 핵심 "속임수"입니다.
  2. 위치 1 (데크의 두 번째 카드)에서 시작하여 카드를에있는 카드 i와 교체하십시오 rand(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)]);
}

자바 스크립트 버전 :

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

루비, 한 줄

이것이 부정 행위로 간주됩니까? 얻을 수있는만큼 무작위이어야합니다.

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

(Ruby의 rand메소드는 하나의 인수 만 취한 다음 0 <= number <인수가되도록 숫자 n을 생성합니다.)

또한-sogart의 Perl 솔루션과 유사하지만 내가 아는 한 문제가 발생하지 않습니다.

deck = deck.sort_by{rand}

Ruby의 sort_by는 sort와는 다릅니다. 먼저 배열을 정렬 할 값 목록을 생성 한 다음 정렬합니다. 우리가 정렬하는 속성을 찾는 것이 비싸면 빠르며, 다른 모든 경우에는 다소 느립니다. 코드 골프에서도 유용합니다. : P


나는 그것을 속임수라고 부르지는 않지만 deck[0..51]언어의 기능을 사용하여 "변수 없음"규칙을 어느 정도 적용하지 않습니다. 공평하다, 나는 단지 그것이 도전의 일부를 잃어버린다고 생각한다. :) 나는 루비를 모른다; 그 (0..51).map{deck.delete_at(rand deck.length)}부분 을 설명 할 수 있습니까? 그 카드를 삭제합니까 deck?
저스틴 모건

@JustinMorgan 네, 52 번 무작위 카드를 삭제하고 누적 deck되는 내부 결과 목록에 추가합니다 map. 그런 다음에 남아 아무것도 없을 때 결과에 복사됩니다 . 기본적으로 임시가 있지만 명시 적 변수가 아닌 언어 기능입니다. :)deckmapdeck
호브

deck.sort_by!{rand}더 짧습니다.
Eric Duminil

1

자바 스크립트

참고 :이 솔루션 은를 i호출 할 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] << " ";
}

요소를 서로 바꾸지 않기 때문에 무작위로 두 번 호출해야합니다.


swap(deck[rand(1, 51)], (deck[0] - 51) / 100);swap두 번째 가치를 어디에 두어야하는지 어떻게 알 수 있습니까? 당신은 또한 누락되었습니다 ).
저스틴 모건

죄송합니다. 나는 수정하는 동안 그 부분을 옮기기 시작했고 그것을 끝내기 전에주의가 산만 해졌다. : P
Matthew 읽기

Downvote는 나에게서 온 것이 아닙니다, BTW. 할 수있을 때 테스트하겠습니다.
저스틴 모건

확인. 전체 프로그램을 제공하여 테스트하기가 더 쉬워졌습니다.
Matthew 읽기

1
매우 영리한. 내 자신의 솔루션을 사용 deck[0]했지만 귀하의 방식대로하지 않았습니다.
저스틴 모건

1

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

1

실제로 균일하게 분산 된 출력을 생성하는 또 다른 Perl 솔루션 :

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

say join " ", shuffle_integers 1 .. 52;

이 솔루션은 Perl 's을 사용 하여 0 ≤ 범위 rand의 난수 x 를 반환합니다. x <1 . 입력의 각 정수에 이러한 난수를 더하고 소수 부분에 따라 숫자를 정렬하고 마지막으로 소수 부분을 다시 제거합니다. .

(필자는 특별한 변수의 사용을 믿고 $_, $a그리고 $b사람들은 펄에 입력을 전달하는 방법이기 때문에, 도전의 정신 내에map 하고 sort, 그들이 코드의 다른 목적으로 사용되지 것입니다. 어떤 경우에는, 내가 믿는 . 그들은 이것은 실제로 현재 위치에서 셔플 아니지만 실제로 입력 값이 아닌 독립적 인 복사본 별칭있어, 모두 mapsort스택의 입력의 복사본을 만들).


1

자바

아무도 명백한 것을 말한 것에 놀랐습니다. (스왑 (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));
    }

좋습니다. 짧아 질 수 있습니다.

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

우리는 진정한 임의성이 필요하기 때문에 Burlesque는 I / O 기능이 없기 때문에 Burlesque가 할 수없는 일이 있습니다. STDIN을 통해 임의의 소스를 제공해야합니다.

그것은 아마도 나중 버전에서 고칠 것입니다 (즉, 시작시 임의의 시드를 생성하여 보조 스택 또는 이와 유사한 것으로 푸시하지만 Burlesque Interpreter 자체에는 I / O가 없습니다).


0

자바 스크립트

그것이 "속임수"인지 확실하지 않지만 내 솔루션은 함수 인수의 기본 로컬 배열을 사용합니다. 나는 내 자체 제작 기능을 포함 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();

내 생각 엔 바람 피우고있다. 그러나 그것은 매우 영리한 속임수입니다.
Justin Morgan

0

Tcl , 32 바이트

남용 time어떤 변수를 선언하지 않고 반복되는 메커니즘이 될 수 또한 스크립트가 실행 보냈지 만 어느 정도의 시간을 측정하는 역할을 기능.

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

온라인으로 사용해보십시오!


이것이 52 개의 무작위 스왑 만 수행한다는 것이 맞습니까? 진정한 셔플에는 충분하지 않습니다. 나는 그것을 몇 번 실행했고 여전히 시작 위치에있는 평균 8 장의 카드를 세었다. 를 세었고, 진정한 셔플을 사용할 확률은 약 9x10 ^ -6 입니다.
Justin Morgan

@ 저스틴 모건 : 확률 계산에 대해 더 잘 설명해 주시겠습니까?
sergiol

-1

펄-이것은 주석에 설명 된대로 올바른 셔플이 아닙니다!

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

스왑 등으로 아무것도 사용하지 않았다고 생각합니다. 문제의 일부로 필요한 것입니까?


4
임의의 함수로 정렬하는 것이 임의의 분포를 생성하는 방법이라면 효과가 있습니다. 그러나 그렇지 않습니다. -1
aaaaaaaaaaaa

왜 그렇지 않습니까? 나에게 읽을 링크를 줄 수 있니 ???
sogart

2
결과의 품질은 정렬 알고리즘에 따라 크게 달라 지지만 거의 모든 경우 결과는 등분 포 랜덤 함수와는 거리가 멀습니다. 주제에 관한 기사는 다음과 같습니다. sroucheray.org/blog/2009/11/…
aaaaaaaaaaaa

-1

자바 스크립트 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 . shuffleswap구현 에 맞게 코드를 약간 변경 했지만 여기에 그대로 있습니다. jsfiddle.net/m7km4u6g
Justin Morgan

명확히하기 위해 위의 주석은 새 버전에 적용되며 여전히 무작위는 아닙니다.
저스틴 모건
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.