在每侧出现3次之前,必须掷骰子的预期次数是多少?
这个问题是在新西兰的小学提出的,并通过模拟解决了。该问题的解析解决方案是什么?
在每侧出现3次之前,必须掷骰子的预期次数是多少?
这个问题是在新西兰的小学提出的,并通过模拟解决了。该问题的解析解决方案是什么?
Answers:
假设所有边都有相等的机会。让我们归纳并找到所需的预期滚动数,直到第面出现次,第面出现次,...,而面出现次。由于双方的身份无关紧要(他们都有平等的机会),因此可以简化此目标的描述:让我们假设双方根本不需要出现,双方只需出现一次,...和的侧面必须出现次。让1 n 1 2 n 2 d n d i 0 i 1 i n n = max (n 1,n 2,… ,n d)i = (i 0,i 1,… ,i n)
容易复发。 在下一卷中,出现的一面对应于i_j中的一个:即,我们不需要看到它,或者我们需要看到一次,...,或者我们需要看到次以上。是我们需要看到它的次数。
当,我们不需要看到它,并且没有任何变化。这发生的概率为。
当我们确实需要看到这一面。现在,有少一侧需要看到次,而另一侧需要看到次。因此,变为而变为。让对的组件的此操作指定为,这样Ĵ Ĵ - 1 我Ĵ 我Ĵ - 1 我Ĵ - 1我Ĵ + 1 我我 ⋅ Ĵ
这以概率。
我们只需要计算该掷骰数并使用递归告诉我们预计还会有多少掷骰子。 根据期望和总概率定律,
(让我们知道,每当,总和中的对应项为零。)
如果,则完成,并且。否则,我们可以求解,给出所需的递归公式e (i)= 0 e (i)
注意是我们希望看到的事件总数。如果,则对于任何,操作将其数量减少1 ,这种情况总是如此。因此,此递归在精确于的深度处终止。(等于问题中的)。此外,(不难检查)此问题中每个递归深度的可能性很小(从不超过)。因此,这是一种有效的方法,至少在组合可能性不是太多且我们记住中间结果的情况下(因此值⋅ Ĵ Ĵ > 0 我Ĵ > 0 | 我| 3 (6 )= 18 8 e
我计算出
对我来说,这似乎太小了,所以我进行了一个模拟(使用R
)。经过三百万次掷骰子后,此游戏已完成超过100,000次,平均长度为。该估计值的标准误差为:该平均值与理论值之间的差异不明显,从而确认了理论值的准确性。0.027
长度的分布可能是令人感兴趣的。(显然,它必须从开始,这是收集所有六面每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))
尽管的递归计算很简单,但在某些计算环境中仍存在一些挑战。其中最主要的是在计算的值时将其存储。这是必不可少的,因为否则将(冗余)计算每个值很多次。但是,用索引的数组潜在需要的存储空间可能很大。理想情况下,仅应存储在计算过程中实际遇到的值。这需要一种关联数组。È (我)我我
为了说明,这是工作R
代码。这些注释描述了用于存储中间结果的简单“ AA”(关联数组)类的创建。向量被转换为字符串,并且被用于索引包含所有值的列表。的操作被实现为。我 ⋅ ĴE
%.%
这些预备信息使递归函数定义相当简单,且与数学符号类似。特别是线
x <- (d + sum(sapply(1:n, function(i) j[i+1]*e.(j %.% i))))/(d - j[1])
与上述公式直接可比。注意,所有索引都增加了因为它开始以而不是索引其数组。1 1 0R
时间显示计算需要秒; 它的价值是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次之前需要多少卷
当然,这是一个没有答案的问题,正如@JuhoKokkala上面评论的那样:答案是一个随机变量,需要找到分布。然后将问题修改为询问:“预期的卷数是多少”。以下答案旨在回答最初提出的问题:如何在不使用模拟的情况下找到卷数的分布,而仅使用概念上简单的技术,任何拥有计算机的新西兰学生都可以实现为什么不这样做?问题减少到1班轮。
分配所需的卷筒数量...使得每侧出现3次
我们掷骰子次。令表示骰子的第面出现的次数,其中。然后,的联合pmf 是即:X 我我我∈ { 1 ,... ,6 } (X 1,X 2,... ,X 6)多项式(Ñ ,1
令:那么的cdf 是:
即要找到cdf,只需为每个值计算:
例如,这里是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相差:
当然,分布没有上限,但是我们可以在此处轻松解决实际需要的所有值。该方法是通用的,并且对于所需的任何所需的侧面组合也应同样有效。