fork download
  1. import random
  2. from math import sqrt
  3.  
  4. class Dice:
  5. def __init__(self, n, doRandom = True):
  6. self.n = n
  7. if doRandom:
  8. last = -1
  9. while last < 0 or last >= n:
  10. seq = [random.randrange(0,n) for i in xrange(n-1)]
  11. last = n*(n-1)/2-sum(seq)
  12. self.faces = seq+[last]
  13. else:
  14. # Uniform die
  15. self.faces = range(n)
  16. # only compute self.scoreFunc when you need it
  17. self.scoreFunc = None
  18.  
  19. def CalcScoreFunc(self):
  20. # Calculate score(i) = # {faces > i} - # {faces < i}
  21.  
  22. # First calculate deltaScore(i) = score(i)-score(i-1)
  23. # Clearly score(-1) = n
  24. # deltaScore(i) = (# {faces > i} - # {faces > i-1}) -
  25. # (# {faces < i} - # {faces < i-1})
  26. # = -#{faces=i}-#{faces=i-1}
  27.  
  28. deltaScore = [0] * self.n
  29. for face in self.faces:
  30. deltaScore[face] -= 1
  31. if face < self.n - 1:
  32. deltaScore[face + 1] -= 1
  33.  
  34. # Then calculate score
  35. self.scoreFunc = [0] * self.n
  36. self.scoreFunc[0] = self.n + deltaScore[0]
  37. for i in xrange(1, self.n):
  38. self.scoreFunc[i] = self.scoreFunc[i - 1] + deltaScore[i]
  39.  
  40. def Score(self, other):
  41. if self.n != other.n:
  42. raise ValueError("Cannot compare two different sized dice")
  43. if self.scoreFunc == None:
  44. self.CalcScoreFunc()
  45. return sum(self.scoreFunc[otherFace] for otherFace in other.faces)
  46.  
  47. # Return score(i)-(a+bi) where the result has mean 0 and is statistically independent from i
  48. # This is equivalent to removing the linear regression through (i,score(i))
  49. def Delineated(self):
  50. if self.scoreFunc == None:
  51. self.CalcScoreFunc()
  52. avgx = float(self.n-1)/2
  53. avgy = float(sum(self.scoreFunc))/self.n
  54. cov = sum((i-avgx)*(self.scoreFunc[i]-avgy) for i in xrange(self.n))/self.n
  55. varx = float(self.n**2-1)/12
  56. beta = cov/varx
  57. alpha = avgy - beta * avgx
  58. return [self.scoreFunc[i]-(alpha+beta*i) for i in xrange(self.n)]
  59.  
  60. def test1():
  61. for n in [20,50,100]:
  62. for i in xrange(100):
  63. d = Dice(n)
  64. if d.Score(d) != 0:
  65. print "ERROR 1"
  66.  
  67. def test2():
  68. for n in [20,50,100]:
  69. for i in xrange(100):
  70. d1 = Dice(n)
  71. d2 = Dice(n)
  72. if d1.Score(d2) + d2.Score(d1) != 0:
  73. print "ERROR 2"
  74.  
  75. def test3():
  76. for n in [20,50,100]:
  77. for i in xrange(100):
  78. d1 = Dice(n)
  79. d2 = Dice(n, False)
  80. if d1.Score(d2) != 0:
  81. print "ERROR 3"
  82.  
  83. def test4():
  84. for n in [20,50,100]:
  85. for i in xrange(100):
  86. d1 = Dice(n)
  87. delin = d1.Delineated()
  88. sc1 = sum(delin)
  89. if abs(sc1) > 1e-6:
  90. print "ERROR 4"
  91. sc2 = sum(j*delin[j] for j in xrange(n))
  92. if abs(sc2) > 1e-6:
  93. print "ERROR 5"
  94.  
  95. test1()
  96. test2()
  97. test3()
  98. test4()
  99.  
  100. for n in [100,500,1000]:
  101. for testCase in xrange(20):
  102. d1 = Dice(n)
  103. d2 = Dice(n)
  104. del1 = d1.Delineated()
  105. del2 = d2.Delineated()
  106. var1 = sum(z*z for z in del1)
  107. var2 = sum(z*z for z in del2)
  108. cov = sum(del1[i]*del2[i] for i in xrange(n))
  109. corr = cov/sqrt(var1*var2)
  110. print "Testcase #{} of {}-sided die: Var1={:.4f}, Var2={:.4f}, Cov={:.4f}, Corr={:.4f}".format(
  111. testCase+1, n, var1, var2, cov, corr)
  112.  
Success #stdin #stdout 0.23s 129088KB
stdin
Standard input is empty
stdout
Testcase #1 of 100-sided die: Var1=2123.6931, Var2=3231.4062, Cov=-321.4503, Corr=-0.1227
Testcase #2 of 100-sided die: Var1=1559.6718, Var2=3635.2133, Cov=-777.7703, Corr=-0.3266
Testcase #3 of 100-sided die: Var1=961.8871, Var2=1411.0451, Cov=193.2975, Corr=0.1659
Testcase #4 of 100-sided die: Var1=548.0887, Var2=1442.4500, Cov=150.4077, Corr=0.1692
Testcase #5 of 100-sided die: Var1=5151.2439, Var2=1528.8071, Cov=-1958.6193, Corr=-0.6979
Testcase #6 of 100-sided die: Var1=956.3367, Var2=2345.0850, Cov=589.3224, Corr=0.3935
Testcase #7 of 100-sided die: Var1=526.6313, Var2=746.4473, Cov=-17.6182, Corr=-0.0281
Testcase #8 of 100-sided die: Var1=2659.5636, Var2=1095.7254, Cov=277.4989, Corr=0.1626
Testcase #9 of 100-sided die: Var1=1208.5672, Var2=1197.7324, Cov=-286.5290, Corr=-0.2382
Testcase #10 of 100-sided die: Var1=1548.7376, Var2=3463.2313, Cov=-1618.6767, Corr=-0.6989
Testcase #11 of 100-sided die: Var1=1827.0059, Var2=2474.5666, Cov=1004.7878, Corr=0.4726
Testcase #12 of 100-sided die: Var1=932.7189, Var2=690.4579, Cov=88.6222, Corr=0.1104
Testcase #13 of 100-sided die: Var1=2324.1424, Var2=761.6475, Cov=-223.4093, Corr=-0.1679
Testcase #14 of 100-sided die: Var1=1626.9566, Var2=1917.5650, Cov=327.4917, Corr=0.1854
Testcase #15 of 100-sided die: Var1=548.7578, Var2=3517.5866, Cov=-280.5355, Corr=-0.2019
Testcase #16 of 100-sided die: Var1=893.8125, Var2=4966.4686, Cov=1075.5644, Corr=0.5105
Testcase #17 of 100-sided die: Var1=942.0330, Var2=1436.0531, Cov=505.2469, Corr=0.4344
Testcase #18 of 100-sided die: Var1=1626.4394, Var2=3197.4749, Cov=617.1818, Corr=0.2706
Testcase #19 of 100-sided die: Var1=1462.5155, Var2=1461.3606, Cov=736.0434, Corr=0.5035
Testcase #20 of 100-sided die: Var1=2752.8257, Var2=768.2081, Cov=-362.7613, Corr=-0.2495
Testcase #1 of 500-sided die: Var1=34950.4880, Var2=29305.8294, Cov=-4888.0495, Corr=-0.1527
Testcase #2 of 500-sided die: Var1=26889.0303, Var2=205114.1244, Cov=-4736.4323, Corr=-0.0638
Testcase #3 of 500-sided die: Var1=33261.6696, Var2=30697.6624, Cov=-3396.9827, Corr=-0.1063
Testcase #4 of 500-sided die: Var1=79410.4794, Var2=33242.2538, Cov=10753.2223, Corr=0.2093
Testcase #5 of 500-sided die: Var1=34362.8522, Var2=26480.8854, Cov=1165.1587, Corr=0.0386
Testcase #6 of 500-sided die: Var1=68534.1037, Var2=90365.9760, Cov=-55868.6669, Corr=-0.7099
Testcase #7 of 500-sided die: Var1=17785.5178, Var2=90062.3960, Cov=-7008.6282, Corr=-0.1751
Testcase #8 of 500-sided die: Var1=31693.6512, Var2=49216.6461, Cov=25845.5638, Corr=0.6544
Testcase #9 of 500-sided die: Var1=36694.2058, Var2=44836.6520, Cov=16514.6866, Corr=0.4072
Testcase #10 of 500-sided die: Var1=82885.8796, Var2=71302.2215, Cov=58698.6958, Corr=0.7635
Testcase #11 of 500-sided die: Var1=78291.2336, Var2=80724.5623, Cov=13579.4739, Corr=0.1708
Testcase #12 of 500-sided die: Var1=48077.5187, Var2=30064.7741, Cov=12288.9933, Corr=0.3232
Testcase #13 of 500-sided die: Var1=57543.8764, Var2=40971.9314, Cov=-13255.3697, Corr=-0.2730
Testcase #14 of 500-sided die: Var1=57871.2097, Var2=68529.7083, Cov=-25360.0870, Corr=-0.4027
Testcase #15 of 500-sided die: Var1=57788.7913, Var2=64364.0341, Cov=11903.3471, Corr=0.1952
Testcase #16 of 500-sided die: Var1=45931.1376, Var2=60506.9237, Cov=-36020.1270, Corr=-0.6833
Testcase #17 of 500-sided die: Var1=26319.8234, Var2=55479.2129, Cov=-10811.4257, Corr=-0.2829
Testcase #18 of 500-sided die: Var1=33203.6341, Var2=28432.3371, Cov=3781.9876, Corr=0.1231
Testcase #19 of 500-sided die: Var1=81639.4858, Var2=23655.6132, Cov=-1491.9006, Corr=-0.0339
Testcase #20 of 500-sided die: Var1=62373.9474, Var2=59025.4248, Cov=21848.7694, Corr=0.3601
Testcase #1 of 1000-sided die: Var1=118527.1445, Var2=118073.1565, Cov=-19326.3736, Corr=-0.1634
Testcase #2 of 1000-sided die: Var1=177866.0609, Var2=81783.2634, Cov=19304.0638, Corr=0.1601
Testcase #3 of 1000-sided die: Var1=145965.4821, Var2=119209.4810, Cov=-37982.0882, Corr=-0.2879
Testcase #4 of 1000-sided die: Var1=207686.2276, Var2=239793.9854, Cov=-125109.4858, Corr=-0.5606
Testcase #5 of 1000-sided die: Var1=195731.3478, Var2=75559.5164, Cov=-50763.0037, Corr=-0.4174
Testcase #6 of 1000-sided die: Var1=181034.4024, Var2=203863.7939, Cov=-56807.2105, Corr=-0.2957
Testcase #7 of 1000-sided die: Var1=241864.3454, Var2=123731.9276, Cov=9565.7697, Corr=0.0553
Testcase #8 of 1000-sided die: Var1=210499.4498, Var2=219907.5151, Cov=-99248.9937, Corr=-0.4613
Testcase #9 of 1000-sided die: Var1=156011.3488, Var2=231681.3886, Cov=28400.8783, Corr=0.1494
Testcase #10 of 1000-sided die: Var1=81480.1283, Var2=164379.2079, Cov=-2786.3070, Corr=-0.0241
Testcase #11 of 1000-sided die: Var1=240754.0432, Var2=94439.1400, Cov=54832.8899, Corr=0.3636
Testcase #12 of 1000-sided die: Var1=131609.1752, Var2=214103.4988, Cov=-36294.9506, Corr=-0.2162
Testcase #13 of 1000-sided die: Var1=100021.0712, Var2=288755.0151, Cov=-6724.7937, Corr=-0.0396
Testcase #14 of 1000-sided die: Var1=174738.9605, Var2=143480.2268, Cov=-46122.3061, Corr=-0.2913
Testcase #15 of 1000-sided die: Var1=134903.1913, Var2=165698.6621, Cov=-38524.7238, Corr=-0.2577
Testcase #16 of 1000-sided die: Var1=140622.8809, Var2=199736.2268, Cov=32777.3100, Corr=0.1956
Testcase #17 of 1000-sided die: Var1=125452.4311, Var2=253601.8508, Cov=-64253.1336, Corr=-0.3602
Testcase #18 of 1000-sided die: Var1=113250.5348, Var2=155724.7305, Cov=16335.5649, Corr=0.1230
Testcase #19 of 1000-sided die: Var1=139059.0560, Var2=171194.1095, Cov=3493.9591, Corr=0.0226
Testcase #20 of 1000-sided die: Var1=242230.3438, Var2=75478.2060, Cov=-24002.4284, Corr=-0.1775