Этот вопрос закрыт для ответов, так как повторяет вопрос Как выбрать случайный элемент из списка с учётом его веса?
@ski28

Как сделать распределение по процентам, чем дороже цена тем меньше шансов?

Добрый день. Пишу викторину. И призы за разную цену. Призы меняются, то их больше то меньше. Поэтому хотелось бы иметь общую функцию которая будет работать всегда.
Хотелось бы сделать шанс приза так - цем больше его цена от общий суммы тем меньше у него шансов.
Пример кода
const gift = [
  {
    name : "Ручка",
    price : 12
  },
  {
    name : "Телефон",
    price : 2222
  },
  {
    name : "Блокнот",
    price : 33
  },
  {
    name : "Альбом",
    price : 120
  },
  {
    name : "Книга",
    price : 333
  },
]
//общая сумма предметов
let allSum = gift.reduce((a, b) => a + (b["price"] || 0), 0);
console.log(allSum);

gift.sort((a, b) =>  b.price - a.price );
gift.forEach((e, i) => {
  gift[i].chance = ( 100 / (allSum / e.price) ).toFixed(4);
});

Получаем проценты от общей суммы
[
{"name":"Телефон","price":2222,"chance":"81.6912"},
{"name":"Книга","price":333,"chance":"12.2426"},
{"name":"Альбом","price":120,"chance":"4.4118"},
{"name":"Блокнот","price":33,"chance":"1.2132"},
{"name":"Ручка","price":12,"chance":"0.4412"}
]

А хотелось бы видеть у телефона самую низкий шанс. Нечего готового нагуглить не смог.
  • Вопрос задан
  • 264 просмотра
Решения вопроса 4
alexey-m-ukolov
@alexey-m-ukolov Куратор тега JavaScript
Ну вы же привели 99% решения. Добавьте просто вычитание из 100 получающегося у вас шанса, чтобы его инвертировать. Ну или используйте ту цифру, что получается у вас, просто считайте, что это не шанс, а сложность.
Ответ написан
@rPman
Все зависит от того, будешь ли ты проводить такие розыгрыши часто или это однократная операция. А так же, готов ли ты к серии неудач для тебя (т.е. будет ли случайное число честным для участников розыгрыша).

Если решать задачу в лоб (честно), ты можешь представить шансы выпадения того или иного приза как отрезок на интервале от 0 до суммы цен всех предметов в розыгрыше, где длина этого отрезка - стоимость предмета. Затем каждый розыгрыш - это получение случайного числа на этом интервале , а попадание этого числа на отрезок соответствующего предмета - его выигрыш.

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

Поэтому большинство розыгрышей делают не честным (например игровые автоматы), с целью убрать серию убыточных для организатора выигрышей, например выставляя условие, если общая сумма выигрышей прошедших розыгрышей выше некоторого лимита, то дорогие выигрыши исключаются из следующего розыгрыша. Так же как частный случай, можно заранее провести розыгрыши некоторого количества призов и если их сумма не превышает лимита, сохранить их список или сохранить стартовый seed генератора случайных чисел, чтобы иметь гарантии. У второго подхода есть уязвимость, сотрудники компании, имеющие доступ к этим сохраненным результатам, могут их использовать для повышения своих шансов на выигрыш, фактически грабя остальных участников.
Ответ написан
Rsa97
@Rsa97
Для правильного вопроса надо знать половину ответа
Если у вас заранее определённый список призов и их количество известно (100 ручек, 10 блокнотов, 1 телефон), то можно создать общий массив, сделать shuffle и выдавать призы из полученного случайного массива по порядку.
Ответ написан
@ski28 Автор вопроса
Публикую решение как я сделал. Я реальный шанс разделил на 100 и тогда получается то что нужно.
const gift = [
{ name : "Ручка", price : 12 },
{ name : "Телефон",  price : 2222  },
{  name : "Блокнот", price : 33 },
{name : "Альбом",price : 120 },
{name : "Книга",  price : 333 },
];
let allSum = gift.reduce((a, b) => a + (b["price"] || 0), 0);
console.log(allSum); 
gift.sort((a, b) =>  b.price - a.price );
gift.forEach((e, i) => {
  gift[i].bigChance =  (100/(100 / (allSum / e.price)));
});
let allChance = gift.reduce((a, b) => a + (b["bigChance"] || 0),0);
gift.forEach((e, i) => {
  gift[i].chance = ( 100 / (allChance / e.bigChance)).toFixed(4);
});
console.log(gift)

Результат
[
{"name":"Телефон","price":2222,"bigChance":1.2241224122412242,"chance":"0.3588"},
{"name":"Книга","price":333,"bigChance":8.168168168168169,"chance":"2.3943"},
{"name":"Альбом","price":120,"bigChance":22.666666666666668,"chance":"6.6442"},
{"name":"Блокнот","price":33,"bigChance":82.42424242424242,"chance":"24.1607"},
{"name":"Ручка","price":12,"bigChance":226.66666666666666,"chance":"66.4420"}
]
Ответ написан
Ваш ответ на вопрос

Вопрос закрыт для ответов и комментариев

Потому что уже есть похожий вопрос.
Похожие вопросы