Losowanie obiektów z różną szansą na trafienie

0

Cześć wszystkim. Mam prosty kod, w którym mam klasę example

class Example
{
    string name;
    int chance;
public:
    example(string name,int chance)
    {
        this ->name = name;
        this ->chance = chance;
    }
};

Teraz tworzę przykładowe 3 klasy od ręki w mainie i dodaje je wszystkie do vectora

int main()
{
    Example ex1("example 1",25);
    Example ex2("example 2",40);
    Example ex3("example 3",5);
    vector<Example> exampleList;
    exampleList.push_back(ex1);
    exampleList.push_back(ex2);
    exampleList.push_back(ex3);
}

Chciałbym teraz stworzyć funkcję losującą pomiędzy trzema obiektami w liście z różną szansą na trafienie (jest też szansa 30% na to, że nie wylosujemy ani jednego obiektu). Niestety nie mam pojęcia jak to zrobić.

Stworzyłem coś takiego ale wydaje mi się, że może to być zrobione dużo prościej i lepiej

class Example
{
    string name;
    int chance;
public:
    Example(string name,int chance)
    {
        this ->name = name;
        this ->chance = chance;
    }
    int getChance()
    {
        return chance;
    }
};
int draw(vector<Example> exampleList)
{
    int fullChance = 0;
    for(int i =0; i< exampleList.size(); ++i)
    {
        fullChance += exampleList[i].getChance();
    }
    int rest = 100 - fullChance;
    srand(time(NULL));
    int number = rand()%101;
    fullChance = 0;
    for(int i =0; i< exampleList.size(); ++i)
    {
        if(number > exampleList[0].getChance() + fullChance)
        {
            fullChance +=  exampleList[0].getChance();
        }
        else
        {
            return i;
        }
    }
    return -1;
}

Example *decide(vector<Example> exampleList)
{
    int i = draw(exampleList);
    if(i == -1)
    {
        cout<<"Out of range"<<endl;
        return NULL;
    }
    else
    {
        return &exampleList[i];
    }

}

int main()
{
    Example ex1("example 1",25);
    Example ex2("example 2",40);
    Example ex3("example 3",5);
    vector<Example> exampleList;
    exampleList.push_back(ex1);
    exampleList.push_back(ex2);
    exampleList.push_back(ex3);

    Example *bufor = decide(exampleList);
    if(bufor != NULL)
        cout<<bufor->getChance()<<endl;
}

Jakieś porady jak to można usprawnić / zrobić lepiej?

3
size_t draw(const vector<Example> &exampleList)
{
    size_t fullChance=0,size=exampleList.size();
    for(size_t i=0;i<size;++i) fullChance+=exampleList[i].getChance(); // zastanów się nad użyciem accumulate
    //srand(time(NULL)); // to wywalić stąd i odpalić raz w main
    size_t rnd=rand()%fullChance;
    for(size_t i=0;i<size;++i)
    {
        size_t chance=exampleList[i].getChance();
        if(rnd<chance) return i;
        rnd-=chance;
    }
    //return -1; //to nie ma szansy zajść no chyba że przerobisz chance na double ale wtedy lepsze jest:
    return size-1;
}
4

std::discrete_distribution

std::vector<int> chances = { 30, 25, 40, 5 };
std::random_device rd;
std::mt19937 gen(rd());
std::discrete_distribution<> dist(chances.cbegin(), chances.cend());
auto val = dist(gen);
// val == 0  -> 30%
// val == 1  -> 25%
// val == 2  -> 40%
// val == 3  -> 5%

1 użytkowników online, w tym zalogowanych: 0, gości: 1