Return a random word from a string using std::mt19937

181 Views Asked by At

I want to use this algorithm for choosing a random word from a string:

Choose the first word with propability 1:1,

choose the second word with propability 1:2,

choose the nth word with propability 1:n

where each choice overwrites the last choice.

I want to use std::mt19937 for the "randomness". (is there a better method?)

My function should get an inputstring with this format:

word1 word2
word3 word4 word5
word6

where the number of words per line is unspecified, and words are seperated from eachother by blank spaces or new lines.

Is this the correct use of std::mt19937?

std::string random_word_from_string(std::string input)
{
    static auto gen = std::mt19937{std::random_device{}()};
    std::string random_word="";
    std::string word="";
    std::stringstream iss(input);
    auto count = 0u;
    while (iss >> word)
    {
        if (std::uniform_int_distribution{0u,count++}(gen) == 0)
        {
            random_word = word;
        }
    }
    return random_word;
}

If this question is already answered in c++, sorry, but I wasn't able to find it! But I am very thankful for getting a link to the duplicate.

1

There are 1 best solutions below

0
BlueTune On

You can run the following program online:

#include <iostream>
#include <vector>
#include <random>

std::string GetRandomString(int seed, const std::vector<std::string>& StrVector)
{
    std::mt19937 mt(seed);
    std::uniform_real_distribution<double> dist(0.0, 100.0);

    std::string ResultString= "";

    for(int i=0; i< (int) StrVector.size(); ++i)
    {
        if(dist(mt) < 100.0/(i+1))
            ResultString = StrVector[i];
    }

    return ResultString;
}

int main()
{ 
    std::vector<std::string> StrVector;

    StrVector.push_back("Hello");
    StrVector.push_back("my");
    StrVector.push_back("name");
    StrVector.push_back("is");
    StrVector.push_back("Bob");

    std::cout << GetRandomString(0, StrVector) << std::endl;
    std::cout << GetRandomString(1, StrVector) << std::endl;
    std::cout << GetRandomString(2, StrVector) << std::endl;
    std::cout << GetRandomString(3, StrVector) << std::endl;
    std::cout << GetRandomString(4, StrVector) << std::endl;  
}

The line

if(dist(mt) < 100.0/(i+1))

guarantees that the probability is chosen as you described.

The output reads:

Hello
name
Hello
name
my