我是 R 的新手,我正在练习骰子模拟。我喜欢的游戏使用六面骰子,每个骰子的结果都有一定的成功次数。
成功的结果
1: 0
2: 0
3: 0
4: 1
5: 2
6:2,再掷一个骰子(这可以无限期地继续)
我希望能够掷出多个骰子 (x),将它们的实际值替换为生成的成功次数(见上文)打印每个掷骰子的结果,然后打印掷骰子的总和总计成功。
我正在尝试为这些掷骰子编写一个模拟器,但我被困在多种方式中。
我的循环似乎没有准确地影响样本,所以指出正确的方法会很有帮助。到目前为止,我已经尝试用尽可能多的方式迭代它并在谷歌上进行了检查,但我能找到的所有替换信息都涉及矩阵和/或数据框。
完成后,我不知道如何有条件地向随机生成的样本添加另一个交互(在这种情况下,对于 6 的每个结果,卷数 (x) 应该增加 +1)代码中目前没有任何内容因为我不知道从哪里开始。
这是我目前所知道的,我确信这是非常错误的,所以感谢您的耐心等待。
x <- 10
roll <- sample(1:6, x, replace = TRUE)
for (i in 1:6) {
if (i <= 3) {
i <- 0
} else if (i == 4) {
i <- 1
} else if (i == 5) {
i <- 2
} else if (i == 6) {
i <- 2
}
}
print(roll)
sum(roll)
目前循环似乎完全被忽略,样本只是正常生成。
我会像这样使用递归来模拟:
# roll(n) rolls n dice
roll = function(n) {
# each roll has a
# 1/2 probability of 0 successes,
# 1/6 chance of 1 success
# 1/3 chance of 2 successes
result = sample(
0:2, size = n,
prob = c(3, 1, 2), replace = TRUE
)
# we count the 2s in the result
n_2 = sum(result == 2)
# each 2 has a 1/2 chance of prompting additional rolls
n_additional = sum(runif(n_2) > 0.5)
if(n_additional > 0) {
# if more rolls are needed, we call this function again
# and append the result
result = c(result, roll(n = n_additional))
}
# return results of all the rolls
result
}
## some demonstration (seed set for reproducibility)
set.seed(47)
roll(3)
# [1] 1 0 2 2 0
roll(10)
# [1] 0 2 1 0 2 0 2 2 1 0
length(roll(100))
# [1] 130
## in this instance, rolling 100 dice resulted in a 130 total rolls...
## more than expected, but well within reason
## we could roll 100 dice 100 times and look at how many
## total rolls each instance had:
r100 = replicate(n = 100, length(roll(100)))
summary(r100)
# Min. 1st Qu. Median Mean 3rd Qu. Max.
# 110.0 116.0 119.0 119.6 123.0 130.0
## or similarly look at the number of successes in
## each of 100 simulations of rolling 100 dice
success100 = replicate(n = 100, sum(roll(100)))
summary(success100)
# Min. 1st Qu. Median Mean 3rd Qu. Max.
# 74.00 91.75 101.00 100.65 109.00 127.00
## or look at 100 simulations of rolling 5 dice
success5 = replicate(100, sum(roll(5)))
barplot(table(success5), main = "Successes when rolling 5 dice")
当然,如果你只是想要
sum
,你可以sum()
roll
的结果(或者将函数的最后一行替换为sum(result)
直接返回成功的次数)。
这被称为递归,因为函数
roll()
,在某些情况下(当需要更多骰子时)会调用自己。
这是一个不错的第一次尝试,但你是对的,有几处错误。
从 1 到 6 的循环根本不与
roll
接合。你可能想做这样的事情:
x <- 10
roll <- sample(1:6, x, replace = TRUE)
score <- numeric(x)
for (i in 1:x) {
if (roll[i] <= 3) {
score[i] <- 0
} else if (roll[i] == 4) {
score[i] <- 1
} else if (roll[i] == 5) {
score[i] <- 2
} else if (roll[i] == 6) {
score[i] <- 2
}
}
print(roll)
sum(score)
如果你不需要在 6 上重新滚动,那是可行的,但是你使用的
if
流量控制比你真正需要的多。我会将每一行的“结果”存储在一个 6 元素向量中,然后根据掷骰选择相关结果。您将使用 while
循环实现有条件的重新滚动:基本上,如果您滚动 6,则重新滚动(如果您再次滚动 6,再次滚动直到您停止滚动 6):
number_of_simulations <- 1000
outcomes <- c(0, 0, 0, 1, 2, 2)
scores <- numeric(number_of_simulations)
rolls <- vector('list', number_of_simulations)
for (i in seq_len(number_of_simulations)) {
roll <- sample(6, size = 1)
scores[i] <- outcomes[roll]
rolls[[i]] <- roll
while (roll == 6) {
roll <- sample(6, size = 1)
scores[i] <- scores[i] + outcomes[roll]
rolls[[i]] <- append(rolls[[i]], roll)
}
}
n_rolls <- sapply(rolls, length)
@gregor-thomas 使用递归提供了一个很好的解决方案,您也可以学习它以了解更多关于 R 的强大功能。我希望我的解决方案也有帮助!