Разделите x на y частей в порядке уменьшения

Если бы у меня было 1000 долларов (переменная), и я хочу разделить эту сумму и раздать ее 20 (переменным) людям, но вместо того, чтобы давать поровну каждому человеку, я хочу дать больше 1-му человеку и 2-му человеку, и т.п.

Таким образом, 20-й человек получает меньше всего, а 5-й человек получает 5-е место больше всего.

Как бы я этого добился?

Спасибо

Редактировать:

Формула:

int people = 20;
float prize = 1000;

float k = (2 * prize) / ((people) * (people - 1));
float sum = 0;

for (int i = 1; i < people; ++i)
{
    var personsPrize = i * k;
    sum += personsPrize;
    Console.WriteLine(personsPrize);
}
Console.WriteLine("sum = " + sum);

Похоже на проблему с порядком операций, вам нужны дополнительные скобки вокруг этого выражения: int k = (2 * (int) prize) / (people * (people - 1)); Однако даже с этим исправлением оно в конечном итоге распределяет 1210, что больше, чем ваше prize.

Evan Trimboli 28.05.2019 07:56

@EvanTrimboli да, так и есть, так что где-то еще что-то не так, но я не уверен, что это может быть.

Cypras 28.05.2019 08:03

Так почему вы изменили вопрос, чтобы исправить формулу? «он печатает действительно большие числа, а не 10 чисел, которые в сумме составляют 1000». не совсем соответствует требованиям сейчас.

Evan Trimboli 28.05.2019 08:16

Ну, это еще не сумма приза.

Cypras 28.05.2019 08:18

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

CaTs 28.05.2019 08:25

Ваша формула арифметической прогрессии всех натуральных чисел, начиная с 1, дает только "треугольные" числа 1,3,6,10,15... 1000 не является треугольным числом, вы не можете выразить 1000 как нужную сумму. Возможно, вам нужно переформулировать условия.

MBo 28.05.2019 08:31

Отредактировал вопрос, не понял, что формула неверна.

Cypras 28.05.2019 08:43

Возможно, это лучше подходит для math.stackexchange.com

Zohar Peled 28.05.2019 08:53

Это можно сделать с помощью любой монотонной функции. Самое простое решение: P1, 1$, P2, 2$....P19 19$ P20 остальное.

mikuszefski 28.05.2019 09:02

Возможный дубликат Разделить x на y частей

Brent Worden 28.05.2019 15:26

Нет, это не так. Прочитайте вопросы и вы увидите разницу.

Cypras 28.05.2019 21:28
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
11
179
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Ответ принят как подходящий

Формула правильная, нужно немного доработать.

  1. Не переводите float в int, потеря данных!
  2. При входе в for переходите от первого лица к n-1

    int people = 20;
    float prize = 1000;
    
    float k = (2 * prize) / ((people) * (people - 1));
    float sum = 0;
    
    for (int i = 1; i < people; ++i)
    {
        var personsPrize = i * k;
        sum += personsPrize;
        Console.WriteLine(personsPrize);
    }
    Console.WriteLine("sum = " + sum);
    

Огромное спасибо. Люди сортируются по их баллам, как мы можем дать одинаковую сумму приза людям с одинаковым баллом?

Cypras 28.05.2019 11:23
stackoverflow.com/questions/56339261/разделить-x-на-y-части Новый вопрос, основанный на этом. @SilentTremor
Cypras 28.05.2019 11:43

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

Две вещи

  1. Неверно, при назначении цен от первое лицо в n-1 один человек не получает приз, правильно от первое лицо n

  2. Действительная базаПриз, отмеченный буквой K,

    k = (2 * приз) / ((люди) * (люди + 1))

Теперь ответ на другой вопрос:

int totalPeople = 20;
float prize = 5000;

List<int> peopleScores = new List<int>();
Random r = new Random();
for (int i = 0; i < totalPeople; ++i)
{
    peopleScores.Add(r.Next(0, 100));
}

var totalPeopleWithScore = peopleScores.Where(x => x > 0).Count();

var groupedScores = peopleScores
    .Where(x => x > 0)
    .ToList()
    .GroupBy(x => x)
    .Select(grp => new
    {
        score = grp.Key,
        peopleScores = grp.ToList()
    })
    .OrderBy(g => g.score)
    .ToList();

var groupCount = groupedScores.Select(x => new { count = x.peopleScores.Count() }).Select(z => z.count).Count();

float basePrizeRate = 2 * prize / totalPeopleWithScore / (totalPeopleWithScore + 1);
Console.WriteLine("Base Price rate: " + basePrizeRate);
float sum = 0;
var leaderboardPosition = 0;
var totalWinners = 0;
foreach (var positionScore in groupedScores)
{
    var countWinner = positionScore.peopleScores.Count();
    Console.WriteLine();
    Console.WriteLine($"On leaderboard position : {groupedScores.Count() - leaderboardPosition} are {countWinner} winners with score: {positionScore.score}");

    float positionPrizePool = 0;
    for (int i = 1; i <= positionScore.peopleScores.Count(); ++i)
    {
        totalWinners++;
        positionPrizePool += totalWinners * basePrizeRate;
    }
    Console.WriteLine("Prize Pool " + positionPrizePool);
    var personPoolPrize = positionPrizePool / positionScore.peopleScores.Count();
    foreach (var x in positionScore.peopleScores)
    {
        Console.WriteLine($"Winner {totalWinners} won: {personPoolPrize}");
        sum += personPoolPrize;
    }
    leaderboardPosition++;
}
Console.WriteLine();

Console.WriteLine("Total Prize: " + sum);
Console.WriteLine("Total Winners: " + totalPeopleWithScore);

Это работает очень хорошо, однако есть ли способ сделать так, чтобы победители, занявшие 1-е, 2-е и 3-е место, получили бонусную сумму по сравнению с остальными? И показ их позиций, например 1-й или 1-й равный, 2-й, 3-й, 4-й и т. д.

Cypras 28.05.2019 23:18

Используя формулу Гаусса. (N*(N+1))/2, я не думаю, что это достижимо теоретически, вы можете извлечь часть цены, скажем, за первые 3 места из всего приза, но у вас возникнут проблемы с более чем одним победителем на позиция.

SilentTremor 29.05.2019 08:06

Ты должен мне пиво, на самом деле глоток пива!!

Используя распределение Гаусса (N*(N+1))/2, вы не можете иметь небольшой отрыв от рангов конкурентов, призы имеют линейный рост https://mathbitsnotebook.com/Algebra2/Sequences/SSGauss.html.

Вам нужно что-то, что увеличивается экспоненциально или с фиксированной пропорцией, я хочу решить вашу проблему с помощью математического подхода, поэтому я буду использовать геометрическую прогрессию https://mathbitsnotebook.com/Algebra2/Sequences/SSGeometric.html

Я не буду добавлять никаких других ответов после этого, вы должны создать свою собственную систему призового фонда!

Для формулы геометрического распределения:

rankPrize = ((1 - distributionFactor) / (1 - distributionFactor ^ winners) * distributionFactor ^ (rank - 1)) * prize

where distributionFactor - is between 0 and 1

Поэкспериментируйте с коэффициентом распределения и выберите правильное значение для вашей системы, я выбрал 0,8, потому что разрыв между призами не такой уж большой!

Итак, начнем, ссылка на скрипку: https://dotnetfiddle.net/qmJnYd для игры и реализации:

static void GaussDistributionPricePool()
        {
            Console.WriteLine("________________________________________________________");
            Console.WriteLine("Begin Gauss distribution price pool");

            int totalPeople = 20;
            float prize = 5000;

            List<int> peopleScores = new List<int>();
            Random r = new Random();
            for (int i = 0; i < totalPeople; ++i)
            {
                peopleScores.Add(r.Next(0, 100));
            }

            var totalPeopleWithScore = peopleScores.Where(x => x > 0).Count();

            var groupedScores = peopleScores
                .Where(x => x > 0)
                .ToList()
                .GroupBy(x => x)
                .Select(grp => new
                {
                    score = grp.Key,
                    peopleScores = grp.ToList()
                })
                .OrderBy(g => g.score)
                .ToList();

            var groupCount = groupedScores.Select(x => new { count = x.peopleScores.Count() }).Select(z => z.count).Count();
            // Gauss formula. (N*(N+1))/2
            // https://mathbitsnotebook.com/Algebra2/Sequences/SSGauss.html
            float basePrizeRate = 2 * prize / totalPeopleWithScore / (totalPeopleWithScore + 1);
            Console.WriteLine("Base Price rate: " + basePrizeRate);
            float sum = 0;
            var leaderboardRank = 0;
            var totalWinners = 0;
            foreach (var positionScore in groupedScores)
            {
                var countWinner = positionScore.peopleScores.Count();
                Console.WriteLine();
                Console.WriteLine("On leaderboard rank : " + (groupedScores.Count() - leaderboardRank) + " are " + countWinner + " winners with score: " + positionScore.score);

                float positionPrizePool = 0;
                for (int i = 1; i <= positionScore.peopleScores.Count(); ++i)
                {
                    totalWinners++;
                    positionPrizePool += totalWinners * basePrizeRate;
                }
                Console.WriteLine("Prize Pool " + positionPrizePool);
                var personPoolPrize = positionPrizePool / positionScore.peopleScores.Count();
                foreach (var x in positionScore.peopleScores)
                {
                    Console.WriteLine("Winner " + totalWinners + " won: " + personPoolPrize);
                    sum += personPoolPrize;
                }
                leaderboardRank++;
            }
            Console.WriteLine();

            Console.WriteLine("Total Prize: " + sum);
            Console.WriteLine("Total Winners: " + totalPeopleWithScore);

            Console.WriteLine("End Gauss distribution price pool");
            Console.WriteLine("________________________________________________________");
        }

Другие вопросы по теме