각면이 3 번 나타날 때까지 주사위를 굴려야하는 예상 횟수는 얼마입니까?
이 질문은 뉴질랜드의 초등학교에서 요청되었으며 시뮬레이션을 사용하여 해결되었습니다. 이 문제에 대한 분석 솔루션은 무엇입니까?
각면이 3 번 나타날 때까지 주사위를 굴려야하는 예상 횟수는 얼마입니까?
이 질문은 뉴질랜드의 초등학교에서 요청되었으며 시뮬레이션을 사용하여 해결되었습니다. 이 문제에 대한 분석 솔루션은 무엇입니까?
답변:
모든 변의 기회가 같다고 가정합니다 . 1 면 이 n 1 번 나타날 때까지 , 2 면 이 n 2 번 나타날 때까지 , 그리고 d 면 이 n d 번 나타날 때까지 필요한 롤 수를 일반화하고 찾으십시오 . 측면의 정체성 문제가되지 않기 때문에,이 목표의 설명이 응축 될 수있다 (그들은 모두 동등한 기회가) : 우리가 있다고 가정하자 내가 0 양쪽 모두에 표시하지 않아도, 내가 한 변의를 표시해야합니다 한 번만 ..., 그리고 난 n변의 번 나타나야 합니다. 하자 난 = ( I 0 , i가 1 , ... , i가 N ) ,이 상황과 기입 지정 E ( I ) 롤의 예상 된 수를 들어. 질문은 e ( 0 , 0 , 0 , 6 )를 요청합니다 . i 3 =
쉬운 재발이 가능합니다. 다음 롤 중 하나와 일치 나타나는 측면에서 :이며, 하나 우리는 그것을 볼 필요하지 않았거나 우리는 ... 한 번 볼 필요가 또는 우리는 그것을 볼 필요 N 더 타임스. j 는 우리가 그것을 보는 데 필요한 횟수입니다.
일 때 , 우리는 그것을 볼 필요가 없었으며 아무것도 변하지 않았습니다. 이것은 확률 i 0 / d에서 발생 합니다.
때 이면 을 볼 필요가있었습니다. 이제 j 배 를 볼 필요가있는 한 쪽 과 j - 1 회를 볼 수있는 쪽이 하나 더 있습니다 . 따라서 i j 는 i j - 1이 되고 i j - 1 은 i j + 1이 됩니다. i 의 구성 요소에 대한이 작업을 i ⋅ j 로 지정 하여
이 확률로 발생 .
우리는 단지이 다이 롤을 세고 재귀를 사용하여 얼마나 많은 롤이 예상되는지 알려 주면됩니다. 기대 법칙과 총 확률에 의해
( 일 때 합계의 해당 항은 0이라는 것을 이해 하십시오.)
경우 , 우리는 완료하고 E ( I ) = 0 . 그렇지 않으면 우리는 원하는 재귀 공식을 제공하여 e ( i )를 풀 수 있습니다.
공지 사항이 은보고자하는 총 이벤트 수입니다. ⋅ j 연산 은 i j > 0 이면 j > 0에 대해 수량을 1 씩 줄입니다 ( 항상 그렇습니다). 따라서이 재귀는 정확하게 | 나는 | (동일한 행 3 ( 6 ) =
나는
그것은 나에게 아주 작게 보였으므로 시뮬레이션을 사용했다 R
. 3 백만 롤 이상의 주사위를 굴린 후이 게임은 평균 길이 100,000 회 이상 완료되었습니다 . 이 추정치의 표준 오차는 0.027입니다 .이 평균과 이론 값의 차이는 중요하지 않으므로 이론 값의 정확성을 확인합니다.
길이 분포에 관심이있을 수 있습니다. (반드시 부터 시작해야합니다 . 최소 6 개의 롤을 각각 3 번씩 모아야합니다.)
# Specify the problem
d <- 6 # Number of faces
k <- 3 # Number of times to see each
N <- 3.26772e6 # Number of rolls
# Simulate many rolls
set.seed(17)
x <- sample(1:d, N, replace=TRUE)
# Use these rolls to play the game repeatedly.
totals <- sapply(1:d, function(i) cumsum(x==i))
n <- 0
base <- rep(0, d)
i.last <- 0
n.list <- list()
for (i in 1:N) {
if (min(totals[i, ] - base) >= k) {
base <- totals[i, ]
n <- n+1
n.list[[n]] <- i - i.last
i.last <- i
}
}
# Summarize the results
sim <- unlist(n.list)
mean(sim)
sd(sim) / sqrt(length(sim))
length(sim)
hist(sim, main="Simulation results", xlab="Number of rolls", freq=FALSE, breaks=0:max(sim))
의 재귀 계산 은 간단 하지만 일부 컴퓨팅 환경에서는 몇 가지 문제가 있습니다. 이들 중 가장 중요한 것은 e ( i ) 값을 계산할 때 저장하는 것입니다 . 그렇지 않으면 각 값이 (중복 적으로) 매우 많은 횟수로 계산되므로 필수적입니다. 그러나 i 가 색인을 생성 한 어레이에 잠재적으로 필요한 스토리지 는 막대 할 수 있습니다. 이상적으로 계산 중에 실제로 발생하는 i 값만 저장해야합니다. 이것은 일종의 연관 배열을 요구합니다.
설명을 위해 여기에 작업 R
코드가 있습니다. 주석은 중간 결과를 저장하기위한 간단한 "AA"(연관 배열) 클래스 작성을 설명합니다. 벡터 는 문자열로 변환되며 모든 값을 보유 하는 목록으로 색인하는 데 사용 됩니다. I ⋅ J의 동작으로 구현된다 .E
%.%
이러한 예비를 통해 재귀 함수 를 수학 표기법과 비슷한 방식으로 간단하게 정의 할 수 있습니다. 특히, 라인
x <- (d + sum(sapply(1:n, function(i) j[i+1]*e.(j %.% i))))/(d - j[1])
는 상기 식 과 직접 비교된다 . 배열의 인덱스를 0이 아닌 1 부터 시작 하기 때문에 모든 인덱스가 1 씩 증가했습니다 .R
타이밍은 계산 하는데 초가 걸린다는 것을 보여줍니다 ; 그 가치는e(c(0,0,0,6))
32.6771634160506
누적 부동 소수점 반올림 오류로 인해 마지막 두 자리가 68
아닌 숫자가 손상되었습니다 06
.
e <- function(i) {
#
# Create a data structure to "memoize" the values.
#
`[[<-.AA` <- function(x, i, value) {
class(x) <- NULL
x[[paste(i, collapse=",")]] <- value
class(x) <- "AA"
x
}
`[[.AA` <- function(x, i) {
class(x) <- NULL
x[[paste(i, collapse=",")]]
}
E <- list()
class(E) <- "AA"
#
# Define the "." operation.
#
`%.%` <- function(i, j) {
i[j+1] <- i[j+1]-1
i[j] <- i[j] + 1
return(i)
}
#
# Define a recursive version of this function.
#
e. <- function(j) {
#
# Detect initial conditions and return initial values.
#
if (min(j) < 0 || sum(j[-1])==0) return(0)
#
# Look up the value (if it has already been computed).
#
x <- E[[j]]
if (!is.null(x)) return(x)
#
# Compute the value (for the first and only time).
#
d <- sum(j)
n <- length(j) - 1
x <- (d + sum(sapply(1:n, function(i) j[i+1]*e.(j %.% i))))/(d - j[1])
#
# Store the value for later re-use.
#
E[[j]] <<- x
return(x)
}
#
# Do the calculation.
#
e.(i)
}
e(c(0,0,0,6))
마지막으로 정확한 답변을 제공 한 원래 Mathematica 구현이 있습니다. 메모는 관용적 표현을 통해 이루어지며 e[i_] := e[i] = ...
거의 모든 R
예비를 제거합니다 . 그러나 내부적으로 두 프로그램은 같은 방식으로 같은 일을하고 있습니다.
shift[j_, x_List] /; Length[x] >= j >= 2 := Module[{i = x},
i[[j - 1]] = i[[j - 1]] + 1;
i[[j]] = i[[j]] - 1;
i];
e[i_] := e[i] = With[{i0 = First@i, d = Plus @@ i},
(d + Sum[If[i[[k]] > 0, i[[k]] e[shift[k, i]], 0], {k, 2, Length[i]}])/(d - i0)];
e[{x_, y__}] /; Plus[y] == 0 := e[{x, y}] = 0
e[{0, 0, 0, 6}]
이 질문의 원래 버전은 다음과 같은 질문으로 시작되었습니다.
각면이 3 번 나타날 때까지 필요한 롤 수
각 롤이 3 번 나타나도록 필요한 롤 수 분포 ...
i.e.:
Let: Then the cdf of is:
i.e. To find the cdf , simply calculate for each value of :
예를 들어, Mathematica 코드는 다음과 같습니다. 18에서 60으로 증가합니다. 기본적으로 하나의 라이너입니다.
cdf = ParallelTable[
Probability[x1 >= 3 && x2 >= 3 && x3 >= 3 && x4 >= 3 && x5 >= 3 && x6 >= 3,
{x1, x2, x3, x4, x5, x6} \[Distributed] MultinomialDistribution[n, Table[1/6, 6]]],
{n, 18, 60}]
... 정확한 cdf를 증가합니다 :
다음은 cdf의 도표입니다 의 함수로서 :
pmf를 도출하려면 , 단순히 cdf를 먼저 차이점 :
물론 분포에는 상한이 없지만 실제로 필요한만큼의 값으로 쉽게 해결할 수 있습니다. 이 접근법은 일반적이며 필요한 측면 조합에 대해서도 잘 작동해야합니다.