#include <map>
#include <sstream>
#include <vector>
#include <random>
#include <iostream>
#include <iomanip>
#include <numeric>
struct Die
{
Die(unsigned faces = 6) : _faces(faces), _die(std::random_device()()) {}
Die(const Die& d) : _faces(d._faces), _die(std::random_device()()) {}
unsigned operator()()
{
return std::uniform_int_distribution<unsigned>(1, _faces)(_die);
}
private:
unsigned _faces;
std::mt19937 _die;
};
int main()
{
const unsigned trials = 100000;
const unsigned faces = 6;
const unsigned num_dice = 2;
std::vector<Die> dice(num_dice, Die(faces));
using seq_map = std::map<std::vector<unsigned>, unsigned>;
seq_map sequence_frequency ;
// generate and store roll sequences.
for (unsigned i = 0; i < trials; ++i)
{
std::vector<unsigned> rolls;
for (auto& die : dice)
rolls.push_back(die());
++sequence_frequency[rolls];
}
// collate roll sequences which have the same total.
std::map<unsigned, std::vector<seq_map::const_iterator>> by_total ;
for (auto it = sequence_frequency.cbegin(); it != sequence_frequency.cend(); ++it)
{
unsigned total = std::accumulate(it->first.cbegin(), it->first.cend(), 0u);
by_total[total].push_back(it);
}
// display:
for (const auto& seq : by_total)
{
std::cout << std::setw(3) << seq.first << ": ";
std::ostringstream rolls_string;
unsigned freq = 0;
for (const auto& roll : seq.second)
{
for (const auto& value : roll->first)
rolls_string << '[' << value << ']';
rolls_string << " (" << roll->second << ") ";
freq += roll->second;
}
std::cout << std::setw(6) << freq << " - ";
std::cout << std::setprecision(2) << std::fixed << std::setw(5);
std::cout << (freq / (double) trials*100.0) << "%\n";
std::cout << '\t' << rolls_string.str() << '\n';
}
}