【问题标题】:Logarithmic distribution of profits among game winners游戏获胜者之间利润的对数分布
【发布时间】:2013-05-30 18:46:18
【问题描述】:

我有一个赠品,完成后,有一张玩家和他们的得分表。 另一方面,我有一个虚拟的钱罐,我想分配给这些获胜者。我正在寻找一个 SQL 查询或一段 C# 代码来执行此操作。

降序排列的表格如下所示:

UserId | Name | Score | Position | % of winnings | abs. winnings $
00579  | John | 754   | 1        |  ?            | 500 $    
98983  | Sam  | 733   | 2        |  ?            | ?    
29837  | Rick | 654   | 3        |  ?            | ?    <- there are 2 3rd places
21123  | Hank | 654   | 3        |  ?            | ?    <- there are 2 3rd places
99821  | Buck | 521   | 5        |  ?            | ?    <- there is no 4th, because of the 2 3rd places
92831  | Joe  | 439   | 6        |  ?            | ?    <- there are 2 6rd places 
99281  | Jack | 439   | 6        |  ?            | ?    <- there are 2 6rd places 
12345  | Hal  | 412   | 8        |  ?            | ?    
98112  | Mick | 381   | 9        |  ?            | ?    
and so on, until position 50 
98484  | Sue  | 142   | 50       |  ?            | 5 $ 

注意双第 3 和第 6 名。

现在我想在前 50 个职位中分配(虚拟)资金总额(10,000 美元)。 (如果分配的位置(现在是 50)可以是一个变量,那就太好了)。

最大和最小数量(对于 nr 1 和 nr 50)固定为 500 和 5。

是否有人对 SQL 查询或一段 C# 代码有一个好主意来正确地用 % of bonussabsolutewinnings$ 填充列?

我更喜欢这样一个看起来有点对数的分布:(这使得较高的位置相对于较低的位置获得更多)。

.
|.
| .
|  .
|   .
|     .
|        .
|            .
|                  .
|                           .

【问题讨论】:

  • 假设平局玩家赚到同样多的钱,这是不可能的。问题是过度约束。例如,如果第一名有 49 人并列,则您必须支付 24505 美元。您可能永远不会有 49 路平局,但您应该明确说明您关心哪些可能性以及您不关心哪些可能性。

标签: c# sql math polynomial-math logarithm


【解决方案1】:

自 1994 年以来我没有使用过 SQL,但我喜欢 C# :-)。以下可能适合,根据需要调整DistributeWinPot.DistributeWinPot(...)的参数:

private class DistributeWinPot {

    private static double[] GetWinAmounts(int[] psns, double TotWinAmounts, double HighWeight, double LowWeight) {
        double[] retval = new double[psns.Length];
        double fac = -Math.Log(HighWeight / LowWeight) / (psns.Length - 1), sum = 0;
        for (int i = 0; i < psns.Length; i++) {
            sum += retval[i] = (i == 0 || psns[i] > psns[i - 1] ? HighWeight * Math.Exp(fac * (i - 1)) : retval[i - 1]);
        }
        double scaling = TotWinAmounts / sum;
        for (int i = 0; i < psns.Length; i++) {
            retval[i] *= scaling;
        }
        return retval;
    }

    public static void main(string[] args) {
        // set up dummy data, positions in an int array
        int[] psns = new int[50];
        for (int i = 0; i < psns.Length; i++) {
            psns[i] = i+1;
        }
        psns[3] = 3;
        psns[6] = 6;
        double[] WinAmounts = GetWinAmounts(psns, 10000, 500, 5);
        for (int i = 0; i < psns.Length; i++) {
            System.Diagnostics.Trace.WriteLine((i + 1) + "," + psns[i] + "," + string.Format("{0:F2}", WinAmounts[i]));
        }
    }
}

该代码的输出是:

1,1,894.70
2,2,814.44
3,3,741.38
4,3,741.38
5,5,614.34
6,6,559.24
7,6,559.24
8,8,463.41
9,9,421.84
10,10,384.00
11,11,349.55
12,12,318.20
13,13,289.65
14,14,263.67
15,15,240.02
16,16,218.49
17,17,198.89
18,18,181.05
19,19,164.81
20,20,150.03
21,21,136.57
22,22,124.32
23,23,113.17
24,24,103.02
25,25,93.77
26,26,85.36
27,27,77.71
28,28,70.74
29,29,64.39
30,30,58.61
31,31,53.36
32,32,48.57
33,33,44.21
34,34,40.25
35,35,36.64
36,36,33.35
37,37,30.36
38,38,27.64
39,39,25.16
40,40,22.90
41,41,20.85
42,42,18.98
43,43,17.27
44,44,15.72
45,45,14.31
46,46,13.03
47,47,11.86
48,48,10.80
49,49,9.83
50,50,8.95

【讨论】:

  • 看起来很有趣。但是,我没有得到HighWeight,你输入500,但最高赢额是894.70??对吗?
  • 是的,我有 500 和 5,正如您在问题中所建议的那样。但是,它需要使权重的总和达到 10000。所以它必须缩放初始结果,这就是 DistributeWinPot.DistributeWinPot(...) 中的第二个 for 循环所做的事情。这有意义吗?
  • 是的,这是有道理的。我现在对输入值进行了一些尝试,我发现当我提供一个很容易适合 50 个获胜者的总赢额时,我的 1 号总是获得更高的金额,而 2 号总是获得最大金额。这对我来说意义不大。
  • 我不明白您的问题。可以举个例子吗?
  • 您知道如何使支付曲线或多或少更陡峭吗?
【解决方案2】:

那么这个怎么样?

Select userid, log(score),
   10000 * log(score) / 
      (Select Sum(log(score)) 
       From TableName
       Where score >=
            (Select Min(score) 
             from (Select top 50 score     
                   From TableName
                   Order By score desc) z)) 
From TableName
Order By score desc

【讨论】:

  • 我运行了这个查询,但结果并不像我正在搜索的那样。我在示例中添加了更多内容。就像第 1 名和第 50 名的绝对金额一样。固定为 500 和 5。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多