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

Ссылка скопирована
1 ответ

Добрый день. Пишу викторину. И призы за разную цену. Призы меняются, то их больше то меньше. Поэтому хотелось бы иметь общую функцию которая будет работать всегда.
Хотелось бы сделать шанс приза так - цем больше его цена от общий суммы тем меньше у него шансов.
Пример кода

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); });

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"} ]

[ {"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"} ]

А хотелось бы видеть у телефона самую низкий шанс. Нечего готового нагуглить не смог.

Дополнительно:

Серьёзно считаешь этот вопрос сложным и относящимся к высшей математике? Лол!

  • Elmo Sputterspark, Если это не сложно - то покажи решение. А математику я отметил что может кто-то скажет как называется такое распределение что бы загуглить.
  • Elmo Sputterspark, а java и c# в тегах Вас не смущают, при коде js?
  • Михаил Р., нужен любой пример от чего я смогу оттолкнуться.
  • ski28, если вам нужен алгоритм и не важен язык, на котором он будет реализован, то нужно указывать ровно один тег: алгоритмы. Указывать всё, что придёт в голову, чтобы ваш вопрос увидело больше людей, нельзя, это нарушение правил.
  • Модератор, спасибо за разъяснение, не знал просто. В следующий раз так делать не буду.
  • Ну вы же привели 99% решения. Добавьте просто вычитание из 100 получающегося у вас шанса, чтобы его инвертировать. Ну или используйте ту цифру, что получается у вас, просто считайте, что это не шанс, а сложность.

    Все зависит от того, будешь ли ты проводить такие розыгрыши часто или это однократная операция. А так же, готов ли ты к серии неудач для тебя (т.е. будет ли случайное число честным для участников розыгрыша).

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

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

    Поэтому большинство розыгрышей делают не честным (например игровые автоматы), с целью убрать серию убыточных для организатора выигрышей, например выставляя условие, если общая сумма выигрышей прошедших розыгрышей выше некоторого лимита, то дорогие выигрыши исключаются из следующего розыгрыша. Так же как частный случай, можно заранее провести розыгрыши некоторого количества призов и если их сумма не превышает лимита, сохранить их список или сохранить стартовый seed генератора случайных чисел, чтобы иметь гарантии. У второго подхода есть уязвимость, сотрудники компании, имеющие доступ к этим сохраненным результатам, могут их использовать для повышения своих шансов на выигрыш, фактически грабя остальных участников.

    • Я как раз так и хочу сделать. Что бы розыгрыш был честным.
    • толгда собирай свои выигрыши в массив интервалов (точнее границ интервалов )
      [цена товара 1, цена товара1+цена товара2, цена товара1+..2+..3,...]
      и соответственно бери случайное число от 0 до сумма_цен_всех_товаров и в цикле перебирай этот массив, проверяя, меньше ли полученное число чем значение (и больше предыдущего, начиная с 0) в массиве, как только найдешь - вот искомый товар

    Если у вас заранее определённый список призов и их количество известно (100 ручек, 10 блокнотов, 1 телефон), то можно создать общий массив, сделать shuffle и выдавать призы из полученного случайного массива по порядку.

    • В этом и основная проблема, что количество призов и их цена не фиксированная , поэтому и нужен универсальный способ
    • ski28, Тогда такой вариант:
      function lottery(gifts) {   let total = 0;   for (let i = 0; i < gift.length; ++i) {     gifts[i].minProb = total;     total += 1 / ((gifts[i].price ?? 0) + 1);   }   let prob = Math.random() * total;   for (let i = gifts.length - 1; i >= 0; --i) {     if (prob >= gifts[i].minProb) {       return gifts[i];     }   } }

      function lottery(gifts) { let total = 0; for (let i = 0; i < gift.length; ++i) { gifts[i].minProb = total; total += 1 / ((gifts[i].price ?? 0) + 1); } let prob = Math.random() * total; for (let i = gifts.length - 1; i >= 0; --i) { if (prob >= gifts[i].minProb) { return gifts[i]; } } }

      Кривую можно регулировать степенью в дроби, например:

      total += 1 / Math.pow(((gifts[i].price ?? 0) + 1), 2);

      total += 1 / Math.pow(((gifts[i].price ?? 0) + 1), 2);

      - уменьшит шанc выигрыша дорогой вещи

      total += 1 / Math.pow(((gifts[i].price ?? 0) + 1), 0.3);

      total += 1 / Math.pow(((gifts[i].price ?? 0) + 1), 0.3);

      - увеличит шанc выигрыша дорогой вещи

    • Rsa97, Спасибо, попробую твой вариант. Но вроде я подобрал решение. Опубликовал его.

    Публикую решение как я сделал. Я реальный шанс разделил на 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)

    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"} ]

    [ {"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"} ]

    Нужно решить такую задачу?

    Опишите проблему, и специалист поможет с настройкой, исправлением ошибки или доработкой сайта. Подберём понятный план работ без лишней переписки.

    Заказать помощь
    Лучший ответ
    1
    Артём Dev Ответ

    Для реализации распределения по процентам, где чем дороже цена, тем меньше шансов, можно воспользоваться следующим подходом.

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

    Пример PHP кода:

    $products = [
        ['name' => 'Product A', 'price' => 100],
        ['name' => 'Product B', 'price' => 200],
        ['name' => 'Product C', 'price' => 300]
    ];
     
    $totalPrice = array_sum(array_column($products, 'price'));
     
    $probabilities = [];
    foreach ($products as $product) {
        $probability = 1 - ($product['price'] / $totalPrice);
        $probabilities[$product['name']] = $probability;
    }
     
    arsort($probabilities); // Сортируем вероятности по убыванию
     
    foreach ($probabilities as $productName => $probability) {
        echo "Вероятность покупки $productName: " . $probability * 100 . "%<br>";
    }

    $products = [ ['name' =&gt; 'Product A', 'price' =&gt; 100], ['name' =&gt; 'Product B', 'price' =&gt; 200], ['name' =&gt; 'Product C', 'price' =&gt; 300] ]; $totalPrice = array_sum(array_column($products, 'price')); $probabilities = []; foreach ($products as $product) { $probability = 1 - ($product['price'] / $totalPrice); $probabilities[$product['name']] = $probability; } arsort($probabilities); // Сортируем вероятности по убыванию foreach ($probabilities as $productName =&gt; $probability) { echo "Вероятность покупки $productName: " . $probability * 100 . "%<br>"; }

    В этом примере мы сначала вычисляем общую сумму всех товаров, затем вычисляем вероятности покупки каждого товара и сортируем их по убыванию. Чем дороже товар, тем меньше его вероятность покупки.

    Таким образом, вы можете использовать этот код для распределения вероятностей покупки товаров в зависимости от их цены.

    Другие ответы (0)

    Пока нет других ответов. Будьте первым, кто поможет автору.

    Ответить на вопрос

    комментарий

    Ваш адрес email не будет опубликован. Обязательные поля помечены *

    Вам также может быть интересно