-1

I am trying to write a mock lottery simulator as a thought excercize and for some introductory python practice, where each team would have 2x the odds of getting the first pick as the team that preceded them in the standings. The code below works (although I am sure there is a more efficient way to write it), but now I would like to figure out a way to find each individual teams odds of getting a certain draft spot based on their odds. I believe there are 12! ways for the order to be set, so it would be next to impossible to compute by hand. Is there a way to run a simulation in python (say 10 million times) and see what percentage of those times each team ends up in a certain spot of the shuffled list?

import random
from time import sleep

first = [1*['team 1']]
second = [2*['team 2']]
third = [4*['team 3']]
fourth = [8*['team 4']]
fifth = [16*['team 5']]
sixth = [32*['team 6']]
seventh = [64*['team 7']]
eighth = [128*['team 8']]
ninth = [256*['team 9']]
tenth = [512*['team 10']]
eleventh = [1024*['team 11']]
twelfth = [2048*['team 12']]

total = []

for i in first:
    for x in i:
        total.append(x)

for i in second:
    for x in i:
        total.append(x)

for i in third:
    for x in i:
        total.append(x)

for i in fourth:
    for x in i:
        total.append(x)

for i in fifth:
    for x in i:
        total.append(x)

for i in sixth:
    for x in i:
        total.append(x)

for i in seventh:
    for x in i:
        total.append(x)

for i in eighth:
    for x in i:
        total.append(x)

for i in ninth:
    for x in i:
        total.append(x)

for i in tenth:
    for x in i:
        total.append(x)

for i in eleventh:
    for x in i:
        total.append(x)

for i in twelfth:
    for x in i:
        total.append(x)

random.shuffle(total)

order = []
for i in total:
    if i not in order:
        order.append(i)

print('the twelfth pick goes to {}'.format(order[11]))
sleep(1)
print('the eleventh pick goes to {}'.format(order[10]))
sleep(1)
print('the tenth pick goes to {}'.format(order[9]))
sleep(1)
print('the ninth pick goes to {}'.format(order[8]))
sleep(1)
print('the eighth pick goes to {}'.format(order[7]))
sleep(1)
print('the seventh pick goes to {}'.format(order[6]))
sleep(2)
print('the sixth pick goes to {}'.format(order[5]))
sleep(2)
print('the fifth pick goes to {}'.format(order[4]))
sleep(2)
print('the fourth pick goes to {}'.format(order[3]))
sleep(3)
print('the third pick goes to {}'.format(order[2]))
sleep(3)
print('the second pick goes to {}'.format(order[1]))
sleep(3)
print('the first pick goes to {}'.format(order[0]))
tim82
  • 1
  • I would suggest improving the code you have first. It is difficult for me to understand what your code even does. For instance, your line `twelfth = [2048*['team 12']]` makes a list with 2048 identical elements that all say `team 12`. That makes little sense to me. After testing your code I can see how this will work, but it is sooooooooooo inefficient. Running this 10 million times would take too long (even if you remove the sleep calls). Try improving this efficiency and extending to a Monte Carlo sim will be much easier! – Hoog Jun 20 '19 at 19:54
  • thanks hoog, i did those first 12 lists that was because it was the simplest way that I could think of to create a master list with the appropriate number of lottery balls for each team in it (i am relatively new to this, so if you know of a more efficient way to do it please let me know). twelfth = [2048*['team 12']] creates a list with the team that finished in last places name in it 2048, so when i append all of the individual teams list to the total list they will have the appropriate number of chances at the first pick. – tim82 Jun 20 '19 at 20:03

3 Answers3

1

Instead of doing your sampling like this, I would use a discrete distribution for the probability of getting the team i, and sample using random.choices. We update the distribution after the sampling by discarding all the tickets from that team (since it cannot appear again).

from random import choices
ticket_amounts = [2**i for i in range(12)]
teams = [ i + 1 for i in range(12)]
for i in range(12):
    probabilities = [count/sum(ticket_amounts) for count in ticket_amounts]
    team_picked = choices(teams, probabilities)[0]
    print("team picked is{}".format(team_picked))
    # update probabilities by discarding all the tickets
    # belonging to picked team
    ticket_amounts[team_picked-1] = 0



Juan Carlos Ramirez
  • 2,054
  • 1
  • 7
  • 22
0

Here is what you want I think, but as the other comment said it runs very slow and I would not try 10 million times, its slow enough as is.

from collections import Counter
for i in range(1,10000):
    random.shuffle(total)
    countList.append(total[0])

print Counter(countList)

add the for loop to the end of your code and the import at the top.

lc74
  • 134
  • 8
0

Here is a way to do it (it fast enough to run 1M time in about 15 min, so for 10 millions you would probably need to wait a few hours):

import numpy as np
from collections import Counter

n_teams = 12
n_trials = int(1e4)

probs = [ 2**i for i in range(0,n_teams) ]
probs = [ prob_i / sum(probs) for prob_i in probs ]

lottery_results = np.zeros([n_trials, n_teams],dtype=np.int8) # to store the positions at each lottery
for i in range(n_trials):
    lottery_results[i,:] = np.random.choice(n_teams, n_teams, replace=False, p=probs)

for i in range(n_teams):
    positions = Counter(lottery_results[:,i])
    print("Team {}".format(i), dict(sorted(positions.items())))
Nakor
  • 1,484
  • 2
  • 13
  • 23