양말 서랍 시뮬레이션


16

배경

요일로 표시된 7 쌍의 양말 인 "평일 양말"컬렉션이 있습니다. 양말을 씻을 때 더미에 쌓여 옷장에 넣기 전에 올바른 쌍으로 정리해야합니다. 내 전략은 더미에서 한 번에 하나의 무작위 양말을 꺼내 서랍에 넣는 것입니다. 서랍에 맞는 양말 한 켤레가있을 때마다 양말을 묶어 옷장에 넣습니다. 당신의 임무는이 무작위 프로세스를 시뮬레이션하고 첫 번째 일치하는 쌍을 찾는 데 필요한 추첨 수를 반환하는 것입니다.

입력

입력 값은 정수 N ≥ 1 입니다. "일주일 일수"를 나타냅니다. 더미에 N 쌍의 양말이 있으며 각 쌍에는 고유 한 레이블이 있습니다. 필요한 경우 PRNG 시드를 입력으로 사용할 수도 있습니다.

산출

당신의 출력은 첫 번째 일치하는 쌍을 찾기 전에 내가 뽑아야하는 양말의 수입니다. 예를 들어 처음 두 양말이 이미 일치하는 쌍을 형성하면 출력은 2입니다.

물론 출력은 임의적이며 도면 순서에 따라 다릅니다. 양말을 그릴 때마다 선택이 균일하고 다른 모든 선택과 독립적이되도록 모든 도면 순서가 동일 하다고 가정 합니다.

하자 N = 3 우리는 총 6 개 양말, 라벨이 그래서, AABBCC을 . "양말 드로잉 프로토콜"의 가능한 실행은 다음과 같습니다.

       | Pile   | Drawer | Pairs
Begin  | AABBCC | -      | -
Draw B | AABCC  | B      | -
Draw C | AABC   | BC     | -
Draw B | AAC    | C      | BB
Draw A | AC     | AC     | BB
Draw A | C      | C      | AA BB
Draw C | -      | -      | AA BB CC

첫 번째 일치 쌍은 두 번째 B 를 그리고 난 후 세 번째 양말이 그려 졌으므로 올바른 출력이 3됩니다.

규칙과 득점

전체 프로그램 또는 함수를 작성할 수 있습니다. 가장 낮은 바이트 수가 이기고 표준 허점이 허용되지 않습니다. 입력 및 출력은 단항 (1 s)을 .

언어의 내장 RNG가 완벽하다고 가정 할 수 있습니다. 출력에 올바른 확률 분포가있는 한 실제로 양말 그리기 프로토콜을 시뮬레이션 할 필요는 없습니다.

"테스트 사례"

다음은 입력 N = 7에 대한 모든 출력의 대략적인 확률입니다 .

Output       2     3     4     5     6     7     8
Probability  0.077 0.154 0.210 0.224 0.186 0.112 0.037

솔루션을 테스트하기 위해, 예를 들어, 40,000 회 실행하여 출력 분포가 이에 가까운 지 확인할 수 있습니다.


25
실제 생활, 42 바이트Draw all socks. End up with an odd number.
AdmBorkBork


따라서 n = 8은 1-> 7과 같지 않다가 다시 1입니까? 즉, 1 개의 레이블이 붙은 4 개의 양말
Viktor Mellgren

@ViktorMellgren 아니요, 8 개의 고유 한 레이블이 있습니다.
Zgarb

나는 동일한 양말로 가득 찬 서랍을 가지고 있으므로 그들을 분류 할 필요가 없습니다.
JDługosz

답변:


9

젤리 , 8 바이트

ḤX€Ṛ<RTḢ

온라인으로 사용해보십시오! 또는 N = 7에 대한 분포를 확인하십시오 .

배경

n 을 쌍의 수로 하자 . 가 2N 개인 양말.

첫 번째 추첨의 경우 2n 양말 이 있으며 그 중 0 개 는 일치하는 쌍이됩니다. 따라서 성공 확률은 0 / 2n = 0입니다. 입니다.

첫 번째 무승부가 성공하지 못한 때문에, 거기에 2N - 1 개 더미에 양말과 1 일치하는 쌍을 초래 그들은. 따라서 성공 확률은 1 / (2n-1) 입니다.

경우 두 번째 무승부에 성공하지, 거기에 2N - 2 개 더미에 양말 일치하는 쌍을 초래 그들은. 따라서 성공 확률은 2 / (2n-2) 입니다.

일반적으로 첫 번째 k 추첨이 실패한 경우 더미에 2n-k 양말이 있으며 그중 2 개가 일치하는 쌍이됩니다. 따라서 성공 확률은 k / (2n-k)입니다. 입니다.

마지막으로, 첫 번째 n 추첨 중 어느 것도 성공하지 못한 경우, 더미에 2n-k 양말이 있으며 모두 일치하는 쌍이됩니다. 따라서 성공 확률은 n / (2n-n) = 1 입니다.

작동 원리

ḤX€Ṛ<RTḢ  Main link. Argument: n

Ḥ         Unhalve; yield 2n.
 X€       Map `random draw' over [1, ..., 2n], pseudo-randomly choosing an integer
          from [1, ..., k] for each k in [1, ..., 2n].
   Ṛ      Reverse the resulting array.
     R    Range; yield [1, ..., n].
    <     Perform vectorized comparison.
          Comparing k with the integer chosen from [1, ..., 2n - (k - 1)] yields 1
          with probability (k - 1) / (2n - (k - 1)), as desired.
          The latter half of elements of the left argument do not have a counter-
          part in the right argument, so they are left untouched and thus truthy.
      T   Truth; yield all indices of non-zero integers.
       Ḣ  Head; extract the first one.

8

젤리, 8 바이트

Rx2ẊĠṪ€Ṃ

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

R    generate [1, 2, ..., n]
x2   duplicate every element (two socks of each pair)
Ẋ    shuffle the list, to represent the order in which socks are drawn
Ġ    group indices by value. this will produce a list of pairs of indices;
       each pair represents the point in time at which each of the corresponding
       socks were drawn
Ṫ€   take the last element of each pair. this returns an array of n integers
       which represent the points in time at which a matching sock was drawn
Ṃ    minimum, find the first point at which a matching sock was drawn

확인하려면 다음은 원하는 출력과 "셔플 목록"작업의 결과를 표시 하는 버전 입니다 (주문 양말이 어떤 순서로 그려 졌는지 확인).


5

파이썬, 66 바이트

from random import*
f=lambda n,k=1:k>randint(1,n*2)or-~f(n-.5,k+1)

Dennis는 사물을 재배치하여 5 바이트를 절약 할 수있는 영리한 방법을 생각했습니다.


4

MATL , 16 15 바이트

Q:"r@qGEy-/<?@.

온라인으로 사용해보십시오! 또는 N = 7의 경우 1000 개의 샘플에 대한 경험적 분포관찰하십시오 (시간이 걸립니다).

이것은 직접 생성 확률 변수 의 확률 분포에 기초하여 결과를 나타내는. 하자 N은 양말 쌍의 수, 그리고하자 P ( K를 확률을 나타낸다) K 번째 무승부는 사실을 조건으로, 성공적으로 그 k는 -1 번째 무승부 성공적인 아니었다. 그런 다음 ( 여기 참조 ) :

  • p (1)은 분명히 0입니다. 단일 양말과 쌍을 가질 수 없습니다.
  • p (2)는 1 / (2 * N -1)이다. 두 번째 추첨에는 2 * N -1 남은 양말 중에서 선택할 수있는 우승 양말이 1 개 있습니다 .
  • p (3)은 2 / (2 * N- 2)이다. 세 번째 추첨에는 2 * N- 2 중에서 2 개의 우승 양말이 있습니다 . 두 번째 추첨 후 얻은 두 양말이 다르기 때문에 우승 양말의 수는 2입니다.
  • 일반적으로 동일한 추론에 의해 p ( k )는 ( k -1) / (2 * N - k +1)입니다.
  • 상기 식에 의해, p ( N 당신이 얻을 경우 +1)이 1입니다 N + 1 번째 당신이 다음 성공을 보장립니다.

따라서 코드는 최대 N +1 드로우 동안 반복됩니다 . 상기 K 개의 랜덤 변수가 확률 1 (같 생성 그릴 번째 K (2 * -1) / N - K 기타), 또는 0. 랜덤 변수가 1 (드로우 성공)과 동일 할 때마다 프로세스가 중지되고 현재 k 가 출력됩니다.

Q:      % Input N implicitly. Generate [1 2 ... N+1] (values of draw index, k)
"       % For each
  r     %   Random variable uniformly distributed on the interval (0,1)
  @q    %   Push iteration index, k-1
  GE    %   Push 2*N
  y     %   Duplicate: push k-1 again
  -     %   Subtract: gives 2*N-k+1
  /     %   Divide: gives (k-1)/(2*N-k+1)
  <     %   Push 1 if random value is less than (k-1)/(2*N-k+1), 0 otherwise
  ?     %   If we got a 1
    @   %     Push k
    .   %     Break loop
        %   End if implicitly
        % End loop implicitly
        % Display implicitly

1
당신과 나는 같은 생각을 가지고 있지만, 당신은 MATL을 알고 있습니다 :)
Program man

3

MATL , 14 13 바이트

EZ@G\&=XRafX<

온라인으로 사용해보십시오! 또는 N = 7의 경우 4000 개의 샘플에 대한 경험적 분포관찰하십시오 (시간이 걸립니다).

E      % Input N implicitly. Multiply by 2
Z@     % Random permutation of [1 2 ... 2*N]
G\     % Modulo N: random permutation of [0 0 1 1 ... N-1 N-1]
&=     % Compare all pairs for equality. Gives an N×N matrix
XR     % Upper triangular part excluding the diagonal
a      % True for each column if it contains at least one true entry
f      % Get indices of true values
X<     % Take minimum. Implicitly display

3

자바 스크립트, 77 73 바이트

n=>{p={};for(i=n;i--;p[i]=2);while(--p[n*Math.random()|0])i++;return i+2}

설명

var f = (n) => {
    var index;      // used first to initialize pile, then as counter
    var pile = {};  // sock pile

    // start with index = n
    // check that index > 0, then decrement
    // put 2 socks in pile at index
    for(index = n; index--; pile[index] = 2);
    // index is now -1, reuse for counter

    // pick random sock out of pile and decrement its count
    // continue loop if removed sock was not the last
    while(--pile[n * Math.random() | 0]) {
        index++;    // increment counter
    }
    // loop finishes before incrementing counter when first matching pair is removed
    // add 1 to counter to account for initial value of -1
    // add 1 to counter to account for drawing of first matching pair
    return index + 2;
};

당신은 네 개의 문자를 대체 저장할 수 있습니다 f=(n)=>n=>(당신이 할당을 유지하려는 경우, 또는 두 개의 일부를 유지 , 일부 삭제를 ).
구스타보 로드리게스

잘 잡았습니다. 고쳤습니다. 규칙에서 "전체 프로그램 또는 함수를 작성할 수 있습니다"를 읽을 때 이것이 필수라고 생각했습니다.
kamoroso94

3
Meta에 대한 합의에 따라 이름에 바인딩되지 않은 명명되지 않은 함수는 기본적으로 허용됩니다.
Zgarb

이것이 JavaSock이 아니어야합니까? (yes, lame)
gcampbell


2

파이썬 3 142 105 104 바이트

1 바이트를 절약 한 Eʀɪᴋ ᴛʜᴇ Gᴏʟғᴇʀ 에 감사합니다 !

나의 첫 번째 답변 :

import random 
i=[x/2 for x in range(int(2*input()))]
d=[]
a=0
random.shuffle(i)
while 1:
 b=i.pop()
 if b in d:
  print(a)
  s
 d=d+[b]
 a+=1

나의 새로운 답변 :

from random import*
i=range(int(input()))*2
shuffle(i)
j=0
for x in i:
 if x in i[:j]:print(1+j)+s
 j+=1

둘 다 NameErroron으로 종료 됩니다 s.


2

R, 49

N=scan();which(duplicated(sample(rep(1:N,2))))[1]

R에서 이것을하는 더 좋은 방법이 있어야한다고 확신합니다! 더 똑똑한 일을 시도했지만 작동하지 않았습니다.

편집 : @bouncyball에 의해 기능이 필요하지 않으므로 개선되었습니다.


사용해야 function(N)합니까? 를 사용 N=scan();하면 2 바이트를 절약 할 수 있습니다
bouncyball

1

파이썬 2, 101 바이트

from random import*
d=[]
p=range(input())*2
shuffle(p)
while list(set(d))==d:d+=p.pop(),
print len(d)

0

VBA, 61 바이트

Function K(D):While 2*D-K>K/Rnd:K=K+1:Wend:K=K+1:End Function

-이전의 경기 실패에 대한 양말 경기의 이동 확률을 모델링합니다. 평가 시점에서 K는 "손에 양말"이므로 추첨 번호가 하나 더 있습니다.


0

Pyth, 14 바이트

lhfnT{T._.S*2S

설명:

       ._        #Start with a list of all prefixes of
         .S      #a randomly shuffled
           *2S   #range from 1 to input (implicit), times 2.
  f              #filter this to only include elements where
   nT{T          #element is not equal to deduplicated self (i.e. it has duplicates)
lh               #print the length of the first element of that filtered list
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.