Просчёт шансов, алгоритм распределения шансов
Часть 1. Что и как работает
Для начало расскажу в чём заключит задача, нужно создать определённый алгоритм, на вход которого идёт массив с предметами у которых есть цена ('cost' => 123
), а также на вход идёт стоимость одного получения скина $get_cost = 123;
, пример данных:
$get_cost = 10;
$items = [
['cost' => 5],
['cost' => 10],
['cost' => 20]
];
Так же благодаря методу подбора и 2-м часам потраченного времени я уже просчитал шансы на некоторые входные данные, к примеру у данных которые я выше показал все чётные шансы равны:
+———–+—–——–+——–—+
| 5 | 10 | 20 |
+——––+——–––+—–——+
| 0 | 100 | 0 |
| 10 | 85 | 5 |
| 20 | 70 | 10 |
| 30 | 55 | 15 |
| 40 | 40 | 20 |
| 50 | 25 | 25 |
| 60 | 10 | 30 |
+——––+——–––+—–——+
*некотрые данные стёр чтобы они вам не мешали, данные которые стёр нужны были для подбора и так на всякий случай
Таблица выше показывает возможные чётные проценты для этих чисел, к примеру возьмём 4 строчку, 5 - 30%, 10 - 55%, 20 - 15%.
Теперь расскажу как это работает, к примеру выберем на основе данных шансов предметы 10млн. раз, за каждую выборку (попытку) у нас тратится баланс, сколько потратили запишем в условный $sum_spending = 0;
и у нас получается такой код:
var get_cost = 10;
var sum = 0;
for (var i = 0; i < 10000000; i++) {
var rand = Math.floor(Math.random() * 100) + 1 // генерируем число от 1 до 100
if (rand <= 40) sum += 5; // 40% шанс
else if (rand <= 80) sum += 10; // 40% шанс
else if (rand <= 100) sum += 20; // 20% шанс
}
document.getElementById('cost_get').innerHTML = i * get_cost;
document.getElementById('sum_get').innerHTML = sum;
<div id="cost_get"></div>
<div id="sum_get"></div>
Код переписал на js, чтобы могли по тестить, этот код работает так, у первого есть шанс к примеру 40% значит в первом условии ставим что то по типу:
if (диапозон меньше либо равен 40)
,
к следующему условию прибавляем предыдущий шанс 40%+40% и получается:
if (диапозон меньше либо равен 80 и больше 40)
и так далее, это самый наглядный пример чтобы выбрать случайный элемент исходя из шансов только он не выбирает, а сразу суммирует, это сделано чтобы все эти миллионные операции выполнялись за пару секунд, так же если вам понадобится функция которая будет уже из массива выбирать, массив уже выглядеть так:
$items = [
['cost' => 5, 'chance' => 40],
['cost' => 10, 'chance' => 40],
['cost' => 20, 'chance' => 20]
];
Вот код которые выбирает исходя из указанных шансов (шансы в сумме должны быть 100)
$items = [
['cost' => 5, 'chance' => 40],
['cost' => 10, 'chance' => 40],
['cost' => 20, 'chance' => 20]
];
foreach ($items as $key => &$item) {
if (isset($items[$key - 1])) $item['chance'] += $items[$key - 1]['chance'];
}
function getRandItem($items) {
$rand = rand(1, 100);
foreach ($items as $item) {
if ($rand <= $item['chance']) return $item;
}
}
print_r(getRandItem($items));
Часть 2. Теория и описание
С самого начала я не понимал как это работает, прочитал статью про теорию вероятности, https://ru.wikipedia.org/wiki/%D0%A2%D0%B5%D0%BE%D1%80%D0%B8%D1%8F_%D0%B2%D0%B5%D1%80%D0%BE%D1%8F%D1%82%D0%BD%D0%BE%D1%81%D1%82%D0%B5%D0%B9
По шерстив википедию пришёл к мнению что нужно использовать Распределение Лапласа
Но это только на мой взгляд.
Определимся с принципом шансов, прописывав все эти шансы, я нашёл определённую закономерность, к примеру возьмём такую таблицу:
+—————–———+——————————+———–——–+
| 5 | 20 | SUM |
+—————–———+——————————+———–——–+
| 66.6666 | 33.3333 | ~100% |
+—————–———+——————————+———–——–+
Если есть 2 элемента, то есть только 1 вариант шанса, если элементов 3 то количество вариантов значительно увеличивается вплоть до бесконечности:
+—————+———––+——––+––––––+
| 2.5 | 10 | 40 | SUM |
+—————+———––+——––+––––––+
| 0 | 100 | 0 | 100% |
| 20 | 75 | 5 | 100% |
| 40 | 50 | 10 | 100% |
| 60 | 25 | 15 | 100% |
| 80 | 0 | 20 | 100% |
+—————+———––+——––+––––––+
Так же всегда есть 1 и больше шансов у входных значений, Исключение если все входные значения меньше суммы получения $get_cost или все больше (Во всех выше указаных примерах $get_cost равна = 10),
Если есть входной параметр равный $get_cost, всегда будет вариант что он равен 100%.
Если входных параметров 3 и более и есть параметр равный $get_cost, всегда будет вариант что шанс параметра равного $get_cost будет равен 0%. Это видно на примере выше.
Часть 3. Как вычислять шансы?
Шансы всегда растут и уменьшаются линейно и с определённой закономерностью, вот ещё парочку примеров:
+———–+––———+——–––+———–––+
| 1 | 10 | 100 | SUM |
+———–+––———+——–––+———–––+
| 0 | 100 | 0 | 100% |
| 50 | 45 | 5 | 100% |
+———–+––———+——–––+———–––+
+———–+———––+–———+——–––+––————+
| 5 | 10 | 20 | 40 | SUM |
+———–+———––+–———+——–––+––————+
| 0 | 100 | 0 | 0 | 100% |
| 20 | 70 | 10 | 0 | 100% |
| 40 | 50 | 5 | 5 | 100% |
| 50 | 25 | 15 | 5 | 95% | // Можно не использовать
| 60 | 30 | 0 | 10 | 100% |
| 80 | 0 | 10 | 10 | 100% |
+———–+———––+–———+——–––+––————+
Мне ума не хватило чтоб найти какую то определённую формулу которая будет на основе входящих параметров выдавать подобные шансы, если кто то по умнее, и с логикой по лучше, прошу помочь, буду крайне благодарен, могу дать денежное вознаграждение (надеюсь это не запрещено).
Так же можете писать на любом языке, если что под себя интерпретируют.
Ещё хотел бы подметить, что много кода было упрощено для лучшего понимания, так же старался объяснить задачу понятным языком.
Заранее извиняюсь за ошибки в словах если такие будут наблюдаться, вопрос итак пишу уже часа 4, :)
Спасибо за внимание!