Вопрос C ++ о расчете вероятности игры в кости - PullRequest
0 голосов
/ 16 октября 2019

Напишите программу для определения вероятности каждого «общего значения», когда несколько несмещенных нерегулярных кубиков (возможно, с разным количеством граней) выбрасываются одновременно.

Когда брошен несмещенный кубик,вероятность иметь различную номинальную стоимость должна быть одинаковой. Например, типичная кубическая игральная кость должна давать вероятность 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;
}

Ответы [ 2 ]

0 голосов
/ 16 октября 2019

Для 6-стороннего кубика у вас есть «вектор вероятности» [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/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
0 голосов
/ 16 октября 2019

Вы можете использовать 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
...