使用骰子

时间:2015-11-29 10:26:50

标签: algorithm probability puzzle discrete-mathematics

我一直在想这个但似乎无法弄明白。我需要选择1到50(包括)之间的随机整数,使得它中的每个整数都具有相同的可能性。我将不得不使用8面骰子和15面骰子。

我读过与骰子随机数发生器有关的类似问题,但我仍感到困惑。我认为这是将数字分成几组的界限。然后,我会掷骰子,然后,根据结果,决定再次掷骰子。

有人可以帮我这个吗?

3 个答案:

答案 0 :(得分:1)

作为一个简单的 - 不一定是“最佳”解决方案,滚动8面模具,然后是15面:

8 sided   15 sided   1..50 result
1 or 2    1..15      1..15
3 or 4    1..15      16..30 (add 15 to 15-sided roll)
5 or 6    1..15      31..45 (add 30 to 15-sided roll)
7 or 8    1..5       46..50 (add 45 to 15-sided roll)
7 or 8    6..15      start again / reroll both dice

答案 1 :(得分:1)

假设你有两个函数:d8(),它返回一个从0到7的数字,d15(),它返回一个从0到14的数字。你想写一个{{1}返回0到49之间的数字。

在所有简单的方法中,对于你需要掷多少骰子来说,这个方法可能效率最高,这样的东西对于你拥有的骰子和你想要的骰子都适用:

d50()

如果你想要非常恒定的时间,你可以这样做:

int d50()
{
   int result;
   do
   {
       result = d8()*8+d8(); //random from 0 to 63
   } while(result >=50);
   return result;
}

这种方式组合骰子直到可能性数量(1800)可被50整除,因此相同数量的可能性对应于每个结果。这种方法在这种情况下运行正常,但是如果您拥有的骰子的素数因素(在这种情况下为2,3和5)不起作用,则不能覆盖您想要的骰子因素(2,5)< / p>

答案 2 :(得分:0)

我认为您可以将每个骰子结果视为更大间隔的细分。所以扔掉一个8面骰子,你可以在8个主要区间中选择一个除以你的价值范围。投掷15个骰子意味着从15个子区间中选择一个,依此类推。 考虑到15 = 3 * 5,8 = 2 * 2 * 2和50 = 2 * 5 * 5你可以选择36 = 3 * 3 * 2 * 2作为50的方便倍数,以便:

15 * 15 * 8 = 50 * 36 = 1800

您甚至可以考虑在基数15中表示0到1799之间的数字,并选择ramdomly这三个数字:

选择= [0-7] * 15 ^ 2 + [0-14] * 15 ^ 1 + [0-14] * 15 ^ 0

所以我的建议,测试分布,是(用c ++语言):

#include <iostream>
#include <random>
#include <map>

int main() {
    std::map<int, int> hist;
    int result;

    std::random_device rd;
    std::mt19937 gen(rd());    // initialiaze the random generator
    std::uniform_int_distribution<> d8(0, 7);     // istantiate the dices
    std::uniform_int_distribution<> d15(0, 14);

    for (int i = 0; i < 20000; ++i) {      // make a lot of throws...
        result = d8(gen) * 225;
        result += d15(gen) * 15;           // add to result
        result += d15(gen);
        ++hist[ result / 36 + 1];          // count each result 
    }
    for (auto p : hist) {                  // show the occurences of each result
       std::cout << p.first << " : " << p.second << '\n';
    }
    return 0;
}

输出应该是这样的:

1 : 387
2 : 360
3 : 377
4 : 393
5 : 402
...
48 : 379
49 : 378
50 : 420