Модераторы: Daevaorn
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Случайный выбор объектов с разными вероятностями 
:(
    Опции темы
Riddik
Дата 24.2.2012, 14:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 598
Регистрация: 2.12.2006

Репутация: нет
Всего: нет



Привет! 
Прошу помочь придумать алгоритм для такой задачи: 

Есть набор объектов (A, B, C, D), у каждого своя вероятность, что сейчас выпадит именно он, например для A - 50%, B - 20%, C - 30%, D - 0%(не выпадит никогда).  Какой-то объект должен быть обязательно выбран, но какой именно - зависит от вероятности каждого. Т.е. понятно, что A будет чаще других, D - никогда.
Этот момент критичен по времени выполнения, надо чтобы быстро. 

Не могу никак придумать првильный алгоритм. 

Люди подсказывают так:

Код

int r = rand() % 100;

if (r < 0)
{
   return "D"; // это условие никогда не выполнится, можем его не учитывать
}

if (r < (0 + 20))
{
   return "B";
}

if (r < (20 + 30))
{
   return "C";
}

if (r < (20 + 30 + 50))
{
   return "A";
}


Или для N объектов:

Код

int cases[CASE_MAX] = { ... };
int caseSum = 0;

for (int i = 0; i < CASE_MAX; ++i)
{
   caseSum += cases[i];
}

...
int r = rand() % caseSum;
int caseLimit = 0;

for (int i = 0; i < (CASE_MAX - 1); ++i)
{
   caseLimit += cases[i + 1];

   if (r < caseLimit)
   {
      return i; // return case index
   }
}

return CASE_MAX - 1; // last case


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

Но главное - все же не очень правильно вычисляется вероятность, как мне кажется.

Есть идеи, что можно ещё придумать?
PM MAIL   Вверх
boostcoder
Дата 24.2.2012, 15:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 49
Всего: 110



использовать приоритетную очередь? ;)

PM WWW   Вверх
Riddik
Дата 24.2.2012, 15:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 598
Регистрация: 2.12.2006

Репутация: нет
Всего: нет



А как обеспечить, чтобы объект, у которого вероятность больше, чаще стоял на выходе?
PM MAIL   Вверх
boostcoder
Дата 24.2.2012, 15:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 49
Всего: 110



что значит "чаще" ?
у кого приоритет выше - тот первым выйдет.
для того чтоб очередь использовать многократно - при выходе элемента, добавляем его обратно.

или я не правильно понял задачу?

Добавлено через 3 минуты и 2 секунды
и да - с приоритетными очередями есть проблема: нет стандартной реализации "хорошей" приоритетной очереди. та, что в стандартной библиотеке - ужасная реализация.элементы с более низкими приоритетами вовсе никогда не выйдут, пока имеются элементы с более высокими приоритетами.

хорошая реализация есть в boost: http://www.boost.org/doc/libs/1_49_0/doc/html/heap.html

Добавлено через 6 минут и 36 секунд
приоритеты элементов можно изменять. значит, распределение можно регулировать.
PM WWW   Вверх
Riddik
Дата 24.2.2012, 15:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 598
Регистрация: 2.12.2006

Репутация: нет
Всего: нет



Цитата(boostcoder @  24.2.2012,  15:13 Найти цитируемый пост)
или я не правильно понял задачу?


Понял верно. 
Спасибо за наводку на приоритетную очередь, буду пробовать. Единственное условие - буст не вариант использовать в текущем проекте, нельзя его с собой таскать, придётся разбираться и писать самомуsmile

Если будут ещё идеи, прошу высказываться smile

Это сообщение отредактировал(а) Riddik - 24.2.2012, 15:23
PM MAIL   Вверх
boostcoder
Дата 24.2.2012, 15:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 49
Всего: 110



Цитата(Riddik @  24.2.2012,  15:22 Найти цитируемый пост)
нельзя его с собой таскать

что значит "таскать" ?
для готового продукта, исходники буста таскать не нужно smile

PM WWW   Вверх
Riddik
Дата 24.2.2012, 15:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 598
Регистрация: 2.12.2006

Репутация: нет
Всего: нет



Не так выразилсяsmile 
Нельзя его использовать - подключать к текущему проекту. Такие условия.
PM MAIL   Вверх
Michrutka
Дата 24.2.2012, 17:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 57
Регистрация: 6.2.2008

Репутация: нет
Всего: нет



Как вариант можно взять массив из 100 элементов и заполнить его согласно твоим процентам: у А будет 50 позиций, у Б - 30 и тд.
брать рендомное число в пределах 0-99 и смотреть на какую позицию попадешь.
в итоге будет нормальное распределние.

хотя это не очень красиво, да.

ан нет. это уже предлагали. сорри.

Это сообщение отредактировал(а) Michrutka - 24.2.2012, 17:03
PM MAIL   Вверх
Riddik
Дата 24.2.2012, 17:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 598
Регистрация: 2.12.2006

Репутация: нет
Всего: нет



Всё равно спасибо!

Это сообщение отредактировал(а) Riddik - 24.2.2012, 17:35
PM MAIL   Вверх
Qu1nt
Дата 24.2.2012, 20:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 602
Регистрация: 13.1.2007

Репутация: 1
Всего: 50



Вот, набросал.
Код

#include <algorithm>
#include <ctime>
#include <iostream>
#include <map>
#include <string>
#include <vector>

int main()
{
    std::srand(static_cast<unsigned int>(std::time(0)));

    std::vector<std::pair<std::string, unsigned int>> data;
    data.push_back(std::make_pair("A", 50));
    data.push_back(std::make_pair("B", 20));
    data.push_back(std::make_pair("C", 30));
    data.push_back(std::make_pair("D", 0));

    std::vector<unsigned int> weights(data.size());
    weights[0] = data[0].second;
    for (unsigned int i = 1; i < data.size(); ++i)
    {
        weights[i] = weights[i - 1] + data[i].second;
    }

    std::vector<std::pair<std::string, unsigned int>> result(data.size());
    for (unsigned int i = 0; i < 1e5; ++i)
    {
        unsigned int dice = rand() % weights.back();
        unsigned int item = std::distance(weights.begin(), std::find_if(weights.begin(), weights.end(), 
            [&dice] (unsigned int weight)
            {
                return dice < weight;
            }));

        ++result[item].second;
    }

    std::for_each(result.begin(), result.end(), 
        [] (const std::pair<std::string, unsigned int>& pair)
        {
            std::cout << pair.first << ": " << pair.second << std::endl;
        });
}

http://liveworkspace.org/code/daa70b237fe8...296788da0592921

PM MAIL   Вверх
Riddik
Дата 24.2.2012, 22:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 598
Регистрация: 2.12.2006

Репутация: нет
Всего: нет



Большое спасибо!
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
Earnest Daevaorn

Добро пожаловать!

  • Черновик стандарта C++ (за октябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика(4.4мб).
  • Черновик стандарта C (за сентябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика (3.4мб).
  • Прежде чем задать вопрос, прочтите это и/или это!
  • Здесь хранится весь мировой запас ссылок на документы, связанные с C++ :)
  • Не брезгуйте пользоваться тегами [code=cpp][/code].
  • Пожалуйста, не просите написать за вас программы в этом разделе - для этого существует "Центр Помощи".
  • C++ FAQ

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0848 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.