카드를 뽑은 후 에이스, 2, 3 등을 얻을 때까지 예상되는 수


12

다음을 해결하는 데 문제가 있습니다.

에이스를 얻을 때까지 교체하지 않고 표준 52 카드 데크에서 카드를 가져옵니다. 당신은 2를 얻을 때까지 남은 것에서 뽑습니다. 계속해서 3을 계속합니다.

시키는 것이 자연 스러웠다

  • Ti=first position of card whose value is i
  • Ui=last position of card whose value is i

따라서 문제는 본질적으로 갑판이 다 떨어질 때 올 확률을 알아내는 것입니다 .k

Pr(T1<<TkUk+1<Tk)

나는 그것을 볼 수 있습니다

Pr(T1<<Tk)=1/k!andPr(Uk+1<Tk)=1/70

그러나 더 이상 얻을 수 없었습니다 ...


1
첫 에이스를 그릴 때 까지 초를 모두 그렸다면 어떻게됩니까 ? 2
gung-모니 티 복원

"예상 된"숫자가 실제로 "가장 가능성이 높은"숫자를 의미합니까?
whuber

이것은 흥미로운 문제이지만, "문제가 본질적으로 중요한"이후에 쓴 수학에 대해서는 잘 모르겠습니다. 첫 번째 문장에서 대신 을 쓰려고 했습니까? 그럼에도 불구하고, 나는 그 진술이 정확한지 확신하지 못한다. 시퀀스 시작을 고려하십시오 . 우리는이 등 하지만, 내가 바로 당신의 텍스트 설명을 이해한다면 우리는 여전히 다섯 번째 위치에 다음 2 번째 위치에 에이스를 선택할 수 있습니다? 따라서 가 필요한 조건이 아닙니까? T 1 = 2 , T 2 = 1 T 1 > T 2 T 1 < T 22AAA2T1=2,T2=1T1>T2T1<T2
TooTone

@TooTone 오, 나는 당신이 말한 것처럼 의미 했고, 당신이 옳습니다. 는 필수 조건이 아닙니다 ...T 1 < T 2T1<T2
bill

@gung이 경우에, 당신의 갑판은 다 떨어지고 당신은 여전히 ​​2에있을 것입니다.
bill

답변:


0

@ gung의 아이디어에 따라 예상 값이 5.84라고 생각합니까? 그리고 의견에 대한 나의 해석에서, 나는 "A"가 거의 불가능한 값이라고 가정합니다 (갑판의 마지막 4 장의 카드가 모두 에이스가 아닌 한). 다음은 몬테 카를로 시뮬레이션의 반복 결과입니다.

results
    2     3     4     5     6     7     8     9     J     K     Q     T 
 1406  7740 16309 21241 19998 15127  9393  4906   976   190   380  2334 

여기에 R 코드가 있습니다.

# monte carlo card-drawing functions from here
# http://streaming.stat.iastate.edu/workshops/r-intro/lectures/5-Rprogramming.pdf

# create a straightforward deck of cards
create_deck <-
    function( ){
        suit <- c( "H" , "C" , "D" , "S" )
        rank <- c( "A" , 2:9 , "T" , "J" , "Q" , "K" )
        deck <- NULL
        for ( r in rank ) deck <- c( deck , paste( r , suit ) )
        deck
    }

# construct a function to shuffle everything
shuffle <- function( deck ){ sample( deck , length( deck ) ) }

# draw one card at a time
draw_cards <-
    function( deck , start , n = 1 ){
        cards <- NULL

        for ( i in start:( start + n - 1 ) ){
            if ( i <= length( deck ) ){
                cards <- c( cards , deck[ i ] )
            }
        }

        return( cards )
    }

# create an empty vector for your results
results <- NULL

# run your simulation this many times..
for ( i in seq( 100000 ) ){
    # create a new deck
    sdeck <- shuffle( create_deck() )

    d <- sdeck[ grep('A|2' , sdeck ) ]
    e <- identical( grep( "2" , d ) , 1:4 )

    # loop through ranks in this order
    rank <- c( "A" , 2:9 , "T" , "J" , "Q" , "K" )

    # start at this position
    card.position <- 0

    # start with a blank current.draw
    current.draw <- ""

    # start with a blank current rank
    this.rank <- NULL

    # start with the first rank
    rank.position <- 1

    # keep drawing until you find the rank you wanted
    while( card.position < 52 ){

        # increase the position by one every time
        card.position <- card.position + 1

        # store the current draw for testing next time
        current.draw <- draw_cards( sdeck , card.position )

        # if you draw the current rank, move to the next.
        if ( grepl( rank[ rank.position ] , current.draw ) ) rank.position <- rank.position + 1

        # if you have gone through every rank and are still not out of cards,
        # should it still be a king?  this assumes yes.
        if ( rank.position == length( rank ) ) break        

    }

    # store the rank for this iteration.
    this.rank <- rank[ rank.position ]

    # at the end of the iteration, store the result
    results <- c( results , this.rank )

}

# print the final results
table( results )

# make A, T, J, Q, K numerics
results[ results == 'A' ] <- 1
results[ results == 'T' ] <- 10
results[ results == 'J' ] <- 11
results[ results == 'Q' ] <- 12
results[ results == 'K' ] <- 13
results <- as.numeric( results )

# and here's your expected value after 100,000 simulations.
mean( results )

A불가능합니까? AAAA예를 들어 48 장의 카드 순서를 고려하십시오 .
TooTone

맞습니다 .. 그것은 270725 중 하나입니다-또는 R 코드와 함께1/prod( 48:1 / 52:5 )
Anthony Damico

1
이 답변은 잘못되었습니다. "2"의 수를 고려하십시오. 이는 모든 2가 1보다 먼저 발생하는 경우에만 발생할 수 있기 때문에 모든 에서 확률은 1 이므로 시뮬레이션에 대한 기대는 , 표준 오류는 입니다. 의 출력이 6 개의 표준 오류를 초과하여 거의 확실하게 잘못되었습니다. 평균에 대한 정확한 값 ( 반복 으로 다른 시뮬레이션을 기반으로 함 )은 입니다. 105/ ( 8(84)=7037.516601065.833±0.004105/(84)1428.637.516601065.833±0.004
whuber

1
많이 문서화 된 코드는 불행히도 필요 이상으로 몇 배 더 길고 느립니다. 출력이 잘못되었음을 시연했습니다. 나는 당신의 코드를 디버깅 할 시간이 있었으면 좋겠지 만 그렇게하지 않는 것은 내 임무가 아닙니다. 나의 주장은 이것이다 : 만일 모든 "2"가 모든 "A"보다 우선하는 경우에만, 마지막에 "2"로 작업 할 것이다. 4 개의 "2"와 4 개의 "A"를 배열 하는 똑같이 가능한 방법 중 정확히 하나가이 기준을 충족합니다. 따라서 제목 "2"아래의 값은 가까워 야 하지만 그렇지 않습니다. 105/70=1,429(4+44)=70results105/70=1429
whuber

1
중재자조차도 다른 사람들의 투표를 제거 할 수 없습니다 :-). 카이 제곱 테스트는 결과가 내 결과와 일치 함을 시사하지만 시뮬레이션에 대한 테스트 방법을 아는 것이 좋을 것입니다. 사실, 당신이 당신의 대답에 첫 번째 단락에 만들어진 편집에 따라 지금은 모두 우리의 결과는 잘못 : 나는 당신의 질문을 해석대로, 그것은하지 않습니다 모든 카드가 소진 때 여전히 에이스 작업을 할 수 있습니다.
whuber

7

시뮬레이션을 위해서는 정확 하고 빠른 것이 중요합니다 . 이 두 가지 목표는 프로그래밍 환경의 핵심 기능을 목표로하는 코드 작성과 가능한 짧고 간단한 코드 작성을 제안합니다. 단순함은 명확함과 선명함이 정확성을 높이기 때문입니다. 다음은 두 가지를 모두 달성하려는 시도입니다 R.

#
# Simulate one play with a deck of `n` distinct cards in `k` suits.
#
sim <- function(n=13, k=4) {
  deck <- sample(rep(1:n, k)) # Shuffle the deck
  deck <- c(deck, 1:n)        # Add sentinels to terminate the loop
  k <- 0                      # Count the cards searched for
  for (j in 1:n) {
    k <- k+1                          # Count this card
    deck <- deck[-(1:match(j, deck))] # Deal cards until `j` is found
    if (length(deck) < n) break       # Stop when sentinels are reached
  }
  return(k)                   # Return the number of cards searched
}

다음 과 같이 난수 시드를 설정 한 후 함수를 사용하여 이를 재현 가능한 방식으로 적용 할 수 있습니다 replicate.

> set.seed(17);  system.time(d <- replicate(10^5, sim(13, 4)))
   user  system elapsed 
   5.46    0.00    5.46

속도는 느리지 만 기다릴 필요없이 상당히 길고 정확한 시뮬레이션을 반복적으로 수행 할 수있을 정도로 빠릅니다. 결과를 나타낼 수있는 몇 가지 방법이 있습니다. 그 평균으로 시작합시다.

> n <- length(d)
> mean(d)
[1] 5.83488

> sd(d) / sqrt(n)
[1] 0.005978956

후자는 표준 오차입니다. 시뮬레이션 된 평균이 실제 값의 2 개 또는 3 개의 SE 내에있을 것으로 예상합니다. 이로 인해 실제 기대 값은 에서 사이5.8535.8175.853 입니다.

우리는 또한 주파수 (과의 표를 참조 할 수 있습니다 자신의 표준 오차를). 다음 코드는 도표를 약간 미리 보여줍니다.

u <- table(d)
u.se <- sqrt(u/n * (1-u/n)) / sqrt(n)
cards <- c("A", "2", "3", "4", "5", "6", "7", "8", "9", "T", "J", "Q", "K")
dimnames(u) <- list(sapply(dimnames(u), function(x) cards[as.integer(x)]))
print(rbind(frequency=u/n, SE=u.se), digits=2)

출력은 다음과 같습니다.

                2       3      4      5      6      7       8       9       T       J       Q       K
frequency 0.01453 0.07795 0.1637 0.2104 0.1995 0.1509 0.09534 0.04995 0.02249 0.01009 0.00345 0.00173
SE        0.00038 0.00085 0.0012 0.0013 0.0013 0.0011 0.00093 0.00069 0.00047 0.00032 0.00019 0.00013

시뮬레이션이 올바른지 어떻게 알 수 있습니까? 한 가지 방법은 작은 문제에 대해 철저하게 테스트하는 것입니다. 이 때문에이 코드 교체, 문제의 작은 일반화를 공격하기 위해 작성되었습니다 와 별개의 카드 와 와 정장 . 그러나 테스트를 위해 코드에 데크를 미리 정해진 순서대로 공급할 수 있어야합니다. 동일한 알고리즘에 약간 다른 인터페이스를 작성해 봅시다 :413n4k

draw <- function(deck) {
  n <- length(sentinels <- sort(unique(deck)))
  deck <- c(deck, sentinels)
  k <- 0
  for (j in sentinels) {
    k <- k+1
    deck <- deck[-(1:match(j, deck))]
    if (length(deck) < n) break
  }
  return(k)
}

(사용할 수 있습니다 draw대신에 sim모든 곳에서, 그러나의 시작 부분에 수행 된 추가 작업 draw느린 배 차종을 sim.)

주어진 데크의 모든 셔플 에 적용하여 사용할 수 있습니다 . 여기서의 목적은 일회성 테스트 일 뿐이므로 셔플 생성의 효율성은 중요하지 않습니다. 다음은 빠른 무차별 방식입니다.

n <- 4 # Distinct cards
k <- 2 # Number of suits
d <- expand.grid(lapply(1:(n*k), function(i) 1:n))
e <- apply(d, 1, function(x) var(tabulate(x))==0)
g <- apply(d, 1, function(x) length(unique(x))==n)
d <- d[e & g,]

이제 d행에 모든 셔플이 포함 된 데이터 프레임이 있습니다. draw각 행에 적용 하고 결과를 세십시오.

d$result <- apply(as.matrix(d), 1, draw)
    (counts <- table(d$result))

결과는 (정식 테스트에서 잠시 사용할 것입니다)

   2    3    4 
 420  784 1316 

(의 값 그런데, 이해하기 쉬운 : 우리는 여전히 카드에 일하게 될 것이라고 경우 모든의 보수는 모든 에이스를 선행하는 경우에만이 일어나는의 기회를 (두 벌과)입니다. 의. 아웃 구별 셔플을 이 특성을 갖는다.)2 1 / ( 2 + 2420225202520/6=4201/(2+22)=1/625202520/6=420

카이 제곱 테스트로 출력을 테스트 할 수 있습니다. 이를 위해 소송 에서 개의 개별 카드의 경우 번을 적용 합니다.sim 10,000n=4k=2

>set.seed(17)
>d.sim <- replicate(10^4, sim(n, k))
>print((rbind(table(d.sim) / length(d.sim), counts / dim(d)[1])), digits=3)

         2     3     4
[1,] 0.168 0.312 0.520
[2,] 0.167 0.311 0.522

> chisq.test(table(d.sim), p=counts / dim(d)[1])

    Chi-squared test for given probabilities

data:  table(d.sim) 
X-squared = 0.2129, df = 2, p-value = 0.899

가 너무 높기 때문에 우리 는 말과 철저한 열거로 계산 된 값 사이에 큰 차이가 없습니다 . 과 의 다른 (작은) 값에 대해이 연습을 반복 하면 비슷한 결과가 나오므로 과 적용될 때 신뢰할만한 충분한 이유가 됩니다 .psimnksimn=13k=4

마지막으로 2- 표본 카이 제곱 테스트sim출력을 다른 답변에보고 된 출력과 비교합니다 .

>y <- c(1660,8414,16973,21495,20021,14549,8957,4546,2087,828,313,109)
>chisq.test(cbind(u, y))

data:  cbind(u, y) 
X-squared = 142.2489, df = 11, p-value < 2.2e-16

막대한 카이 제곱 통계량은 본질적으로 0 인 p- 값을 생성합니다 . 의심 할 여지없이 sim다른 답변에 동의하지 않습니다. 불일치에 대한 두 가지 가능한 해결책이 있습니다.이 답변 중 하나 (또는 ​​둘 다!)가 틀리거나 질문에 대한 다른 해석을 구현합니다. 예를 들어, 나는 마지막 카드를 관찰 한 "덱이 바닥 난 후"를 의미 하고, 가능하다면 절차를 종료하기 전에 "사용할 번호"를 업데이트 한 것으로 해석했습니다 . 아마도 그 마지막 단계는 취해지지 않았습니다. 아마도 그러한 미묘한 해석 차이는 의견 차이를 설명 할 것이며,이 시점에서 우리는 질문을 명확하게하기 위해 질문을 수정할 수 있습니다.


4

정확한 답이 있습니다 (아래 4 항에 제시된 매트릭스 제품 형태). 이를 계산하기 위해 합리적으로 효율적인 알고리즘이 존재합니다.

  1. 셔플의 임의의 카드 랜덤 셔플 링에 의해 생성 될 수있는 카드하고 임의로 산재 나머지 그 안에 카드.N+kNk

  2. 에이스 만 섞은 다음 (첫 번째 관찰을 적용하여) 두 개, 세 개 등을 산재시킴으로써이 문제는 13 단계의 체인으로 볼 수 있습니다.

  3. 우리는 우리가 찾고있는 카드의 가치보다 더 많은 것을 추적해야합니다. 그러나 이렇게 할 때 모든 카드에 대한 마크의 위치를 ​​설명 할 필요는 없지만 값이 같거나 작은 카드에 대한 위치 만 고려하면됩니다.

    첫 에이스에 표시를 한 다음 그 뒤에 나오는 첫 번째 두 개의 마크를 표시하는 것을 상상해보십시오. (어떤 단계에서든 현재 찾고있는 카드를 표시하지 않고 덱이 떨어지면 모든 카드를 표시하지 않은 상태로 둡니다.) 각 마크의 "장소"(존재하는 경우)는 값이 같거나 낮은 카드 수입니다. 마크가 만들어 졌을 때 (표시된 카드 자체 포함) 처리되었습니다. 장소는 모든 필수 정보를 포함합니다.

  4. 표시 뒤의 위치 는 임의의 숫자입니다. 특정 데크의 경우 이러한 장소의 순서는 확률 적 프로세스를 형성합니다. 실제로 Markov 프로세스 (가변 전이 행렬 포함)입니다. 따라서 12 개의 행렬 곱셈을 통해 정확한 답을 계산할 수 있습니다.ith

이 아이디어를 사용하여이 기계는 초 안에 (배정 밀도 부동 소수점으로 계산) 의 값을 얻습니다 . 정확한 값 은 표시된 모든 자릿수에 정확합니다.5.83258855290199651/9

1982600579265894785026945331968939023522542569339917784579447928182134345929899510000000000

이 게시물의 나머지 부분에서는 세부 정보를 제공하고 실제 구현을 제공하며 R질문과 솔루션의 효율성에 대한 의견으로 마무리합니다.


갑판의 무작위 셔플 생성

그것은 (일명 개념적 실제로 명확하고 더 이상은 "데크"를 고려하는 것이 수학적으로 복잡 MULTISET )의 가있는 카드 가장 낮은 교단의 등 다음으로 낮은, 그리고 . (질문과 같은 질문은 벡터 의해 결정된 데크에 관한 것 입니다.)N=k1+k2++kmk1k213(4,4,,4)

카드 의 "무작위 셔플"은 에서 균일하고 무작위로 가져온 하나의 순열입니다 카드의 순열 . 이러한 셔플은 "aces"를 변경하면 아무것도 변경되지 않고 "twos"를 변경해도 아무것도 변경되지 않기 때문에 동등한 구성의 그룹으로 분류 됩니다. 따라서 카드의 양복이 무시 될 때 동일하게 보이는 각 순열 그룹에는순열. 다항식 계수에 의해 주어진 수의 그룹N ! = N × ( N - 1 ) × × 2 × 1 N k 1 k 2NN!=N×(N1)××2×1Nk1k2k1!×k2!××km!

(Nk1,k2,,km)=N!k1!k2!km!,

갑판의 "조합"이라고합니다.

조합을 계산하는 다른 방법이 있습니다. 첫 번째 카드는 조합. 다음 카드를 놓을 수 있도록 그들 사이와 주변에 "슬롯"을 남겨 둡니다 . " "는 카드 중 하나를 지정 하고 " "는 과 사이의 추가 카드를 넣을 수있는 슬롯을 지정 하는 다이어그램 으로이를 수 있습니다 .k1k1!/k1!=1k1+1k2k1_0k2

_____k1 stars

때 추가 카드가 산재되어, 별과 새로운 카드 파티션의 패턴 두 부분 집합으로 카드. 고유 한 하위 집합의 수는 입니다.k2k1+k2(k1+k2k1,k2)=(k1+k2)!k1!k2!

"threes" 로이 절차를 반복하면 는 첫 번째 카드 사이에 하는 방법 입니다. 따라서 이런 식으로 첫 번째 카드 를 배열하는 총 고유 한 방법의 수는k3((k1+k2)+k3k1+k2,k3)=(k1+k2+k3)!(k1+k2)!k3!k1+k2k1+k2+k3

1×(k1+k2)!k1!k2!×(k1+k2+k3)!(k1+k2)!k3!=(k1+k2+k3)!k1!k2!k3!.

마지막 카드를 완성 하고이 텔레 스코핑 비율을 계속해서 곱한 후 , 얻은 고유 조합 수가 이전에 계산 된 총 조합 수인 . 따라서 우리는 조합을 간과하지 않았습니다. 이는 카드를 순서대로 섞는이 순차적 프로세스가 각 단계에서 기존 카드 중 새 카드를 산재하는 각각의 고유 한 방법이 균일하게 동일한 확률로 가정된다는 가정하에 각 조합의 확률을 정확하게 포착 한다는 것을 의미 합니다 .kn(Nk1,k2,,km)

장소 프로세스

처음에는 개의 에이스가 있으며 분명히 첫 번째가 표시됩니다. 후기 단계에는 카드가 있으며 장소 (표시된 카드가있는 경우)는 (일부 값은 에서 임 )와 같 으며 는 산재하려고합니다. 주위에 카드. 우리는 이것을 다음과 같은 다이어그램으로 시각화 할 수 있습니다k1n=k1+k2++kj1p1nk=kj

_____p1 stars____np stars

여기서 " "는 현재 표시된 기호를 나타냅니다. 조건부 장소의이 값에 , 우리는 다음 장소는 동일 확률 찾고자 (일부 값 을 통해 , 게임의 규칙에 의해, 다음 장소 후에 와야 , 어디서 ). 우리가 산재하기 위해 얼마나 많은 방법을 찾아 낼 수있는 경우에 그래서 다음 장소에 해당하는 빈칸에 새로운 카드를 , 우리는이 카드를 산재하는 방법의 총 개수로 나눌 수 있습니다 (동일 우리가 본 것처럼pq1n+kpqp+1kq(n+kk)장소가 에서 바뀌는 전이 확률 . (표시된 카드를 따르는 새 카드도 없을 때 장소가 완전히 사라질 가능성이 있지만이를 명시 적으로 계산할 필요는 없습니다.)pq

이 상황을 반영하도록 다이어그램을 업데이트하겠습니다.

_____p1 starss stars | ____nps stars

"세로줄 제 새로운 카드가 표시된 카드 후에 발생 쇼" 새로운 카드 그러므로 사이 나타나지 않을 수 및 (따라서 어떤 슬롯이 그 간격에 도시되지 않음). 우리는이 구간에 얼마나 많은 별이 있는지 모릅니다. 그래서 방금 (0 일 수도 있습니다) 라고 불렀습니다 . 알 수없는 는 우리가 그것과 사이의 관계를 찾으면 사라질 것 입니다.||ssq

그런 다음, 우리 는 이전의 별 주위에 새 카드를 산재하고 독립적으로 뒤의 별 주위에 남아있는 새 카드를 산재 한다고 가정합니다 . 있다jkj1|

τn,k(s,p)=((p1)+jj)((nps)+(kj)1kj1)

이것을하는 방법. 공지 사항,하지만 -이 분석의 가장 까다로운 부분은 -의 장소 것을 동일 인해를|p+s+j+1

  • 있다 "오래된"카드 또는 마크 전에.p
  • 거기 마크 후하지만 전에 오래된 카드 .s|
  • 마크 앞에 새로운 카드 가 있습니다 .j
  • 자체로 표시되는 새 카드가 있습니다.|

따라서 는 장소 에서 장소 로의 전환에 대한 정보를 제공합니다 . 우리는 모든 가능한 값에 대해 신중하게이 정보를 추적 할 때 , 그리고 합계 모든 (이산) 가능성을 통해 우리는 위의 조건부 확률을 구하는 위 아래의 ,τn,k(s,p)pq=p+s+j+1sqp

Prn,k(q|p)=(j(p1+jj)(n+kqkj1))/(n+kk)

여기서 합계는 에서 시작하고 에서 끝납니다 이 합계의 가변 길이는 특별한 경우를 제외하고 및 의 함수로 공식에 포함되지는 않습니다 .)j=max(0,q(n+1))j=min(k1,q(p+1)n,k,q,p

알고리즘

초기 확률이 존재 곳이 될 것이라고 확률 이 임의의 다른 가능한 값을 가질 것 . 이것은 벡터 로 나타낼 수 있습니다 .1102,3,,k1p1=(1,0,,0)

다음 카드를 산재한 후 벡터 은 왼쪽에있는 전이 행렬 을 곱하여 로 업데이트됩니다. . 모든 카드가 배치 될 때까지이 과정이 반복 됩니다. 각 단계 에서 확률 벡터 의 항목 합계는 일부 카드가 표시되었을 가능성입니다 . 따라서 값을 유지하기 위해 남은 것은 단계 후에 카드가 표시 되지 않을 가능성입니다k2p1p2(Prk1,k2(q|p),1pk1,1qk2)k1+k2++kmjpj1j. 따라서 이러한 값의 연속적인 차이는 표시 할 유형의 카드를 찾을 수없는 확률을 제공 합니다. 즉, 게임이 끝날 때 덱이 다 떨어질 때 찾고 있던 카드 값의 확률 분포입니다. .j


이행

다음 R코드는 알고리즘을 구현합니다. 앞에서 설명한 내용과 비슷합니다. 먼저, 전환 확률 계산은t.matrix 않고 정규화하지 않고 코드를 테스트 할 때 계산을 더 쉽게 추적 할 수 있습니다.(n+kk)

t.matrix <- function(q, p, n, k) {
  j <- max(0, q-(n+1)):min(k-1, q-(p+1))
  return (sum(choose(p-1+j,j) * choose(n+k-q, k-1-j))
}

transition 로 업데이트 하는 데 사용됩니다 . 전이 행렬을 계산하고 곱셈을 수행합니다. 또한 인수 가 빈 벡터 인 경우 초기 벡터 을 계산합니다 .pj1pjp1p

#
# `p` is the place distribution: p[i] is the chance the place is `i`.
#
transition <- function(p, k) {
  n <- length(p)
  if (n==0) {
    q <- c(1, rep(0, k-1))
  } else {
    #
    # Construct the transition matrix.
    #
    t.mat <- matrix(0, nrow=n, ncol=(n+k))
    #dimnames(t.mat) <- list(p=1:n, q=1:(n+k))
    for (i in 1:n) {
      t.mat[i, ] <- c(rep(0, i), sapply((i+1):(n+k), 
                                        function(q) t.matrix(q, i, n, k)))
    }
    #
    # Normalize and apply the transition matrix.
    #
    q <- as.vector(p %*% t.mat / choose(n+k, k))
  }
  names(q) <- 1:(n+k)
  return (q)
}

이제 모든 데크에 대해 각 단계에서 비 마크 확률을 쉽게 계산할 수 있습니다.

#
# `k` is an array giving the numbers of each card in order;
# e.g., k = rep(4, 13) for a standard deck.
#
# NB: the *complements* of the p-vectors are output.
#
game <- function(k) {
  p <- numeric(0)
  q <- sapply(k, function(i) 1 - sum(p <<- transition(p, i)))
  names(q) <- names(k)
  return (q)
}

다음은 표준 데크입니다.

k <- rep(4, 13)
names(k) <- c("A", 2:9, "T", "J", "Q", "K")
(g <- game(k))

출력은

         A          2          3          4          5          6          7          8          9          T          J          Q          K 
0.00000000 0.01428571 0.09232323 0.25595013 0.46786622 0.66819134 0.81821790 0.91160622 0.96146102 0.98479430 0.99452614 0.99818922 0.99944610

규칙에 따르면 왕이 표시되면 더 이상 카드를 찾지 않을 것입니다. 이는 의 값 을 로 늘려야 한다는 의미 입니다. 그렇게 할 때, 차이점은 "갑판이 다 떨어졌을 때의 숫자"의 분포를 나타냅니다.0.99944611

> g[13] <- 1; diff(g)
          2           3           4           5           6           7           8           9           T           J           Q           K 
0.014285714 0.078037518 0.163626897 0.211916093 0.200325120 0.150026562 0.093388313 0.049854807 0.023333275 0.009731843 0.003663077 0.001810781

(Monte-Carlo 시뮬레이션을 설명하는 별도의 답변으로 출력 한 보고서와 비교해보십시오. 예상되는 임의의 변동량까지 동일한 것으로 보입니다.)

예상 값은 즉각적입니다.

> sum(diff(g) * 2:13)
[1] 5.832589

모두들, 이것은 12 줄 정도의 실행 코드 만 필요했습니다. 나는 작은 값 (최대 ) 에 대한 손 계산과 비교하여 확인했습니다 . 따라서 코드와 문제의 이전 분석간에 불일치가 발생 하면 분석에 인쇄상의 오류가있을 수 있으므로 코드를 신뢰하십시오 .k3


비고

다른 서열과의 관계

각 카드 중 하나가있을 때 분포는 정수의 역수 순서입니다.

> 1/diff(game(rep(1,10)))
[1]      2      3      8     30    144    840   5760  45360 403200

장소 의 가치 는( 에서 시작 ). 이다 순서 A001048 정수 시퀀스의 온라인 백과 사전이다. 따라서 우리는 이 시퀀스를 일반화 할 상수 ( "적합한"데크)를 가진 데크에 대해 닫힌 공식을 원할 수 있습니다. (예를 들어, 순열 그룹에서 가장 큰 결합 클래스의 크기를 계산하고 삼항 계수 와도 관련이 있습니다 .) (안타깝게도 에 대한 일반화의 역수는 일반적으로 정수가 아닙니다.)ii!+(i1)!i=1kik>1

확률 적 프로세스로서의 게임

우리의 분석은 벡터 , 의 초기 계수 가 일정 하다는 것을 분명히합니다 . 예를 들어, 각 카드 그룹을 처리 할 때 출력을 추적 해 보겠습니다 .ipjjigame

> sapply(1:13, function(i) game(rep(4,i)))

[[1]]
[1] 0

[[2]]
[1] 0.00000000 0.01428571

[[3]]
[1] 0.00000000 0.01428571 0.09232323

[[4]]
[1] 0.00000000 0.01428571 0.09232323 0.25595013

...

[[13]]
 [1] 0.00000000 0.01428571 0.09232323 0.25595013 0.46786622 0.66819134 0.81821790 0.91160622 0.96146102 0.98479430 0.99452614 0.99818922 0.99944610

예를 들어, 최종 벡터 의 두 번째 값 (총 52 장의 카드로 결과를 설명 함)은 두 번째 그룹이 처리 된 후 이미 나타 났으며 과 같습니다 . 따라서 카드 값을 통해 마크 업에 대한 정보 만 원하는 경우 카드 의 데크에 계산을 수행하면됩니다 .1/(84)=1/70jthk1+k2++kj

가치의 카드를 표시하지 가능성 때문에 신속하게 가까운지고 로 증가, 이후 사 정장 카드의 종류 우리는 거의 기대에 대한 한계 값에 도달했습니다. 실제로, 제한 값은 약 ( 카드 의 데크에 대해 계산 됨 ,이 시점에서 배정도 반올림 오류로 인해 더 이상 진행되지 않음).j1j135.8333554×32

타이밍

-vector 적용된 알고리즘을 살펴보면 타이밍이 비례해야 하고 조잡한 상한을 사용하여 비례하는 것보다 나쁘지 않아야합니다. . ~ 및 ~ 대한 모든 계산의 타이밍을 정하고 상대적으로 오랜 시간 ( 초 이상)이 걸리는 계산 만 분석함으로써 계산 시간은 대략 ,이 상한 평가를 지원합니다.( K , K는 , ... , k는 ) k는 2 m 3 (K) = 1 (7) N = 10 30 1 / 2 O ( K 2 N 2.9 )m(k,k,,k)k2m3k=17n=10301/2O(k2n2.9)

이러한 무증상의 한 가지 용도는 더 큰 문제에 대한 계산 시간을 계획하는 것입니다. 예를 들어, 의 경우 약 초가 걸리고 , (매우 흥미로운) 경우 경우 약 초 (실제로 초가 걸립니다 .)1.31 K = 1 , N = 100 1.31 ( 1 / 4 ) (2) ( 100 / 30 ) 2.92.7 2.87k=4,n=301.31k=1,n=1001.31(1/4)2(100/30)2.92.72.87


0

Perl에서 간단한 Monte Carlo를 해킹하여 약 발견 .5.8329

#!/usr/bin/perl

use strict;

my @deck = (1..13) x 4;

my $N = 100000; # Monte Carlo iterations.

my $mean = 0;

for (my $i = 1; $i <= $N; $i++) {
    my @d = @deck;
    fisher_yates_shuffle(\@d);
    my $last = 0;
        foreach my $c (@d) {
        if ($c == $last + 1) { $last = $c }
    }
    $mean += ($last + 1) / $N;
}

print $mean, "\n";

sub fisher_yates_shuffle {
    my $array = shift;
        my $i = @$array;
        while (--$i) {
        my $j = int rand($i + 1);
        @$array[$i, $j] = @$array[$j, $i];
    }
}

이 시뮬레이션과 이론적 (정확한) 시뮬레이션을 포함하여 이전 답변과 이전 답변 사이 의 날카로운 불일치가 주어지면 질문을 다른 방식으로 해석하고 있다고 생각합니다. 귀하의 설명이 없으면 잘못 설명해야합니다. (나는 당신이 4.8을 5.83258과 비교해야한다고 생각하지만, 두 자리의 정밀도는이 문제에 대한 추가적인 통찰력을 제공하지 않습니다.)
whuber

1
네! 일대일 실수가있었습니다.
Zen
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.