[Разминка для мозгов]: взвешенный рандом

Итак, задача написать функцию взвешенного рандома. То есть такого рандома, где частота выпадения элемента зависит от значения его веса.

Например, возьмем двумерный массив размером 4 x 2. Каждый подмассив описывает вес и значение в соответствующем порядке.

int arr[5][2] = {
    {100, 1},
    {200, 2},
    {300, 3},
    {400, 4}
};

Необходимо написать функцию, которая будет принимать подобный массив и возвращать псевдослучайное значение, учитывая веса элементов.

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

Например, на 20000 вызовах функции с вышеприведенным массивом, число 1 выпадет примерно 2000 раз, число 2 — ~4000, число 3 — ~6000, а 4 — около 8000 раз.

Свои решения пишите прямо в этом топике.

которая будет принимать подобный массив

Размер массива передаётся в функцию?

Я тут написал, и в результате, результат в среднем колеблется от -23 до +30. Критично? Или так оставлять?
Вот пример запуска:

Please, wait...
Result:
[1] dropped 107 times
[2] dropped 217 times
[3] dropped 294 times
[4] dropped 372 times
[5] dropped 481 times
[6] dropped 597 times
[7] dropped 727 times
[8] dropped 757 times
[9] dropped 914 times
[10] dropped 1034 times

С таким массивом весов и значений.

int arr[10][2] = {
        { 100, 1 },
        { 200, 2 },
        { 300, 3 },
        { 400, 4 },
        { 500, 5 },
        { 600, 6 },
        { 700, 7 },
        { 800, 8 },
        { 900, 9 },
        { 1000, 10 }
    };

UPD на всякий случай убрал код

Код зря убрал, возвращай :)

#include <iostream>
#include <ctime>
#include <cstdlib>

using namespace std;

int weigt_rand( const int arr[][2], int n );

int main()
{
    srand( time(NULL) );

    int arr[10][2] = {
        { 100, 1 },
        { 200, 2 },
        { 300, 3 },
        { 400, 4 },
        { 500, 5 },
        { 600, 6 },
        { 700, 7 },
        { 800, 8 },
        { 900, 9 },
        { 1000, 10 }
    };

    int res[10] = { 0, };

    cout << "Please, wait..." << endl;

    for ( int i = 0; i < 5500; i++ )
        res[weigt_rand( arr, 10 )-1]++;

    cout << "Result: " << endl; 
    for ( int i = 0; i < 10; i++ )
        cout << "[" << i+1 << "] dropped " << res[i] << " times" << endl;

    return 0;
}

int weigt_rand( const int arr[][2], int n )
{
    long long summ = 0;
    for ( int i = 0; i < n; i++ )
        summ += arr[i][0];

    int r = 0 + rand() % summ;
    int prev = 0;

    for ( int i = 0; i < n; i++ )
    {
        if ( r >= prev && r <= arr[i][0] + prev )
           return arr[i][1];

        prev += arr[i][0];
    }
}

Да, все верно. Берем рандом от суммы весов — и берем соответствующий сдвиг в исходном массиве.

Сколько времени ушло вывод на решение? :-)

P.S. Если отвечаешь на предыдущий пост, то цитировать его целиком не нужно :)

Внимание! Это довольно старый топик, посты в него не попадут в новые, и их никто не увидит. Пишите пост, если хотите просто дополнить топик, а чтобы задать новый вопрос — начните новый.

Ответить

Вы можете использовать разметку markdown для оформления комментариев и постов. Используйте функцию предпросмотра для проверки корректности разметки.

Пожалуйста, оформляйте исходный код в соответствии с правилами разметки. Для того, чтобы вставить код в комментарий, скопируйте его в текстовое поле ниже, после чего выделите то, что скопировали и нажмите кнопку «код» в панели инструментов. Иначе ваш код может принять нечитаемый вид.

Либо производите оформление кода вручную, следующим образом:

``` #include <iostream> using namespace std; int main() { // ... } ```

Предпросмотр сообщения

Ваше сообщение пусто.