오늘의 랜덤 골프 # 1 : 배열 섞기


35

시리즈 정보

나는 무작위성이라는 주제를 중심으로 일련의 코드 골프 과제를 진행할 것입니다. 기본적으로 9 홀 골프 코스 가되지만 몇 가지 질문이 있습니다. 일반적인 질문 인 것처럼 도전에 개별적으로 참여할 수 있습니다.

그러나 모든 과제에서 리더 보드를 유지합니다. 이 시리즈는 며칠에 한 번 게시 된 9 가지 이상의 과제를 진행할 예정입니다 (현재). 9 가지 도전 과제모두 참여한 모든 사용자 는 전체 시리즈에서 우승 할 수 있습니다. 전체 점수는 각 챌린지에 대한 최단 제출의 합계입니다 (따라서 챌린지에 두 번 답변하면 더 나은 답변 만 점수에 포함됩니다). 누군가이 28 일 동안 이 전체 순위표에서 1 위를 차지하면 500 명의 보상금을 받게됩니다 .

시리즈에 대한 아이디어가 많이 있지만 미래의 과제는 아직 해결되지 않았습니다. 제안 사항이 있으면 관련 샌드 박스 게시물에 알려주십시오 .

1 번 홀 : 배열 섞기

첫 번째 작업은 매우 간단합니다. 비어 있지 않은 정수 배열이 있으면 무작위로 섞습니다. 그래도 몇 가지 규칙이 있습니다.

  • 가능한 모든 순열은 같은 확률로 반환되어야합니다 (따라서 셔플은 균일 한 분포를 가져야합니다). 편견 의 행렬을 생성하는 Will it Shuffle 에서 JavaScript로 알고리즘을 구현하여 알고리즘이 균일 / 비 편향인지 확인할 수 있습니다 . 결과는 바이어스의 매트릭스를 생성합니다. 결과는 내장 된 Fisher-Yates 또는 정렬 (임의 순서) 처럼 균일해야합니다 .
  • 내장 또는 타사 방법을 사용하여 배열을 섞거나 임의 순열을 생성하거나 모든 순열을 열거해서는 안됩니다. 특히, 사용할 수 있는 유일한 내장 임의 함수는 한 번에 하나의 난수를 얻는 것 입니다. 내장 난수 방법이 O (1)에서 실행되고 요청 된 간격 동안 완벽하게 균일하다고 가정 할 수 있습니다 (수학적 의미에서 부동 소수점 표현의 세부 사항은 여기에서 무시할 수 있음). 귀하의 언어로 m 개의 난수 목록을 한 번에 얻을 수있는 경우, m 수가 서로 독립적이며 O (m)으로 계산하면 이 기능을 사용할 수 있습니다 .
  • 구현은 시간 복잡도 O (N)을 초과해서는 안됩니다 . 여기서 N 은 셔플 할 배열의 크기입니다. 예를 들어 "임의의 숫자로 정렬"할 수 없습니다.
  • 배열을 순서대로 섞거나 새 배열을 만들 수 있습니다 (이 경우 이전 배열은 원하는대로 수정할 수 있음).

전체 프로그램 또는 함수를 작성하고 STDIN, 명령 행 인수, 함수 인수 또는 프롬프트를 통해 입력을 받고 리턴 값을 통해 또는 STDOUT (또는 가장 가까운 대안)으로 인쇄하여 출력을 생성 할 수 있습니다. 배열을 셔플하는 함수를 작성하는 경우 물론 반환 할 필요가 없습니다 (제공된 언어는 함수가 반환 된 후 수정 된 배열에 액세스 할 수있는 경우).

입력 및 출력은 편리한 목록 또는 문자열 형식 일 수 있지만 -2 31 ≤ x <2 31 범위의 임의의 정수를 지원해야합니다 . 원칙적으로 코드는 최대 길이가 2 31 인 배열에서 작동해야 하지만 반드시 메모리에 맞지 않거나 합리적인 시간 내에 완료해야 할 필요는 없습니다. (단지 루프 또는 다른 코드에 대한 임의의 크기 제한을보고 싶지 않습니다.)

이것은 코드 골프이므로 가장 짧은 제출 (바이트)이 이깁니다.

리더 보드

다음 스 니펫은 시리즈의 모든 과제에서 리더 보드를 생성합니다.

답변이 표시되도록하려면 다음 마크 다운 템플릿을 사용하여 모든 답변을 헤드 라인으로 시작하십시오.

# Language Name, N bytes

N제출물의 크기는 어디에 있습니까 ? 당신이 당신의 점수를 향상시킬 경우에, 당신은 할 수 있습니다 를 통해 눈에 띄는에 의해, 헤드 라인에 오래된 점수를 유지한다. 예를 들어 :

# Ruby, <s>104</s> <s>101</s> 96 bytes

(언어는 현재 표시되어 있지 않지만 스 니펫은이를 요구하고 구문 분석하며 향후 언어 별 리더 보드를 추가 할 수 있습니다.)


7
나는 우리가 "영리한"수 없으며 " 임의의 숫자를 얻는 것"이외의 라이브러리 함수를 사용하는 것이 실망 스럽다 . Fisher-Yates 셔플 링의 또 다른 69 구현을 살펴보고 싶습니까? 향후 작업에서이 규칙을 제거하십시오. 또한 시간 복잡성에 한계가있는 이유는 무엇입니까? 적어도 O (n ^ 2)까지 이완하는 것을 고려하십시오. 또한 O (n!)를 허용하면 누군가가 특히 골프 구현을 찾을 수 있다고 생각합니다.
anatolyg 2019

7
@anatolyg 제한을 제거하면 모든 답변이 sortby(random)(시간 제한의 이유) 또는 단순히 .shuffle()(내장 제한의 이유)이며, Fisher-Yates 또는 기타를 구현 해야하는 것보다 훨씬 덜 영리하다고 생각합니다. 접근.
Martin Ender 2019

1
셔플 링하는 경우 함수가 배열 을 반환 해야합니까, 아니면 수정하기에 충분합니까? shuffle(array)대신에 함수를 작성할 수 있습니까 newArray=shuffle(array)?
Geobits

1
@Bakuriu 숫자가 고정 된 경우 선형 시간으로 정렬 할 수 있다고 주장하는 것은 입력 크기가 고정 된 경우 O (1)에서 아무것도 할 수 있다고 주장하는 것과 약간 같습니다. 또한 관련 크기는 고정 크기 정수가 아닌 고정 크기 배열입니다. 배열 크기에 따라 난수가 얼마나 큰지 결정되기 때문입니다. 어쨌든 시간 복잡성에 대한 제한은 물론 구현하는 일반적인 알고리즘에 대한 것입니다. 반면 입력 크기에 대한 제한이 있으므로 언어가 상자에서 즉시 사용하지 않는 경우 임의의 정밀도 정수를 사용할 필요가 없습니다. .
Martin Ender

2
Adám의 솔루션이 실제로 14 인 경우 왜 43319 바이트로 표시됩니까?
boboquack가 14:17

답변:


20

Dyalog APL, 25 24 바이트

25 자 솔루션 우선 : i{⊃a[⍺⍵]←a[⍵⍺]}¨?i←⌽⍳⍴a←⎕

                      a←⎕ ⍝ evaluated input, assign to "a"
                     ⍴a   ⍝ length
                    ⍳⍴a   ⍝ 1 2 .. length
                   ⌽⍳⍴a   ⍝ length .. 2 1
                 i←       ⍝ assign to "i"
                ?i        ⍝ random choices: (1..length)(1..length-1)..(1 2)(1)
i{            }¨?i        ⍝ for each index ⍺ and corresponding random choice ⍵
   a[⍺⍵]←a[⍵⍺]            ⍝ swap a[⍺] and a[⍵]
        ←                 ⍝ in Dyalog, assignment returns its right-hand side
  ⊃                       ⍝ first element, i.e. a[⍵]
                          ⍝ the result from {} is an array of all those a[⍵]

위의 일부 등가 변환 후 :

i {}¨ ?i  ←→  i {}¨∘? i   ⍝ because A f∘g B ←→ A f g B
          ←→  {}¨∘?⍨ i    ⍝ because f⍨ B ←→ B f B

과제를 없애고 i←캐릭터를 저장할 수 있습니다 .

{⊃a[⍺⍵]←a[⍵⍺]}¨∘?⍨⌽⍳⍴a←⎕


3
... 마음. 부푼.
danwyand

1
오른쪽에서 왼쪽으로 읽어야하는 언어 ?? 와우!
Luminous

5
종종 수학 표기법의 경우와 같이 @Luminous : 죄 왜냐하면 LN SQRT X
NGN

4
@ngn 당신이 그렇게하면 내 이전 의견을 웃게 보이게합니다. 하아.
Luminous

5
@ronalchn 같은 APL 8 비트 인코딩이 있습니다 하나 다른 하나는, 내가 들어 본 Dyalog 유니 코드에 대한 대안으로,이 중 하나를 사용합니다.
anatolyg

12

80386 머신 코드, 44 24 바이트

코드의 16 진 덤프 :

60 8b fa 0f c7 f0 33 d2 f7 f1 49 8b 04 8f 87 04
97 89 04 8f 75 ed 61 c3

rdrand지침 사용을 제안한 FUZxxl에게 감사합니다 .

소스 코드는 다음과 같습니다 (Visual Studio에서 컴파일 할 수 있음).

__declspec(naked) void __fastcall shuffle(unsigned size, int array[])
{
    // fastcall convention:
    // ecx = size
    // edx = array
    _asm
    {
        pushad;             // save registers
        mov edi, edx;       // edi now points to the array

    myloop:
        rdrand eax;         // get a random number
        xor edx, edx;
        div ecx;            // edx = random index in the array

        dec ecx;            // count down
        mov eax, [edi + 4 * ecx];   // swap elements
        xchg eax, [edi + 4 * edx];  // swap elements
        mov [edi + 4 * ecx], eax;   // swap elements
        jnz myloop;

        popad;              // restore registers
        ret;
    }
}

또 다른 Fisher-Yates 구현. 골프의 대부분은 레지스터에 매개 변수를 전달하여 달성되었습니다.


1
rdrand똥과 낄낄 거림 에도 사용할 수 있습니다 .
FUZxxl

@ FUZxxl 나는 그것에 대해 완전히 잊었다!
안타깝게도

9

자바, 88 (101)

기본적인 Fisher-Yates 셔플이 트릭을 수행합니다. 빠르고 쉽게 구현할 수 있기 때문에 여기에서 일반적으로 사용되는 느낌이 듭니다. 여기 주입식 일부 루프 / 과제가있다,하지만 정직이 아니라 너무 골프에 많은; 본질적으로 짧습니다.

void t(int[]s){for(int i=s.length,t,x;i>0;t=s[x*=Math.random()],s[x]=s[i],s[i]=t)x=i--;}

줄 바꿈과 함께 :

void t(int[]s){
    for(int i=s.length,t,x;
        i>0;
        t=s[x*=Math.random()],
        s[x]=s[i],
        s[i]=t
    )
        x=i--;
}

원래 배열을 수정하여 섞습니다 s[]. 테스트 프로그램 :

public class Shuffle {
    public static void main(String[] args) {
        int[] a = {1,2,3,4,5,6,7,8,9};
        new Shuffle().t(a);
        for(int b:a)
            System.out.print(b+" ");
    }
    void t(int[]s){for(int i=s.length,t,x;i>0;t=s[x*=Math.random()],s[x]=s[i],s[i]=t)x=i--;}
}

1
아니요, 도전 과제에 따르면 " 요청한 범위에서 완벽하게 균일 "하다고 가정 할 수 있습니다 . 요청 된 범위의 Math.random()크기는 2의 거듭 제곱이므로 사양을 충족하지 않습니다.
피터 테일러

1
@PeterTaylor Jan과 Geobits의 해석은 실제로 규칙을 의도 한 방식으로 PRNG의 실제주기 길이에 대해 걱정할 필요 가 없습니다 .
Martin Ender 2019

1
@ MartinBüttner 사이클 길이는 여기서 문제가되지 않습니다-그것은 규칙에 의해 커버됩니다. 수레의 조잡함입니다.
John Dvorak

3
@TheBestOne 현재 게시 된 유일한 파이썬 솔루션보다 1 바이트 습니다.)
Geobits

1
더 이상은 아닙니다! : D
Sp3000

8

파이썬 2, 86 바이트

from random import*
def S(L):i=len(L);exec"i-=1;j=randint(0,i);L[i],L[j]=L[j],L[i];"*i

이것은 Fisher-Yates shuffle 의 간단한 구현을 사용하여 배열을 반환하지 않고 제자리에 섞는 기능입니다 . 파이썬에서 난수를 얻는 것은 비싸다 ...

팁을주는 @xnor와 @colevk에게 감사합니다.


그 범위 표현은 꽤 번거로워 보입니다. 수동으로 카운트 다운하는 것이 더 짧 while i:i-=1;...습니까?
xnor

@ xnor 그래, 고마워. 나는 그것이 이런 종류의 것 while보다 짧아지는 경향이 있다는 것을 계속 잊어 for
버린다

1
Awww ... 이제 Java 답변이 이것을 치고 있지 않습니다. 나는 아주 짧은 시간 동안 아주 행복했습니다 :(
Geobits

i=len(L)while 루프의 시작 부분에 감소를 만들어서 2 바이트를 더 절약 할 수 있습니다 .
colevk

8

J, 45 44 자

이것은 까다로운 일이었습니다.

<@({.,?@#@}.({,<^:3@[{])}.)&>/@(<"0@i.@#,<)

여기에 설명이 있습니다 :

  1. # y다음 탈리y인, 요소의 수 y.
  2. ?@# y:에서 1까지 의 범위에 균일하게 분포 된 난수 (#y)-1입니다.
  3. x { y: at 의 항목 입니다 .yx
  4. (<<<x) { y:의 색인 x에 있는 항목을 제외한 모든 항목 y.
  5. x , y: y 추가x.
  6. x ({ , <^:3@[ { ]) y:의 색인 x에 있는 항목 y과 다른 모든 항목.
  7. (?@# ({ , <^:3@[ { ]) ]) y에서 무작위로 y선택한 다음 다른 모든 항목 에서 무작위로 추출합니다 .
  8. x {. y: 에서 가져온 첫 번째 x항목 .y
  9. x }. y: 첫 번째 x항목은 떨어졌다 에서 y.
  10. x ({. , }.) y: 첫 번째 x항목 촬영 에서는 y, 다음 첫 번째 x항목은 떨어졌다 에서y
  11. x ({. , (?@# ({ , <^:3@[ { ]) ])@}.) y: 에서 가져온 첫 번째 x항목 , 그런 다음 첫 번째 항목은 7 번과 같이 처리됩니다.yxy
  12. x ({. , ?@#@}. ({ , <^:3@[ { ]) }.) y: 한 글자를 저장하기 위해 끌어다 놓은 것과 같은 것 .
  13. u/ y: 의 항목 사이에 u 삽입되었습니다y .
  14. < y: y 박스 .
  15. <"0 y: y 박스의 각 항목 .
  16. i. y: 에서 까지의 정수 .0y - 1
  17. i.@# y: 에서 까지의 정수 .0(#y) - 1
  18. (<"0@i.@# , <) y:에서 정수 0(#y) - 1각각 박스 다음 y하나의 상자에 입력하십시오. J의 배열이 균일하기 때문에 필요합니다. 상자는 내용의 모양을 숨 깁니다.
  19. x u&v y: 좋아 (v x) u (v y).
  20. > y: y 열린 , 즉 상자가 없습니다.
  21. x ({. , ?@#@}. ({ , <^:3@[ { ]) }.)&> y 박스의 인수에 적용되는 12 번의 문구.
  22. ({. , ?@#@}. ({ , <^:3@[ { ]) }.)&>/ y의 항목들 사이에 삽입 된 21 번 문구 y.
  23. ({. , ?@#@}. ({ , <^:3@[ { ]) }.)&>/@(<"0@i.@# , <) y숫자 18의 문구의 결과에 적용되는 숫자 22의 문구, 또는의 항목의 균일 한 순열 y.

1
모든 괄호를 구별 할 수는 없습니다. 그리고 그 트리플 복싱 <@<@<@[도 수수께끼입니다 ... 설명을 기다리고 있습니다. :)
randomra 2019

2
이것은 설명 도착하면,이 대답 ;-) upvote에 훨씬 더 가능성이있을 수도 있습니다
존 드보락

@randomra 여기 있습니다.
FUZxxl

@JanDvorak 설명이 만족 스럽습니까?
FUZxxl

좋은 설명! from( {) 의 모든 박스 사용에 대해 몰랐습니다 . 그리고 나는 &>/목록을 조작하는 트릭을 정말로 좋아합니다 . 나는 그것을 몇 번 전에 그것을 사용할 수 있었다고 확신한다.
randomra

5

Pyth, 25 바이트

여기에서 테스트하십시오.

또 다른 Fisher-Yates 구현. pyth에서 @ Sp3000 python 솔루션과 본질적으로 동일합니다.

FNrlQ1KONJ@QN XXQN@QKKJ)Q

스와핑 트릭을위한 @Jakube에게 감사합니다

<implicit>    Q=input()
FNrlQ1        For N in len(Q) to 1, only goes len Q-1 because how range implemented in pyth
 KON          K = random int 0-N
 J@QN         J=Q[N]
 <space>      Suppress print
 XXQN@QKKJ    Swap K and J
)             End for
Q             Print Q

XQN @ QK XQKJ 대신 XXQN @ QKKJ와 같은 두 가지 목록 할당을 결합하여 2 바이트를 절약 할 수 있습니다.
Jakube

팁을 주셔서 감사합니다. 나는 목록에서 값을 바꿀 수있는 방법이 있어야한다는 것을 알고 있었고 이것이 현명합니다. 팁 목록에 추가해야합니다.
Maltysen

4

펄, 68 56 44

다른 많은 솔루션과 마찬가지로 Fisher-Yates 알고리즘을 사용합니다 .

nutki 의 주석을 사용하여 12 개의 문자가 배열 인덱스 $_대신 $i작업을 수행하고 대신 사용하여 저장됩니다 .

44 :

sub f{@_[$_,$j]=@_[$j=rand$_,--$_]for 1..@_}

56 :

sub f{$i=@_;$j=int(rand$i),@_[$i,$j]=@_[$j,$i]while$i--}

이것이 나의 첫 번째 코드 골프입니다.


나쁜 시작은 아니지만, 당신이 그런 @_[...]rvalue로 사용할 수 있다는 것을 몰랐습니다 . 로 더 골프를 칠 수 있습니다 sub f{@_[$_,$j]=@_[$j=rand$_,--$_]for 1..@_}.
nutki

3

C, 63 61 60 바이트

i,t;s(a,m)int*a;{for(;m;a[m]=t)t=a[i=rand()%m--],a[i]=a[m];}

주어진 배열을 정렬하는 Fischer-Yates의 간단한 구현입니다. Visual Studio 컴파일러 (vs2013, 다른 버전은 테스트하지 않음) 및 Intel Compiler와 완벽하게 컴파일 및 연결됩니다. 멋진 찾고 기능 서명입니다 s(int array[], int length). 나는 파이썬과 루비를 이길 정당한 인상을 받았습니다.

이것은 srand()호출되고 rand ()가 올바르게 구현 되었다고 가정 하지만이 규칙에 따라 가능합니다.

You may assume that any built-in random number method runs in O(1) and is perfectly uniform over the requested interval

멋진 형식의 버전 :

index, temp;
shuffle(array, length) int* array;  {
    for(;length; array[index] = temp)
        index = rand() % length--,
        temp = array[length],
        array[length] = array[index];
}

나는 header 함수를 작성하면 충분하다고 생각 s(a,m)*a{하지만 확실하지 않으며 테스트하고 싶지 않습니다. xor에서와 같이 -swap 을 수행 할 수 있습니다 a[i]^=a[m]^=a[i]^=a[m]. 또한 선언 할 필요가 없습니다 t.
FUZxxl

@FUZxxl xor 스왑이 문제가 발생한다고 생각합니다 i==m.
Geobits

실제로 @Geobits. 나는 그 가능성을 놓쳤다.
FUZxxl

나는 왜 그것이 작동하지 않는지 알아 내려고 노력 중이었습니다 ... 기억해야합니다. 또한 s(a,m)int*aVisual Studio 및 인텔 컴파일러 가 필요 합니다. 테스트를 위해 gcc 또는 clang을 설치하지 않았지만 불만을 제기한다고 가정합니다.
pseudonym117

이것은 꽤 인상적인 골프입니다. 아무것도 저장하지 않은 많은 수정을 시도한 후 2 문자를 저장하는 방법을 보았습니다. 첫 번째 스왑 문이로 바뀌도록 스왑 순서를 변경하면 명령문을 배열 인덱스로 내부로 t=a[i]이동할 수 있습니다 i=rand()%m--.
Runer112

3

옥타브, 88 77 바이트

function s=r(s)for(i=length(s):-1:1)t=s(x=randi(i));s(x)=s(i);s(i)=t;end;end

또 다른 Fisher-Yates 구현 ... 일반적인 줄 반환과 간격을 추가하면 매우 간단해야합니다.

function s=r(s)
  for(i=length(s):-1:1) # Counting down from i to 1
    t=s(x=randi(i));    # randi is builtin number generator for an int from 0 to i
    s(x)=s(i);
    s(i)=t;
  end
end

"end"키워드는 불행히도 여기서 골프 점수를 죽입니다. "endfor"와 "endfunction"대신 "end"를 사용할 수 있습니다!


1
참고로, "바이트"는 코드에서 실제로 필요하지 않습니다. 되어 다음 쉼표 뒤에 쉼표 (언어를 분리하기 위해) 적어도 하나 개의 숫자를 포함하고, 헤드 라인, 그냥 마지막 선택 넘어지지 않은 숫자. 그래도 "바이트"를 가지고있는 것은 여전히 ​​좋은 일입니다. ;)
Martin Ender 2019

1
numel대신 에 사용하여 1 바이트를 절약 할 수 있습니다lenght 있습니다. 보너스로 프로그램은 2 차원 배열 (일명 행렬)에서도 작동합니다.)
paul.oderso

2

자바 8, 77

(x)->{for(int i=x.length,j,t;;t=x[j*=Math.random()],x[j]=x[i],x[i]=t)j=i--;};

int[]void를 가져 오고 돌려주는 람다 입니다. 나의 첫 번째 시도는 그리 재미 있지 않은 것처럼 보였으므로 예외를 던져서 종료하기로 결정했습니다.

테스트 프로그램 :

interface shuff {
    void shuff(int[] x);
}
class Ideone
{
    public static void main (String[] args) throws java.lang.Exception
    {
        shuff s = (x)->{for(int i=x.length,j,t;;t=x[j*=Math.random()],x[j]=x[i],x[i]=t)j=i--;};
        int[] x = {3, 9, 2, 93, 32, 39, 4, 5, 5, 5, 6, 0};
        try {
            s.shuff(x);
        } catch(ArrayIndexOutOfBoundsException _) {}
        for(int a:x) System.out.println(a);
    }
}

1
람다를 어디에서나 사용하기 위해 대리자를 제공해야 할 때 함수 서명을 작성해야 할 때 람다를 사용하는 것이 부정적이지 않습니까? 또한 ... 괄호를 묶을 수 Math.random()없습니까?
롤링

1
@Rawling 이 메타 질문에 투표 할 수 있습니다. 현재 람다에 찬성하여 9 표, 반대에 대해서는 0 표가 있습니다. 괄호를 제거 할 수 있습니다.
feersum

허, 메타 포스트와 지금까지 합의 된 내용이 있다면 해고하십시오. (그리고 나에 대한 두 개의 낮은 골프 점수를 즐기십시오 : p)
Rawling

3
나는 정상적인 경우에 예외적으로 기능이 멈추는 것이 불공평하다고 생각합니까?
Qwertiy

1
@Qwertiy 각자 자신에게 ... 당신은 그것이 불공평하다고 생각합니다.
feersum

2

골프 루아, 37

Golflua를 실행하는 방법?

~@i=1,#X`r=M.r(i)X[i],X[r]=X[r],X[i]$

입력은 변수 X에 테이블로 제공됩니다. 테이블이 섞입니다.

사용법 예 :

> X={0,-45,8,11,2}
> ~@i=1,#X`r=M.r(i)X[i],X[r]=X[r],X[i]$
> w(T.u(X))
-45 0 8 11 2

2

R, 79 바이트

f=function(x){n=length(x);for(i in 1:n){j=sample(i:n,1);x[c(i,j)]=x[c(j,i)]};x}

이것은 Fisher-Yates 셔플의 간단한 구현입니다. R 함수 sample는 동일한 확률로 주어진 벡터에서 주어진 크기의 간단한 랜덤 샘플을 그립니다. 여기에서는 정수 i, ..., 에서 반복 할 때마다 크기가 1 인 임의의 샘플을 그 n립니다. 질문에서 언급했듯이 이것은 O (1)로 가정 할 수 있으므로이 모든 구현에서 O (N)이어야합니다.


2

MATLAB, 67

Fisher-Yates도 구현합니다.

a=input('');n=numel(a);for i=1:n;k=randi(i);a([i,k])=a([k,i]);end;a

Matlab의 randperm기능을 사용할 수 없다고 생각했습니다 . 그러나 주변을 둘러 본 후 나는 randperm그것이 어떻게 수행되는지 볼 수 있는 출처 를 볼 수 있다고 생각했으며 한 줄만 있음을보고 놀랐습니다 : [~,p] = sort(rand(1,n))=)


2

펄, 44

sub f{($_[$x],$_)=($_,$_[$x=rand++$i])for@_}

44 자로 된 또 다른 펄. 사용 예 :

@x=(1..9);f(@x);print@x

2

Mathematica, 82 90 83 93 바이트

참고 : Fisher-Yates 셔플의 이러한 변형은 실제로 Martin Büttner의 솔루션이며 alephalpha의 일부 코드 구문 분석입니다. s입력 배열입니다. 공상적인 솜씨는 없지만 때로는 단순한 것들이 가장 애매합니다.

f@s_:=(a=s;m=Length@a;Do[t=a[[r=RandomInteger@{1,m-1}]];a[[r]]=a[[m]]; a[[m]]=t,{n,1,m-1}];a)

Do여기서 사용할 수 있습니다 . 보다 짧습니다 While.
alephalpha

2

루비, 57 바이트

->a{a.size.times{|i|j=rand(i+1);a[i],a[j]=a[j],a[i]};p a}

입력 (람다 함수) :

f.([1,2,3,4,5])

산출:

[2, 1, 4, 3, 5]


2

K, 31 자

f:{{l[i:x,1?x]:l@|i}'|!#l::x;l}

내가 전에 입었던 것만큼이나 짧지 않다.

기본적인 Fisher-Yates 셔플입니다. 이것은 Kona 메일 링리스트의 많은 도움으로 만들어졌습니다 .


2

자바 스크립트 (ES6), 66

이 기능은 어레이를 제자리에 섞습니다. 또한 셔플 된 출력이 아니고 고려해서는 안되는 부산물 배열을 반환합니다.

F=a=>a.map((v,i)=>a[a[i]=a[j=0|i+Math.random()*(a.length-i)],j]=v)

2

MATL , 16 바이트

XH`HnYr&)XHxvHHn

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

MATL의 Fisher-Yates. 이 프로그램의 거의 3 분의 1이 HMATL의 클립 보드 기능에 해당하는 문자 에 사용됩니다.

기본적으로 H스택은 셔플 목록을 추적하면서 입력에서 사용하지 않는 항목을 저장합니다.


2

apt, 12

rÈiMqZÄ Y}[]

시도 해봐!

@Shaggy 덕분에 -10 (약 절반;)!

나는 골프 언어를 시험 해보고 싶었고 Japt 통역사는 훌륭한 문서와 브라우저에서 물건을 시험해 볼 수있는 방법을 가지고있었습니다.

아래는 내가 취한 전략입니다.

  • 빈 배열로 입력 시딩 감소
  • 각 단계에서 현재 요소를 삽입 할 임의의 슬롯을 찾으십시오.

1
Japt에 오신 것을 환영합니다. 나는 이것이 같은 방법을 사용하여 9 바이트에서 작동 한다고 생각 합니다 . RNG가 만족스럽지 않으면 대신 시도 하십시오 .
얽히고 설킨

@Shaggy-팁 주셔서 감사합니다! :) 두 번째 솔루션의 약간 수정 된 버전을 사용했습니다. reduce 함수의 3 번째 파라미터는 인덱스이므로 길이를 이미 알고 있습니다.
다나

1

자바 스크립트 ES6, 69

a=>{m=a.length;while(m)[a[m],a[i]]=[a[i=~~(Math.random()*m--)],a[m]]}

Fisher-Yates입니다.

PS : Firefox에서 테스트 가능


@ MartinBüttner, 그것을 제거 :)
Qwertiy


1

하스켈, 170

import System.Random
import Data.Array.IO
s a=do(_,n)<-getBounds a;sequence$map(\i->do j<-randomRIO(i,n);p<-a%i;q<-a%j;writeArray a j p;return q)[1..n]where(%)=readArray

https://wiki.haskell.org/Random_shuffle 의 알고리즘에서 영감을 얻은 또 다른 Fisher-Yates 솔루션 .

s 서명이있는 함수입니다. IOArray Int a -> IO [a]


1

CJam-30

q~_,,W%{_I=I)mr:J2$=@I@tJ@t}fI

http://cjam.aditsu.net/ 에서 시도 하십시오

입력 예 : [10 20 30 40 50]
출력 예 : 3020401050( p예쁜 인쇄를 위해 코드 끝에 a 를 추가하십시오 )

코드가 함수 에서처럼 스택에서 입력을받을 수 있으면 처음 2자를 제거하여 크기를 28로 줄입니다.

설명:

배열에 대한 "스왑"연산자가 없기 때문에 코드가 예상보다 길다
(나중에 구현 될 것이다 : p).

q~            read and evaluate the input (let's call the array "A")
_,,           make an array [0 1 2 ... N-1] where N is the size of A
W%            reverse the array, obtaining [N-1 ... 2 1 0]
{…}fI         for I in this array
    _I=       push A[I]
    I)mr:J    push a random number from 0 to I (inclusive) and store it in J
              stack: A, A[I], J
    2$=       get A[J]
    @I@t      set A[I] = A[J]
              stack: former A[I], A
    J@t       set A[J] = former A[I]

의견에서 언급했듯이 이것이 잘못되었음을 두려워합니다. 최소한 _O (N) (O (N) 루프 내부)입니다. 불행히도 CJam에서는 그 문제를 해결할 방법이 없습니다.
마틴 엔더

리스트는 변경 불가능한 객체처럼 처리되므로 중복은 참조를 복제하는 것처럼 구현됩니다. 실제로 t목록을 변경하지 못하고 복사본을 만들어야하므로 실제로는 죽입니다.
Runer112

@ MartinBüttner 나는 Runer112와 같은 것을 게시하려고했습니다. 예,에 문제가있을 수 있습니다. t향후 버전에서 개선하고 싶습니다 ..
aditsu

따라서이 코드는 내부 언어 구현 문제로 인해 질문의 정신을 따르지만 "문자"는 아닙니다.
aditsu

1

자바 스크립트 (ES 6), 61

S=a=>(a.map((c,i)=>(a[i]=a[j=Math.random()*++i|0],a[j]=c)),a)

(Firefox 전용) 이라는 행을 추가하여 여기에서 테스트 할 수 있습니다 shuffle = S.


1

스타 타, 161

di _r(s)
set ob wordcount($s)
token $s
g a=0
foreach x in $s{
gl j=floor(runiform()*_n)+1
replace a=`$j' if word($s,_n)=`x'
replace a=`x' if word($s,_n)=`$j'
}
l

공백으로 구분 된 숫자로 입력을 예상합니다. 원하는 경우 출력에서 ​​헤더와 관찰 번호를 제거 할 수 있지만 그렇지 않은 경우 더 짧습니다.


이게 뭐야 _n?
Martin Ender 2019

_n은 현재 관측치의 수입니다.
bmarks


1

SQF, 91 바이트

params["i"];{n=floor random count i;i set[_forEachIndex,i select n];i set[n,_x]}forEach i;i

1
이것은 편향되어 있지만 (Will It Shuffle의 "스왑 (i <-> 임의)"참조) 대신로 바꾸어 Fisher-Yates (편견이없는)로 바꿀 수 %x있습니다 %i.
Martin Ender

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.