如何使用示例命令有条件地向示例添加附加数字?

问题描述 投票:0回答:2

我是 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)

目前循环似乎完全被忽略,样本只是正常生成。

r replace sampling
2个回答
0
投票

我会像这样使用递归来模拟:

# 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()
,在某些情况下(当需要更多骰子时)会调用自己。


0
投票

这是一个不错的第一次尝试,但你是对的,有几处错误。

从 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 的强大功能。我希望我的解决方案也有帮助!

© www.soinside.com 2019 - 2024. All rights reserved.