【问题标题】:Divide x into y parts by decreasing amount通过减少量将 x 分成 y 部分
【发布时间】:2019-10-13 14:23:46
【问题描述】:

如果我有 1000 美元(可变),我想把这笔钱分成 20 个(可变)人,但不是平均分配给每个人,而是想给第一个人更多,然后第二人称等

所以第 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 大。
  • @EvanTrimboli 是的,确实如此,所以某处还有其他问题,但我不确定它可能是什么。
  • 那么你为什么要改变问题来更正公式呢? “它打印的是非常高的数字,而不是总共 1000 个的 10 个数字。”现在真的不合算了。
  • 好吧,它仍然不包括奖金价值。
  • Divide x into y parts的可能重复

标签: c# algorithm unity3d math


【解决方案1】:

公式正确,需要稍加修改。

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

【讨论】:

【解决方案2】:

Ensure prize pool doesn't award tied participants less than participants who scored worse添加答案

两件事

  1. 不正确,当分配价格从第一人到第n-1人时,一个人没有中奖,正确的是从第一人到第n >

  2. 用 K 标记的有效 basePrize 是

    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 或第 1 相等、第 2、第 3、第 4 等
  • 使用高斯公式。 (N*(N+1))/2,我认为理论上是无法实现的,您可以从整个奖金中提取前 3 个位置的价格部分,但您将无法处理一个以上的获奖者位置。
【解决方案3】:

你欠我一杯啤酒,其实是一大杯啤酒!!

使用高斯分布 (N*(N+1))/2 你不能比竞争对手的排名有微小的差距,奖金线性增加https://mathbitsnotebook.com/Algebra2/Sequences/SSGauss.html

你需要的是呈指数增长或以固定比率增长的东西,我想用数学方法解决你的问题,所以我将使用几何级数https://mathbitsnotebook.com/Algebra2/Sequences/SSGeometric.html

我不会在这个之后添加任何其他答案,您必须建立自己的奖池系统!

对于几何分布公式为:

rankPrize = ((1 - 分布因子) / (1 - 分布因子 ^ 获胜者)* distributionFactor ^(排名 - 1))* 奖金

在哪里 distributionFactor - 介于 0 和 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("________________________________________________________");
        }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-07-08
    • 2020-11-14
    • 1970-01-01
    • 2019-06-15
    • 2019-08-21
    • 1970-01-01
    • 2019-12-20
    相关资源
    最近更新 更多