Если бы у меня было 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);
@EvanTrimboli да, так и есть, так что где-то еще что-то не так, но я не уверен, что это может быть.
Так почему вы изменили вопрос, чтобы исправить формулу? «он печатает действительно большие числа, а не 10 чисел, которые в сумме составляют 1000». не совсем соответствует требованиям сейчас.
Ну, это еще не сумма приза.
Возможно, вы захотите переименовать свой вопрос, чтобы он отражал то, чего вы пытаетесь достичь. Кажется, это проблема с вашей формулой, а не с порядком операций.
Ваша формула арифметической прогрессии всех натуральных чисел, начиная с 1, дает только "треугольные" числа 1,3,6,10,15... 1000 не является треугольным числом, вы не можете выразить 1000 как нужную сумму. Возможно, вам нужно переформулировать условия.
Отредактировал вопрос, не понял, что формула неверна.
Возможно, это лучше подходит для math.stackexchange.com
Это можно сделать с помощью любой монотонной функции. Самое простое решение: P1, 1$, P2, 2$....P19 19$ P20 остальное.
Возможный дубликат Разделить x на y частей
Нет, это не так. Прочитайте вопросы и вы увидите разницу.





Формула правильная, нужно немного доработать.
При входе в 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);
Огромное спасибо. Люди сортируются по их баллам, как мы можем дать одинаковую сумму приза людям с одинаковым баллом?
Добавление ответа на Убедитесь, что призовой фонд не присуждает участникам с равным количеством очков меньше, чем участникам, набравшим худшие баллы.
Две вещи
Неверно, при назначении цен от первое лицо в n-1 один человек не получает приз, правильно от первое лицо n
Действительная базаПриз, отмеченный буквой 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-й и т. д.
Используя формулу Гаусса. (N*(N+1))/2, я не думаю, что это достижимо теоретически, вы можете извлечь часть цены, скажем, за первые 3 места из всего приза, но у вас возникнут проблемы с более чем одним победителем на позиция.
Ты должен мне пиво, на самом деле глоток пива!!
Используя распределение Гаусса (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("________________________________________________________");
}
Похоже на проблему с порядком операций, вам нужны дополнительные скобки вокруг этого выражения:
int k = (2 * (int) prize) / (people * (people - 1));Однако даже с этим исправлением оно в конечном итоге распределяет1210, что больше, чем вашеprize.