Advertisement
creamygoat

Tentative Lotto Odds Calculations

Mar 9th, 2014
333
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 5.34 KB | None | 0 0
  1. from __future__ import division
  2. from math import *
  3. import random
  4. import os
  5.  
  6. # Pretty
  7.  
  8. def MaxDP(x, n):
  9.   s = '%.*f' % (n, x)
  10.   if '.' in s:
  11.     while s[-1:] == '0':
  12.       s = s[:-1]
  13.     if s[-1:] == '.':
  14.       s = s[:-1]
  15.   return s
  16.  
  17. # n choose k
  18.  
  19. def C(n, k):
  20.   if k >= 0 and k <= n:
  21.     if k == 0 or k == n:
  22.       Result = 1
  23.     else:
  24.       if n < 4:
  25.         Result = n
  26.       else:
  27.         if k <= (n // 2):
  28.           j = k
  29.         else:
  30.           j = n - k
  31.         Numerator = 1
  32.         Divisor = 1
  33.         i = 1
  34.         while i <= j:
  35.           Numerator *= (n - j + i)
  36.           Divisor *= i
  37.           i += 1
  38.         Result = Numerator / Divisor
  39.   else:
  40.     Result = 0
  41.   return Result
  42.  
  43. # Permutations of k items drawn from n items
  44.  
  45. def P(n, k):
  46.   Result = 1
  47.   Limit = n - k
  48.   x = n
  49.   while x > Limit:
  50.     Result *= x
  51.     x -= 1
  52.   return Result
  53.  
  54. # Combinations of k items drawn from n items which include
  55. # exactly j specified matches.
  56.  
  57. def J(n, k, j):
  58.   return C(n - j, k - j)
  59.  
  60. # (Faulty) Lotto odds
  61.  
  62. def B(n, k, j, b):
  63.   return (C(k, j) * C(1, b) * C(n - k - 1, k - j - b)) / C(n, k)
  64.  
  65. # >>> 1/B(40, 6, 6, 0)
  66. # 3838380.0
  67. # >>> 1/B(40, 6, 5, 1)
  68. # 639730.0
  69. # >>> 1/B(40, 6, 5, 0)
  70. # 19385.757575757576
  71. # >>> 1/B(40, 6, 4, 1)
  72. # 7754.303030303031
  73. # >>> 1/B(40, 6, 4, 0)
  74. # 484.64393939393943
  75. # >>> 1/B(40, 6, 3, 1)
  76. # 363.4829545454545
  77. # >>> 1/B(40, 6, 3, 0)
  78. # 35.17576979472141
  79.  
  80. # Slosh's formula:
  81.  
  82. def Zb(n, k, j):
  83.   return C(k,j)*C(n-k-1,k-j)/C(n,k)*1/(n-k)
  84.  
  85. def Zn(n, k, j):
  86.   return C(k,j)*C(n-k-1,k-j)/C(n,k)*(1 - 1/(n-k))
  87.  
  88. # Simulation
  89.  
  90. def DieRoll(n):
  91.   return 1 + int(floor(n * random.random()))
  92.  
  93. def Draw(n, k):
  94.   # A boring sequence is statistically as good as any other to win even if
  95.   # Lotto forbids the customer to make such a selection and risk sharing
  96.   # their prize with many other people who think runs of numbers are great.
  97.   Line = list(range(1, k + 1))
  98.   LineBonus = k + 1
  99.   Bag = list(range(1, n + 1))
  100.   Drawn = []
  101.   for i in range(k):
  102.     Drawn.append(Bag.pop(DieRoll(len(Bag)) - 1))
  103.   Bonus = Bag.pop(DieRoll(len(Bag)) - 1)
  104.   NumMatches = 0
  105.   for x in Line:
  106.     if x in Drawn:
  107.       NumMatches += 1
  108.   return (NumMatches, Bonus == LineBonus)
  109.  
  110. def WinDist(n, k, Trials):
  111.   H = [(0, 0) for j in range(k + 1)]
  112.   i = 0
  113.   while i < Trials:
  114.     i += 1
  115.     (m, b) = Draw(n, k)
  116.     if b:
  117.       H[m] = (H[m][0], H[m][1] + 1)
  118.     else:
  119.       H[m] = (H[m][0] + 1, H[m][1])
  120.   Eta = 1/Trials
  121.   N = [(Eta * x[0], Eta * x[1]) for x in H]
  122.   return N
  123.  
  124. # More pretty
  125.  
  126. def OddsStr(x, DP=None):
  127.   try:
  128.     Odds = 1/x
  129.     if DP is None:
  130.       DP = max(0, 2 - int(floor(log10(Odds))))
  131.     return '1:' + MaxDP(Odds, DP)
  132.   except (ZeroDivisionError):
  133.     return 'None'
  134.  
  135. def OddsH(H, DP=None):
  136.   return [(OddsStr(x[0], DP), OddsStr(x[1], DP)) for x in H]
  137.  
  138. def PrintLottoH(H):
  139.   PLose = sum(H[0]) + sum(H[1]) + sum(H[2]) + H[3][0]
  140.   DivRecs = {
  141.     1: (H[6][0] + H[6][1], '6 balls'),
  142.     2: (H[5][1], '5 balls + bonus'),
  143.     3: (H[5][0], '5 balls, no bonus'),
  144.     4: (H[4][1], '4 balls + bonus'),
  145.     5: (H[4][0], '4 balls, no bonus'),
  146.     6: (H[3][1], '3 balls + bonus')
  147.   }
  148.   PWin = 0
  149.   for d in sorted(DivRecs):
  150.     (p, Desc) = DivRecs[d]
  151.     PWin += p
  152.     print 'Division %d (%s): %s' % (d, Desc, OddsStr(p))
  153.   print 'Any division: ' + OddsStr(PWin)
  154.   print 'P(No luck): ' + str(PLose)
  155.  
  156. # >>> H = WinDist(40, 6, 50000000)
  157. # >>> PrintLottoH(H)
  158. # Division 1 (6 balls): 1:7142857
  159. # Division 2 (5 balls + bonus): 1:617284
  160. # Division 3 (5 balls, no bonus): 1:19904
  161. # Division 4 (4 balls + bonus): 1:16573
  162. # Division 5 (4 balls, no bonus): 1:466
  163. # Division 6 (3 balls + bonus): 1:1198
  164. # Any division: 1:323
  165. # P(No luck): 0.99690874
  166. # >>> H
  167. # [(0.34190612, 0.00847088), (0.42398538, 0.01088244), (0.17660452000000001, 0.00470074), (0.03035866, 0.00083488), (0.00214404, 6.034e-05), (5.024e-05, 1.62e-06), (1.4e-07, 0.0)]
  168. # >>> OddsH(H)
  169. # [('1:2.92', '1:118'), ('1:2.36', '1:91.9'), ('1:5.66', '1:213'), ('1:32.9', '1:1198'), ('1:466', '1:16573'), ('1:19904', '1:617284'), ('1:7142857', 'None')]
  170.  
  171. # >>> H = WinDist(40, 6, 1000000000)
  172. > >> PrintLottoH(H)
  173. # Division 1 (6 balls): 1:4032258
  174. # Division 2 (5 balls + bonus): 1:621118
  175. # Division 3 (5 balls, no bonus): 1:19390
  176. # Division 4 (4 balls + bonus): 1:16413
  177. # Division 5 (4 balls, no bonus): 1:469
  178. # Division 6 (3 balls + bonus): 1:1197
  179. # Any division: 1:324
  180. # P(No luck): 0.996917296
  181. # >>> H
  182. # [(0.34188522200000004, 0.008488078000000001), (0.424051646, 0.010917859), (0.17652759, 0.00470585), (0.030341051, 0.000835703), (0.002132643, 6.0927e-05), (5.1573e-05, 1.61e-06), (2.43e-07, 5e-09)]
  183. # >>> OddsH(H)
  184. # [('1:2.92', '1:118'), ('1:2.36', '1:91.6'), ('1:5.66', '1:213'), ('1:33', '1:1197'), ('1:469', '1:16413'), ('1:19390', '1:621118'), ('1:4115226', '1:200000000')]
  185.  
  186. # >>> H1 = [(Zn(40,6,j), Zb(40,6,j)) for j in range(7)]
  187. # >>> OddsH(H1)
  188. # [('1:3.57', '1:118'), ('1:2.78', '1:91.6'), ('1:6.44', '1:213'), ('1:36.2', '1:1196'), ('1:499', '1:16478'), ('1:19973', '1:659116'), ('1:3954695', '1:130504920')]
  189. #
  190. # >>> PrintLottoH(H1)
  191. # Division 1 (6 balls): 1:3838380
  192. # Division 2 (5 balls + bonus): 1:659116
  193. # Division 3 (5 balls, no bonus): 1:19973
  194. # Division 4 (4 balls + bonus): 1:16478
  195. # Division 5 (4 balls, no bonus): 1:499
  196. # Division 6 (3 balls + bonus): 1:1196
  197. # Any division: 1:339
  198. # P(No luck): 0.847048647668
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement