【问题标题】:A C++ question about dice probability calculation一个关于骰子概率计算的C++问题
【发布时间】:2020-02-12 18:23:51
【问题描述】:

编写一个程序找出每个的概率 “总值”当几个无偏的不规则骰子(可能有不同数量的 面)同时抛出。

当掷出一个无偏的骰子时​​,具有不同面值的概率应该 等于。例如,一个典型的立方​​骰子应该给出面部的 1/6 概率 值 1、2、3、4、5 和 6。 如果掷出两个立方体骰子,则两个骰子的面值之和在范围内 [2..12]。但是,每个“总值”的概率并不相等。例如, 总共 4 个的概率为 3/36(对于组合 1+3、2+2 和 3+3),而 总共 2 的概率只有 1/36(当两个骰子都给 1 时)。

Sample output as follow: (the one with * are the input from user)
Input the number of dice(s): *2
Input the number of faces for the 1st dice: *6
Input the number of faces for the 2nd dice: *6
Probability of 2 = 1/36
Probability of 3 = 2/36
Probability of 4 = 3/36
Probability of 5 = 4/36
Probability of 6 = 5/36
Probability of 7 = 6/36
Probability of 8 = 5/36
Probability of 9 = 4/36
Probability of 10 = 3/36
Probability of 11 = 2/36
Probability of 12 = 1/36

Input the number of dice(s): *5
Input the number of faces for the 1st dice: *1
Input the number of faces for the 2nd dice: *2
Input the number of faces for the 3rd dice: *3
Input the number of faces for the 4th dice: *4
Input the number of faces for the 5th dice: *5
Probability of 5 = 1/120
Probability of 6 = 4/120
Probability of 7 = 9/120
Probability of 8 = 15/120
Probability of 9 = 20/120
Probability of 10 = 22/120
Probability of 11 = 20/120
Probability of 12 = 15/120
Probability of 13 = 9/120
Probability of 14 = 4/120
Probability of 15 = 1/120

我实际上不知道如何完成概率部分。我想对计算问题的方法有一些提示。

#include <iostream>
#include <string>
using namespace std;

//Initialise output function
string output(int num){
  case 1:
    return "st";
    break;
  case 2:
    return "nd";
    break;
  case 3:
    return "rd";
    break;
  default:
    return "th";
}



//Roll function
int roll(int num, int result, int value[20]){
    int dice[num][20];
    for (int i=0; i<num;i++){
        for (int j=1; j<=value[i];j++){
            for (int k=0; k<value[i];k++)
                dice[i][k]=j;
            }
        }
    }
}

int main(){
    int number;
    //Initialise the number variable
    cout <<"Input the number of dice(s): ";
    cin >> number;
    cout<<endl;

    //Initialise the face of the dice using std::array
    int value[11];
    for (int i=0; i<number; i++){
        cout << "Input the number of faces for the "<< i+1 << output(i+1) 
    <<" dice: ";
        cin>>value[i];
    }

    //set the base of the probability (multiply), the maxrange (sum) for 
    the dice probability
    int base=1;
    int sum;
    for (int i=0; i<number; i++){
        base = base*value[i];
        sum = sum +value[i];
    }

    //Output statements
    if (sum >9){
        for (int i=number; i<10; i++){
            cout << "Probability of  "<<i<<" = "<<roll(number, i, value);
        }
        for (int i=10; i<=sum;i++){
            cout << "Probability of "<<i<<" = "<<roll(number, i, value);
        }
    } else {
        for (int i=number; i<=sum; i++){
            cout << "Probability of "<<i<<" = "<<roll(number, i, value);
        }
    }

    return 0;
}

【问题讨论】:

    标签: c++ probability dice


    【解决方案1】:

    您可以使用 brute froce 并使用递归函数计算所有组合,并使用映射来计算每个结果出现的次数。

    此外,使用 C++ 容器而不是 C 样式的数组。

    喜欢:

    #include <iostream>
    #include <vector>
    #include <map>
    
    void calcAll(const uint32_t value,
                 const uint32_t index, 
                 const std::vector<uint32_t>& dices, 
                 std::map<uint32_t, uint32_t>& count, 
                 uint32_t& total)
    {
        if (index == dices.size())
        {
            // No more dices -> save result and stop recursion
            auto it = count.find(value);
            if (it == count.end())
            {
                count[value]=1;
            }
            else
            {
                count[value]++;
            }
            ++total;
            return;
        }
    
        // Iterate over all dice values
        for (uint32_t i = 0; i < dices[index]; ++i)
        {
            calcAll(value + i + 1, index + 1, dices, count, total);
        }
    }
    
    int main() {
        std::vector<uint32_t> dices {6, 6, 6}; // 3 dices, 6 sides each
        std::map<uint32_t, uint32_t> count;
        uint32_t total = 0;   
    
        calcAll(0, 0, dices, count, total);
    
        for (const auto& v : count)
        {
            std::cout << v.first << " seen " << v.second << " times out of " << total << std::endl;
        }
    
        return 0;
    }
    

    输出:

    3 seen 1 times out of 216
    4 seen 3 times out of 216
    5 seen 6 times out of 216
    6 seen 10 times out of 216
    7 seen 15 times out of 216
    8 seen 21 times out of 216
    9 seen 25 times out of 216
    10 seen 27 times out of 216
    11 seen 27 times out of 216
    12 seen 25 times out of 216
    13 seen 21 times out of 216
    14 seen 15 times out of 216
    15 seen 10 times out of 216
    16 seen 6 times out of 216
    17 seen 3 times out of 216
    18 seen 1 times out of 216
    

    【讨论】:

      【解决方案2】:

      对于一个 6 面骰子,您有一个“概率向量”[1/6, 1/6, 1/6, 1/6, 1/6, 1/6],然后对于每个额外的骰子,您 convolve 具有下一个骰子的“概率向量”的向量以获得更长、更“钟形”向量。

      [1/6, 1/6, 1/6, 1/6, 1/6, 1/6] * [1/6, 1/6, 1/6, 1/6, 1/6, 1/6] =
        [1/36, 2/36, 3/36, 4/36, 5/36, 6/36, 5/36, 4/36, 3/36, 2/36, 1/36]
      

      您可以这样编码:(请注意,我将分母从卷积中分解出来)。

      static std::vector<int> conv(const std::vector<int>& f, const std::vector<int>& g) {
        const int nf = f.size();
        const int ng = g.size();
        const int n  = nf + ng - 1;
      
        std::vector<int> out(n);
      
        for(int i = 0; i < n; ++i) {
          const int jmn = (i >= ng - 1) ? i - (ng - 1) : 0;
          const int jmx = (i <  nf - 1) ? i            : nf - 1;
      
          for(int j = jmn; j <= jmx; ++j) {
            out[i] += (f[j] * g[i - j]);
          }
        }
      
        return out; 
      }
      
      static void rollDice(const std::vector<int>& dice) {
          std::vector<int> firstDie(dice[0], 1);
          std::vector<int> a = firstDie;
          int denominator = dice[0];
      
          for (int i = 1; i < dice.size(); ++i) {
              a = conv(a, std::vector<int>(dice[i], 1));
              denominator *= dice[i];
          }
      
          for (auto aa : a) {
              std::cout << aa << '/' << denominator << '\n';
          }
      }
      
      int main() {
          rollDice({6, 6});
          rollDice({1, 2, 3, 4, 5});
      }
      

      输出是:

      1/36
      2/36
      3/36
      4/36
      5/36
      6/36
      5/36
      4/36
      3/36
      2/36
      1/36
      1/120
      4/120
      9/120
      15/120
      20/120
      22/120
      20/120
      15/120
      9/120
      4/120
      1/120
      

      【讨论】:

        猜你喜欢
        • 2020-02-11
        • 2021-09-23
        • 2021-07-14
        • 2013-07-18
        • 2020-09-02
        • 2020-03-22
        • 1970-01-01
        • 1970-01-01
        • 2017-11-01
        相关资源
        最近更新 更多