给定一个随机的int生成器[0-5],生成[0-7]

时间:2019-05-16 12:52:05

标签: algorithm

所以这是一个面试问题。

为您提供了一个函数rand5(),该函数生成范围为[0-5]的随机整数,即{0,1,2,3,4,5}

a)您可以使用该函数生成范围为[0-7]的随机整数吗?

b)您可以使用该函数生成范围为[0-7]的随机整数,每个数字具有相等的概率吗?

您可以多次使用该功能。

a部分((rand5() +rand5())*7)//10的一种解决方案,其中// represents integer division的范围为[0-7],但是概率不相等。

很乐意看到您对此的答案和思考过程。

4 个答案:

答案 0 :(得分:5)

    $one  = rand5();
    $two  = rand5();
    $four = rand5();

    return (($four < 3)? 4 : 0)  +  (($two < 3)? 2 : 0)  +  ($one < 3)? 1 : 0);

答案 1 :(得分:2)

尝试这种方法:

  • rand5()产生概率在 0-5 之间的随机数。另外, rand5()返回的三个数字( 0、2、4 )是偶数,其他三个( 1、3、5 )是奇数。因此,它以相等的概率产生偶数和奇数。
  • 如果 rand7()返回具有相等概率的所有数字,则 rand7() 6 的概率应为 1 / 8 rand5()返回偶数三次的概率也为 1/8

因此 rand7()可以是:

// returns random number between 0-5 with equal probability
function rand5() {
  return Math.floor(Math.random() * 6);
}

// returns random number between 0-7 with equal probability
function rand7() {
  if(rand5() % 2 == 0 && rand5() % 2 == 0) { 
    return 6 + rand5() % 2;
  } else {
    return rand5();
  }
}

console.log(rand7());

答案 2 :(得分:0)

骰子有相等的机会掷出任何一面。如果所需的范围小于骰子的范围,只需在超出范围时重新滚动即可。

当所需范围大于一个芯片的范围时,就会出现问题。多个骰子掷骰的总和不是正态分布的,因此增加多个掷骰子的值是行不通的。

相反,请考虑使用连续滚动来逐步“放大”子范围内的值。如果我们滚动一个6面的模具两次,则第一次滚动将选择一个6个单位的子范围,例如12-17(包括12-17)。第二轮将从该子范围中选择一个值,例如14。

同样,与单个骰子一样,如果范围大于期望值,则只需拒绝超出范围的值,然后再次滚动。

答案 3 :(得分:0)

这可以使用Rejection Sampling完成。
考虑将卷布置在如下所示的2D网格中

[0, 1, 2, 3, 4, 5]
[0, 1, 2, 3, 4, 5]
[0, 1, 2, 3, 4, 5]
[0, 1, 2, 3, 4, 5]
[0, 1, 2, 3, 4, 5]
[0, 1, 2, 3, 4, 5]

现在,如果您滚动模具两次,则可以在2D网格中生成任何位置(第一行表示行位置,第二行表示列位置)。共有36个职位。由于我们要生成[0, 7]范围内的数字,因此我们需要输出空间为8的倍数。如果我们考虑第一个32位置(按主要顺序排列),我们可以将它们分成4个索引组。例如

[0, 1, 2, 3] in first row => 0
[4, 5, 0, 1] in first and second row => 1
[2, 3, 4, 5] in second row => 2
...
[4, 5, 0, 1] in fifth and sixth row => 7

如果我们滚动最后4个位置,我们将再次滚动。

int rand7() {
    while(true) {
        int row = rand(5);
        int col = rand(5);
        int pos = row * 6 + col;
        if(pos < 32) {
            return pos/4;
        }
    }
}