Skip to content

Instantly share code, notes, and snippets.

@ryannow
Last active May 7, 2016 09:00
Show Gist options
  • Save ryannow/72811664be09e14fa8baa0b3ee3bddad to your computer and use it in GitHub Desktop.
Save ryannow/72811664be09e14fa8baa0b3ee3bddad to your computer and use it in GitHub Desktop.
Script to calculate NBA lottery odds. Includes all pick swaps and transfers relevant to the top 14 picks.
import collections
import csv
chances = {
'PHI': 250,
'LAL': 199,
'BOS': 156,
'PHX': 119,
'MIN': 88,
'NOP': 63,
'TOR': 43,
'SAC': 19,
'DEN': 19,
'MIL': 18,
'ORL': 8,
'UTA': 7,
'WAS': 6,
'CHI': 5,
}
# Dict above does not maintain order so use this instead to fill picks 4-14
order = ['PHI', 'LAL', 'BOS', 'PHX', 'MIN', 'NOP', 'TOR',
'SAC', 'DEN', 'MIL', 'ORL', 'UTA', 'WAS', 'CHI']
def chancesLeft(used):
total = 1000
for team in used:
total -= chances[team]
return total
# A node contains a list of teams that won the first n spots and the probability we got to that point.
# Its child nodes are nodes representing each sequence of n+1 teams starting with the teams we already have.
class Node:
def __init__(self, prob, winners):
self.prob = prob
self.winners = winners
self.children = []
def addChildren(self):
for key, value in chances.items():
if value > 0:
if key not in self.winners:
nextProb = value / float(chancesLeft(self.winners))
newProb = self.prob * nextProb
newWinners = self.winners + [key]
self.children.append(Node(self.prob * nextProb, self.winners + [key]))
def addDescendants(self, depth):
if depth > 0:
self.addChildren()
for child in self.children:
child.addDescendants(depth-1)
# Returns all leaf nodes at bottom of tree; does not return internal descendants.
def getAllDescendants(self):
fullList = []
if len(self.children) == 0:
return [self]
for child in self.children:
fullList.extend(child.getAllDescendants())
return fullList
"""
Print a CSV with each team's odds of each pick.
Since Philly has many likely scenarios in which they got multiple picks,
and the likelihood of getting the Lakers pick depends on their own result to some degree,
break their results out separately to find likelihood of each outcome.
"""
def main():
root = Node(1, [])
root.addDescendants(3)
probs = {}
phiOutcomes = collections.defaultdict(int)
for team in order:
probs[team] = [0]*14
for desc in root.getAllDescendants():
phiPicks = ""
for idx, val in enumerate(doTransfers(fullList(desc.winners))):
probs[val][idx] += desc.prob
if val == "PHI":
phiPicks += str(idx + 1)
phiOutcomes[phiPicks] += desc.prob
print phiOutcomes
printCSV(probs)
def fullList(winners):
output = winners
for team in order:
if team not in winners:
output.append(team)
return output
def doTransfers(results):
afterswap = results
# In all cases, find pick in pre-swap results array, swap location in afterswap.
SACindex = results.index('SAC')
PHIindex = results.index('PHI')
if SACindex < PHIindex:
afterswap[SACindex] = 'PHI'
afterswap[PHIindex] = 'SAC'
TORindex = results.index('TOR')
DENindex = results.index('DEN')
if TORindex < DENindex:
afterswap[TORindex] = 'DEN'
afterswap[DENindex] = 'TOR'
LALindex = results.index('LAL')
if LALindex >= 3:
afterswap[LALindex] = 'PHI'
if SACindex >= 10:
afterswap[SACindex] = 'CHI'
WASindex = results.index('WAS')
if WASindex >= 3:
afterswap[WASindex] = 'PHX'
return afterswap
def printCSV(probs):
with open('lotto_odds.csv', 'wb') as csvfile:
oddswriter = csv.writer(csvfile, delimiter=',')
for team in order:
oddswriter.writerow([team] + probs[team])
if __name__ == '__main__':
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment