【问题标题】:How to use a while() loop within a for() loop in R如何在 R 的 for() 循环中使用 while() 循环
【发布时间】:2014-11-01 01:31:01
【问题描述】:

我是 R 新手,所以我的大部分代码很可能是错误的。但是,我想知道如何在 for() 循环中使用 while() 循环。如果总数为 2、3、7、11 或 12,我正在尝试多次模拟掷骰子,然后我停止。如果总数为 4、5、6、8、9 或 10,那么我将继续掷骰子,直到出现初始总数或 7。我试图找出结束游戏所需的平均掷骰数

count = 0
x = NULL
for (i in 1:10) {
  x[i] = c(sample(1:6,1) +sample(1:6,1))
  if(x[i] == c(2||3||7||11||12)) {
    if(TRUE) {count = count +1}
  } else { while(x[i] == c(4||5||6||8||9||10)) {
    x[i +1] = c(sample(1:6,1)+sample(1:6,1))
    if(x[i+1] == c(x[i]||7)) {
      if(TRUE){count = count + x[i+1]}
    }
  }
  }
}
print(count)

【问题讨论】:

  • 您的主要问题是您应该使用x[i] %in% c(2,3,7,11,12) 而不是|| 运算符( x[i]==2 || x[i]==3 || ...
  • 令我惊讶的是你选择的数字。如果第一组数字是1、2、3、4、5、6,另一组数字是7、8、9、10、11、12,第二组“逃脱”,游戏会不会更简单将是初始数字或 1?概率保持不变......
  • 你在这里得到了一组很好的比较答案...
  • 这款骰子游戏非常有趣。你怎么能抗拒。我希望会有更多的答案。
  • 请在发布之前对您的代码进行一些基本检查。 c(2||3||7||11||12) 返回TRUE

标签: r for-loop while-loop


【解决方案1】:

我认为您的逻辑存在一些问题。我不太确定你想在你的代码中做什么,但这是我对你的问题的描述的解释......这只运行你的游戏的一轮 - 它如果你将它嵌入到for 循环中应该可以工作(只是不要重置count 或重置循环中的随机数种子——然后count 会给你滚动的总数,你可以除以轮数得到平均值)

设置:

count = 0
sscore <- c(2,3,7,11,12)
set.seed(101)
debug = TRUE

运行单轮:

x = sample(1:6,1) +sample(1:6,1)  ## initial roll
count = count + 1
if (x %in% sscore) {
    ## don't need to do anything if we hit,
    ## as the roll has already been counted
    if (debug) cat("hit",x[i],"\n")  
} else {
    ## initialize while loop -- try one more time
    y = c(sample(1:6,1)+sample(1:6,1))
    count = count + 1
    if (debug) cat("initial",x,"next",y,"\n")
    while(!(y %in% c(x,7))) {
        y = c(sample(1:6,1)+sample(1:6,1))
        count = count+1
        if (debug) cat("keep trying",y,"\n")

    }  ## end while
}  ## end if-not-hit
print(count)

我尝试将其嵌入到 for 循环中,1000 轮的平均值为 3.453,接近 @PawelP 的答案。

PS 我希望这不是作业,因为我不想回答作业问题...

【讨论】:

  • 虽然代码很好,但为了 OP,我会指出精确值的公式远非正确。滚动数字的概率因数字而异。此外,“滚动初始值或 7”阶段的计算并非易事(请记住非均匀概率,并且 7 可能是初始滚动)。我现在没有时间提供正确的公式,但它肯定更复杂(很多乘法、加法、除法......)
【解决方案2】:

编辑:我有一个错误 - 忘记删除 if 否定。现在,以下内容似乎 100% 符合您对问题的描述。

这是我对你所描述的游戏的实现。它会计算在TOTAL_GAMES 多场比赛中结束游戏所需的平均掷骰数。

TOTAL_GAMES = 1000
counts = rep(0, TOTAL_GAMES)
x = NULL
for (i in 1:TOTAL_GAMES) {
    x_start = c(sample(1:6,1) +sample(1:6,1))
    counts[i] = counts[i] + 1
    x = x_start
    if(x %in% c(2, 3, 7, 11, 12)){
       next
    }

    repeat {
        x = c(sample(1:6,1)+sample(1:6,1))
            counts[i] = counts[i] + 1
        if(x %in% c(x_start, 7)){
            break
        }
    }
}

print(mean(counts))

似乎平均滚动数在 3.38 左右

【讨论】:

  • 不错的解决方案,虽然我认为使用nextrepeat/break 在流量(如果紧凑)方面比我的解决方案更令人困惑......跨度>
【解决方案3】:

这是解决这个问题的一种方法 - 我创建了一个运行单个试验的函数,以及另一个执行可变数量的这些试验并返回累积平均值的函数。

## Single trial
rollDice <- function(){
  init <- sample(1:6,1)+sample(1:6,1)
  rolls <- 1
  if( init %in% c(2,3,7,11,12) ){
    return(1)
  } else {
    Flag <- TRUE
    while( Flag ){
      roll <- sample(1:6,1)+sample(1:6,1)
      rolls <- rolls + 1
      if( roll %in% c(init,7) ){
        Flag <- FALSE
      }
      rolls
    }
  }
  return(rolls)
}
## Multiple trials
simAvg <- function(nsim = 100){
  x <- replicate(nsim,rollDice())
  Reduce("+",x)/nsim
}
##
## Testing 
nTrial <- seq(1,1000,25)
Results <- sapply(nTrial, function(X){ simAvg(X) })
##
## Plot over varying number of simulations
plot(x=nTrial,y=Results,pch=20)

正如@Ben Bolker 所指出的,|| 有几个语法错误,这对于 R 新手来说是可以理解的。此外,您可能会听到一千次,但 for 和 @987654325 @ 循环在 R 中效率很低,因此您通常希望尽可能避免使用它们。对于上述rollDice() 函数中的while 循环,这可能没什么大不了的,因为循环执行大量次数的概率非常低。我使用函数Reducereplicate 在第二个函数中充当for 循环的角色。不过,这是个好问题,工作很有趣。

【讨论】:

  • 我认为你对游戏描述的理解有些许误解。 OP 说要重新滚动“直到最初的总数出现或 7”,并且他们的(有点混淆)代码似乎同意这种解释(if(x[i+1] == c(x[i]||7)) ,应该是if ([next roll] %in% c([initial roll],7))
  • 哦,你是对的 - 谢谢你指出这一点,我会编辑函数。
猜你喜欢
  • 2011-05-11
  • 1970-01-01
  • 2023-03-02
  • 1970-01-01
  • 2017-04-30
  • 2021-06-29
  • 2019-01-13
  • 2021-07-27
  • 2020-05-15
相关资源
最近更新 更多