파로는 배열을 섞는다


31

파로 셔플은 자주 "셔플"갑판에 마술사가 사용하는 기술입니다. 파로 셔플을 수행하려면 먼저 데크를 2 등반으로 자른 다음 2 반부를 인터리브하십시오. 예를 들어

[1 2 3 4 5 6 7 8]

파로가 섞여있다

[1 5 2 6 3 7 4 8]

이것은 여러 번 반복 될 수 있습니다. 흥미롭게도, 이것을 충분히 반복하면 항상 원래 배열로 돌아갑니다. 예를 들면 다음과 같습니다.

[1 2 3 4 5 6 7 8]
[1 5 2 6 3 7 4 8]
[1 3 5 7 2 4 6 8]
[1 2 3 4 5 6 7 8]

1은 맨 아래에, 8은 맨 위에 있습니다. 이것은 이것을 외부 셔플로 만듭니다. 이것은 중요한 차이점입니다.

도전

정수 A 의 배열 과 숫자 N이 주어지면 N Faro shuffles 후에 배열을 출력하십시오 . A 는 반복적이거나 부정적인 요소를 포함 할 수 있지만 항상 짝수의 요소를 갖습니다. 배열이 비어 있지 않다고 가정 할 수 있습니다. N 이 음수가 아닌 정수 라고 가정 할 수도 있지만, 0 일 수도 있습니다. 이러한 입력을 합리적인 방식으로 취할 수 있습니다. 바이트 단위의 최단 답변이 승리합니다!

IO 테스트 :

#N, A,                                              Output
1,  [1, 2, 3, 4, 5, 6, 7, 8]                        [1, 5, 2, 6, 3, 7, 4, 8]
2,  [1, 2, 3, 4, 5, 6, 7, 8]                        [1, 3, 5, 7, 2, 4, 6, 8]
7,  [-23, -37, 52, 0, -6, -7, -8, 89]               [-23, -6, -37, -7, 52, -8, 0, 89]
0,  [4, 8, 15, 16, 23, 42]                          [4, 8, 15, 16, 23, 42]
11, [10, 11, 8, 15, 13, 13, 19, 3, 7, 3, 15, 19]    [10, 19, 11, 3, 8, 7, 15, 3, 13, 15, 13, 19]

그리고 대규모 테스트 사례 :

23, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100]

출력해야합니다 :

[1, 30, 59, 88, 18, 47, 76, 6, 35, 64, 93, 23, 52, 81, 11, 40, 69, 98, 28, 57, 86, 16, 45, 74, 4, 33, 62, 91, 21, 50, 79, 9, 38, 67, 96, 26, 55, 84, 14, 43, 72, 2, 31, 60, 89, 19, 48, 77, 7, 36, 65, 94, 24, 53, 82, 12, 41, 70, 99, 29, 58, 87, 17, 46, 75, 5, 34, 63, 92, 22, 51, 80, 10, 39, 68, 97, 27, 56, 85, 15, 44, 73, 3, 32, 61, 90, 20, 49, 78, 8, 37, 66, 95, 25, 54, 83, 13, 42, 71, 100]  

배열에 0 개의 요소가 포함될 수 있습니까?
Leaky Nun

@LeakyNun 우리는 아니오라고 말할 것입니다. 제로 요소를 처리 할 필요가 없습니다.
DJMcMayhem



1
유한 세트의 순열은 충분한 시간이 반복되면 시작 위치로 돌아갑니다. 이것은 파로 셔플에 특별하지 않습니다.
Greg Martin

답변:



19

정력, 62 59 54

qrma50%mb:norm@q<cr>ggqOjdd'apjma'b@q<esc>0"qDJ<C-a>D@"i@r<esc>xxdd@"

와우. 이것은 아마도 내가 PPCG를 위해 작성한 가장 해로운 일일 것입니다.

입력은 첫 번째 줄에서 N으로, 그 다음에는 각각 자체 줄에서 배열의 요소가 취해집니다.

qr         first, we're going to record the contents of the @r macro. this is
             the macro which does the faro-shuffle operation.
  ma       set the mark 'a at the beginning of the file
  50%      move to the 50% point of the file (i.e. halfway down)
  mb       set another mark here
  :norm@q  evaluate the recursive macro @q. we'll get to what that does later,
             but the interesting part here is that it's :norm@q instead of @q.
             this is because a recursive macro terminates at the end of the
             file, which means when @q terminates, @r would also abort, which
             would make calling it with a count impossible. running @q under
             :norm prevents this.
  gg       move back to the top of the file for the next iteration
q          end recording
O          now we're inserting contents of the @q macro, the recursive part
             we can't record it directly because it's destructive
  j        move to line directly below mark 'b (which was just set before @q)
  dd       delete this line and bring it...
  'ap      up after mark 'a (which starts on line 1, bringing the N/2th line
             directly below line 1, aka line 2)
  jma      replace mark 'a one line below this so that the next time we call
             'ap, the line from the second half is interleaved with the lines
             from the first half
  'b       jump back to mark 'b (remember, 'b is the last line of the first
             half of the file, originally reached via 50%)
  @q       call ourselves, causing the macro to run until hitting EOF
0"qD       delete this into register "q
J          delete the empty line that remains
<C-a>      here's another interesting bit: we want to run @r N times. but 0@r
             means "go to column 0, and then run @r once." so we have to
             increment the input number...
D@"        and then *that* many times...
  i@r        insert @r...
xx         ... and finally, delete two characters, which is the extra @r from
             the increment
dd         delete the sequence of @rs into the "" register...
@"         and run it!

이 답변을 쓰는 ​​동안 실제로 몇 가지 vim 버그를 발견했을 수 있습니다.

  • 다른 매크로 내에서 (텍스트를 사용하지 않고 수동으로 설정할 때 q) 또는 :*maps 내에서 매크로 기록은 불가능합니다 .

  • :let @a='<C-v><cr>'<cr>i<C-r>a 어떤 특별한 이유로 든 하나가 아닌 두 개의 줄 바꿈을 출력합니다.

나중에 더 조사 할 수도 있습니다.

3 바이트의 Green Eggs 박사와 Ham DJ 에게 감사 합니다!


4
이것은 아름답고 끔찍합니다. vim에서 이것을 할만 큼 인내심이 없을 것입니다. :P또한, 당신은 수행하여 2 바이트를 벗을 수있는 "rck대신에 vgg"rc, 당신은 수행하여 다른 5 벗을 수있는 dw@"i@r<esc>대신에AA@R<C-v><esc><esc>0D@"
DJMcMayhem

@DrGreenEggsandHamDJ 첫 줄을 할 수는 없습니다. 왜냐하면 줄 바꿈 줄도 잡았지만 두 번째 최적화는 작동하기 때문입니다. 감사!
Doorknob

7

파이썬 2, 59 바이트

def f(n,L):exec"l=len(L)/2;L=(L+L[1:]*~-l)[::l];"*n;print L

다른 파이썬 답변보다 약간 긴 다른 접근법. 양수의 짝수 요소에만 작동합니다.

예를 들어 1, [1,2,3,4,5,6,7,8], 배열을 가져 와서 len(L)/2-1첫 번째 요소를 뺀 사본을 추가하십시오.

[1,2,3,4,5,6,7,8,2,3,4,5,6,7,8,2,3,4,5,6,7,8,2,3,4,5,6,7,8]

그런 다음 모든 len(L)/2요소를 취하십시오 .

[1,2,3,4,5,6,7,8,2,3,4,5,6,7,8,2,3,4,5,6,7,8,2,3,4,5,6,7,8]
 ^       ^       ^       ^       ^       ^       ^       ^

6

파이썬, 68 57 바이트

f=lambda n,x:n and f(n-1,sum(zip(x,x[len(x)/2:]),()))or x

11 바이트를 골라 낸 @ Sp3000에 감사합니다!

Ideone에서 테스트하십시오 .


6

하스켈, 62 바이트

0!a=a
n!a|s<-length a=(n-1)![a!!mod(div(s*i+i)2)s|i<-[0..s-1]]

보자 = 2 · t이 목록의 크기. 새 목록 의 i 번째 요소는 enter image description here0으로 색인 된 이전 목록 의- 번째 요소를 모듈러스로 가져옵니다. .

증명 : i = 2 · k 가 짝수이면

                                         enter image description here

그리고 만약 I = 2 · K + 1은, 홀수

                        enter image description here

따라서 인덱싱에 사용되는 값은 0, t , 1, t + 1, 2, t + 2,…


5

J-12 바이트

부사 (!)는 왼쪽에서 셔플을 몇 번하고 오른쪽에서 셔플하기 위해 배열을 사용합니다.

/:#/:@$0,#^:

J 파서에는 암묵적 부사를 쓰는 규칙이있다 있지만 우선 순위가 매우 낮습니다. 동사를 왼쪽 인수로 사용하려면 필요한 괄호 세트를 생략 할 수 있습니다. 따라서 위의 내용은 실제로 짧아서 (/:#/:@$0,#)^:왼쪽의 셔플 수를 부사로 취한 다음 배열을 오른쪽으로 셔플하는 모나 딕 함수가됩니다.

즉, 다음과 같이 섞습니다. #배열의 길이이므로 0,#두 개의 요소 목록이 있습니다. 0 뒤에 0이 아닌 값이옵니다. 그런 다음 #/:@$입력 배열만큼 목록에 복제하고 정렬 벡터를 .

목록의 정렬 벡터는 목록을 정렬하는 방법에 대한 정보입니다. 가장 작은 요소의 (0 기반) invdex, 그 다음으로 가장 작은 인덱스 등이 있습니다. 예를 들어의 정렬 벡터는 0 1 0 1 ...입니다 0 2 4 ... 1 3 5 ....

J가 이제이 정렬 벡터를 정렬한다면, 파로 섞습니다. 그러나 우리가 0 1 2 3 ...돌아 오기 때문에 그것은 사소한 것 입니다. 따라서 우리는 dyadic/: 을 사용 하여 입력 배열 을 마치 마치 0 2 4 ... 1 3 5 ... Faro- 셔플 링하는 것처럼 정렬 합니다.

아래 사용법 예. tryj.tk 에서 직접 해보십시오 !

   1 (/:#/:@$0,#^:) 1 2 3 4 5 6 7 8
1 5 2 6 3 7 4 8

   f =: /:#/:@$0,#^:

   2  f  1 2 3 4 5 6 7 8
1 3 5 7 2 4 6 8

   7  f  _23 _37 52 0 _6 _7 _8 89   NB. "negative 1" is spelled _1
_23 _6 _37 _7 52 _8 0 89

   1  f  0 0 0 0 1 1 1              NB. odd-length lists
0 1 0 1 0 1 0

5

피스 -8 7 바이트

@issacg 덕분에 1 바이트를 절약했습니다.

usCc2GE

여기에서 온라인으로 사용해보십시오 .


2
흠 ... Pyth가 Jelly를 이길 경우 Jelly 답변에 문제가 있어야합니다.
Leaky Nun

2
입력 순서를 바꾸고를 제거하여 Q바이트를 저장하십시오. Jelly가 Pyth를 이길 경우 Pyth 답변에 문제가 있어야합니다. :)
isaacg 2016 년

@isaacg darn, 맹세 할 수 있었지만 이전에 시도해 보았습니다. 왜 작동합니까? uNone 을 사용 하여 기본값에 연결해서는 안되며 고정 소수점을 수행합니까?
Maltysen

@ Maltysen 당신 말이 맞아, 내가 시도한 하나의 테스트 케이스에서만 작동했다고 생각합니다. 미안합니다.
isaacg 2016

덕분에 @LeakyNun @Dennis@issacg , Pyth 젤리 해주기 (6 바이트)와 동일하다. ; D
Kevin Cruijssen


2

자바 스크립트 (ES6), 61 51 바이트

(n,a)=>[...a].map((e,i)=>a[(i<<n)%~-a.length||i]=e)

입력 배열을 수정하고 원래 배열의 복사본을 반환합니다. 허용되지 않는 경우 &&a접미사로 수정 된 배열을 반환 할 수 있습니다. nJavaScript 정수 산술의 한계로 인해 작은 값에서만 작동합니다 . @Lynn의 공식을 기반으로 더 큰 작동하는 61 바이트 바이트 재귀 버전 n:

f=(n,a,l=a.length)=>n?f(n-1,a.map((_,i)=>a[(i*-~l>>1)%l])):a

2

MATL , 11 바이트

w:"tn2/e!1e

@Dennis에게 감사의 말을 전합니다.

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

설명

w         % Take the two inputs N and A. Swap them
:         % Generate [1 2 ... N]
"         % Repeat N times
  tn2/    %   Duplicate A. Number of elements divided by 2
  e       %   Reshape to that number of rows
  !       %   Transpose
  1e      %   Reshape to one row
          % End (implicit)
          % Display (implicit)

w필요한가?
David

@David 그것은 정정이었다. 이것이 없으면 N = 0 인 경우 루프가 입력되지 않고 두 번째 입력이 수행되지 않습니다.
Luis Mendo

아 짜증나!
David

2

J, 22 19 17 바이트

@Gareth 덕분에 3 바이트 .

@algorithmshark 덕분에 2 바이트 .

-:@#({.,@,.}.)]^:

용법

>> f =: -:@#({.,@,.}.)]^:
>> 2 f 1 2 3 4 5 6 7 8
<< 1 3 5 7 2 4 6 8

>>STDIN은 어디에 있고 <<STDOUT입니다.

이전 22 바이트 버전 :

({~[:,/@|:@i.2,-:@#)^:

용법

>> f =: ({~[:,/@|:@i.2,-:@#)^:
>> 2 f 1 2 3 4 5 6 7 8
<< 1 3 5 7 2 4 6 8

>>STDIN은 어디에 있고 <<STDOUT입니다.


때문에의 J의 구문 분석 규칙 , 당신은이 개 문자의 바깥 쪽 괄호를 놓을 수 있습니다.
algorithmshark

18 바이트에{~2,@|:@i.@,-:@#^: 대해 전치 된 인덱스 를 사용하는 대안 .
마일

사용하는 또 다른 17 바이트[:,@|:]]\~_2%~#^:
마일

@ miles15 ,@|:@$~2,-:@#^:바이트에 대해 작동 한다고 생각 합니다
Jonah

1

매스 매 티카 44 바이트

@miles 덕분에 4 바이트가 절약되었습니다.

Riffle@@TakeDrop[#,Length@#/2]&~Nest~##&

Riffle @@ TakeDrop[#, Length@#/2] &~Nest~## &[list, nShuffles]목록을 두 개의 동일한 하위 목록으로 나누고 섞 Riffle습니다.


 Riffle @@ TakeDrop[#, Length@#/2] &~Nest~## &[Range@8, 1]

{1, 5, 2, 6, 3, 7, 4, 8}


Riffle @@ TakeDrop[#, Length@#/2] &~Nest~## &[Range@100, 23]

{1, 30, 59, 88, 18, 47, 76, 6, 35, 64, 93, 23, 52, 81, 11, 40, 69, 98, 28, 57, 86, 16, 45, 74, 4 , 33, 62, 91, 21, 50, 79, 9, 38, 67, 96, 26, 55, 84, 14, 43, 72, 2, 31, 60, 89, 19, 48, 77, 7, 36 , 65, 94, 24, 53, 82, 12, 41, 70, 99, 29, 58, 87, 17, 46, 75, 5, 34, 63, 92, 22, 51, 80, 10, 39, 68 , 97, 27, 56, 85, 15, 44, 73, 3, 32, 61, 90, 20, 49, 78, 8, 37, 66, 95, 25, 54, 83, 13, 42, 71, 100 }


를 사용하면 40 바이트TakeDrop사용하는 솔루션을 찾을 수 있을뿐만 아니라에 대한 추가 인수로 구문 분석 할 시퀀스 를 가져옵니다 . Riffle@@TakeDrop[#,Length@#/2]&~Nest~##&##Nest
마일

@ 마일. 의 아주 좋은 사용 TakeDrop. 그리고 ##시퀀스를 삽입하는 데 사용하는 것이 좋습니다 .
DavidC

1

APL, 23 21 자

({⊃,/⍵(↑,¨↓)⍨2÷⍨⍴⍵}⍣N)A

가정 (Dennis에게 감사)과 1 문자 더 짧은 :

({{∊,⌿2(2÷⍨≢⍵)⍴⍵}⍣⎕)⎕

온라인에서 사용해보십시오 .


1

자바, 109 바이트

int[]f(int[]a,int n){for(int x,q=a.length,d[];0<n--;a=d){d=new int[q];for(x=0;x<q;x++)d[(2*x+2*x/q)%q]=a[x];}return a;}

설명 : 요소가 셔플 될 때 요소가 움직이는 방식에 대한 패턴이 있습니다.

x를 원래 색인으로하자

y를 새로운 색인으로 삼자

L을 배열의 길이라고하자

  • y는 이중 x입니다
  • x가 L의 절반보다 크거나 같으면 y를 증가시킵니다.
  • 배열의 범위 내에서 y를 유지

또는 코드로 : y=(2*x+x/(L/2))%L

이것은 인덱스가 0에서 시작한다고 가정합니다. 코드는 다음과 같습니다.

int[] faroShuffle( int[] array, int numberOfShuffles ) {
    //repeat the faro shuffle n times
    for( int index, length=array.length, destination[]; 0<numberOfShuffles--; array=destination ) {
        //new array to copy over the elements
        destination=new int[length];
        //copy the elements into the new array
        for( index=0; index<length; index++ )
            destination[(2*index+2*index/length)%length]=array[index];
        //at the end of each loop, copy the reference to the new array and use it going forward
    }
    return array;
}  

테스트 사례에 대한 아이디어를 참조하십시오


나는 그것이 1 년 이상 지났음을 알고 있지만, 당신은 몇 부분을 골프를 칠 수 있습니다 : void f(int[]a,int n){for(int x,q=a.length,d[];0<n--;a=d)for(d=new int[q],x=0;x<q;)d[(2*x+2*x/q)%q]=a[x++];}( 107 바이트 -현재 답변은 119 바이트가 아니라 109 바이트이므로 -12 바이트) 입력 배열을 수정하므로 반환 할 필요가 없으므로 바이트를 줄이기 위해 void로 변경할 수 있습니다. 아, 그리고 카레를 사용하여 Java 8 람다로 변환하면 더 짧게 만들 수 있습니다. a->n->{for(int x,q=a.length,d[];0<n--;a=d){d=new int[q];for(x=0;x<q;x++)d[(2*x+2*x/q)%q]=a[x];}}( 96 bytes )
Kevin Cruijssen

1

줄리아, 45 42 바이트

a\n=n>0?reshape(a,endof(a)÷2,2)'[:]\~-n:a

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

작동 원리

\이 작업을 위해 이진 연산자 를 정의합니다 . 하자 A가 배열되고 n은 음이 아닌 정수.

경우 n은 긍정적이다, 우리는 배열을 섞는다. 이것은 길이 (a) ÷ 2 행 및 2 열의 행렬로 재구성함으로써 달성됩니다 . '결과 행렬을 전치하고 두 개의 행을 만든 다음 결과를로 평탄화합니다 [:]. Julia는 행렬을 열 주요 순서로 저장하므로 두 행을 인터리브합니다.

그 후, \셔플 된 an-1 ( ~-n)을 인자로 재귀 적으로 호출 하여 추가 셔플을 수행합니다. 일단 n 개 에 도달 0 , 우리의 현재 값 반환 .



0

실제로 15 바이트

`;l½≈@│t)HZ♂i`n

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

설명:

`;l½≈@│t)HZ♂i`n
`            `n  do the following n times:
 ;l½≈              push half the length of the array
     @             swap
      │            duplicate entire stack
       t)H         last L//2 elements, first L//2 elements
          Z♂i      zip, flatten each element

0

프롤로그, 116 바이트

a([],[[],[]]).
a([H,I|T],[[H|U],[I|V]]):-a(T,[U,V]).
f(X,0,X).
f(X,N,Y):-N>0,M is N-1,f(X,M,Z),a(Z,[A,B]),append(A,B,Y).

용법

?- f([1,2,3,4,5,6,7,8],2,X).
X = [1, 5, 2, 6, 3, 7, 4, 8] ;
false.


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