Many people start playing the lottery for fun, but for some this activity turns into a habit which eventually escalates into addiction. Like other compulsive gamblers, lottery addicts soon begin spending from their savings and loans, they start to accumulate debts, and eventually engage in desperate behaviors like theft.
A medical institute that aims to prevent and treat gambling addictions wants to build a dedicated mobile app to help lottery addicts better estimate their chances of winning. The institute has a team of engineers that will build the app, but they need us to create the logical core of the app and calculate probabilities.
For the first version of the app, they want us to focus on the 6/49 lottery and build functions that enable users to answer questions like:
Let's start by creating a core functions to find factorials and combinations which will be vital for calculating probabilites.
# Function to find factorial
def factorial(n):
factorial = 1
for i in range(n, 0, - 1):
factorial *= i
return factorial
# Function to find combination
def combinations(n, k):
numerator = factorial(n)
denominator = factorial(k) * factorial(n - k)
return numerator / denominator
Now we can use these functions to calculate the probability of winning the 6/49 lottery with just 1 ticket. The user can input a list of 6 numbers and see how likely they are to win.
# Function to find probability of winning lottery with one ticket
def one_ticket_probability(list_of_6):
# Only accept lists of 6
if len(list_of_6) != 6:
return "Please enter 6 numbers"
# Only accept whole numbers
for n in list_of_6:
if type(n) != int:
return "Must be whole numbers"
# Only accept numbers between 1 and 49
if n == 0 or n > 49:
return "Numbers must be between 1 and 49"
# Total outcomes
outcomes = combinations(49, len(list_of_6))
# Total successful ooutcomes
succesful_outcomes = 1
percentage = (succesful_outcomes / outcomes) * 100
return "You have a {:8f}% chance of winning the lottery with these numbers.".format(percentage)
test = one_ticket_probability([1, 2, 3, 4, 5, 7])
test
'You have a 0.000007% chance of winning the lottery with these numbers.'
Well, those odds aren't very good. Let's have a look at how the lottery has gone in practice. I am going to read in a dataset coming from the national 6/49 lottery game in Canada .The data set has data for 3,665 drawings, dating from 1982 to 2018.
# Import Pandas
import pandas as pd
# Read into DataFrame
drawings = pd.read_csv("649.csv")
# Number of columns and rows
print(drawings.shape)
# Show top 3 rows
drawings.head(3)
(3665, 11)
PRODUCT | DRAW NUMBER | SEQUENCE NUMBER | DRAW DATE | NUMBER DRAWN 1 | NUMBER DRAWN 2 | NUMBER DRAWN 3 | NUMBER DRAWN 4 | NUMBER DRAWN 5 | NUMBER DRAWN 6 | BONUS NUMBER | |
---|---|---|---|---|---|---|---|---|---|---|---|
0 | 649 | 1 | 0 | 6/12/1982 | 3 | 11 | 12 | 14 | 41 | 43 | 13 |
1 | 649 | 2 | 0 | 6/19/1982 | 8 | 33 | 36 | 37 | 39 | 41 | 9 |
2 | 649 | 3 | 0 | 6/26/1982 | 1 | 6 | 23 | 24 | 27 | 39 | 34 |
# Show bottom 3 rows
drawings.tail(3)
PRODUCT | DRAW NUMBER | SEQUENCE NUMBER | DRAW DATE | NUMBER DRAWN 1 | NUMBER DRAWN 2 | NUMBER DRAWN 3 | NUMBER DRAWN 4 | NUMBER DRAWN 5 | NUMBER DRAWN 6 | BONUS NUMBER | |
---|---|---|---|---|---|---|---|---|---|---|---|
3662 | 649 | 3589 | 0 | 6/13/2018 | 6 | 22 | 24 | 31 | 32 | 34 | 16 |
3663 | 649 | 3590 | 0 | 6/16/2018 | 2 | 15 | 21 | 31 | 38 | 49 | 8 |
3664 | 649 | 3591 | 0 | 6/20/2018 | 14 | 24 | 31 | 35 | 37 | 48 | 17 |
Each row is a different draw. I am now going to extract each draw and create a fucntion which takes a list of 6 numbers from a user and checks to see if those 6 numbers have ever won:
# Extract lottery draws from dataset
def extract_numbers(row):
the_list = []
for i in row[4:10]:
the_list.append(i)
return set(the_list)
# Apply function to Dataset
winning_numbers = drawings.apply(extract_numbers, axis=1)
# Function to find if numbers have ever won before
def check_historical_occurence(user_nums):
user_nums = set(user_nums)
matches = 0
for sets in winning_numbers:
if user_nums == sets:
matches += 1
return 'Your numbers have won the lottery the following number of times: {} .'.format(matches)
# Test
test = check_historical_occurence([4, 41, 11, 12, 43, 14])
test
'Your numbers have won the lottery the following number of times: 0 .'
The next function will take in a list of 6 numbers and return both the probability of winning and the number of times those numbers have won in past draws.
# Function to show probability and historic occurances
def probability_and_historic(user_nums):
a = check_historical_occurence(user_nums)
b = one_ticket_probability(user_nums)
return """
{}
{}
""".format(a, b)
# Test
print(probability_and_historic([4, 41, 11, 12, 43, 14]))
Your numbers have won the lottery the following number of times: 0 . You have a 0.000007% chance of winning the lottery with these numbers.
These odds are very bad. However, some people buy multiple tickets. Let's see if this improves their odds:
# Function to check probability with multiple tickets
def multi_ticket_probability(n):
outcomes = combinations(49, 6)
success_outcomes = n
percentage = (success_outcomes / outcomes) * 100
return "You have a {:8f}% chance of winning the lottery with {} tickets".format(percentage, n)
# Test
for i in range(10000, 100000, 20000):
print(multi_ticket_probability(i))
print("-----------------------------------------------------")
You have a 0.071511% chance of winning the lottery with 10000 tickets ----------------------------------------------------- You have a 0.214534% chance of winning the lottery with 30000 tickets ----------------------------------------------------- You have a 0.357556% chance of winning the lottery with 50000 tickets ----------------------------------------------------- You have a 0.500579% chance of winning the lottery with 70000 tickets ----------------------------------------------------- You have a 0.643601% chance of winning the lottery with 90000 tickets -----------------------------------------------------
Wow, that didn't help very much! Even with 90,000 tickets you still only have a 0.64% chance of winning. So, we know that matching 6 numbers is very tough but what about matching less than 6 and winning a smaller prize?
# Function to check probabilites of matching 5, 4, 3 and 2 numbers
def probability_less_6(n):
if n < 2 or n > 6 or type(n) != int:
return "Invalid number"
number_combinations = combinations(6, n)
success_per_combination = combinations(43, 6-n)
successful_outcomes = number_combinations * success_per_combination
outcomes = combinations(49, 6)
percentage = (successful_outcomes / outcomes) * 100
return "You have a {:8f}% chance of matching {} numbers".format(percentage, n)
# Test
for i in range(5, 1, -1):
print(probability_less_6(i))
print("-----------------------------------------------------")
You have a 0.001845% chance of matching 5 numbers ----------------------------------------------------- You have a 0.096862% chance of matching 4 numbers ----------------------------------------------------- You have a 1.765040% chance of matching 3 numbers ----------------------------------------------------- You have a 13.237803% chance of matching 2 numbers -----------------------------------------------------
# Function to check probabilites of matching at least 5, 4, 3 and 2 numbers
def probability_at_least(n):
if n < 2 or n > 6 or type(n) != int:
return "Invalid number"
number_combinations = combinations(6, n)
success_per_combination = combinations(44, 6-n)
successful_outcomes = number_combinations * success_per_combination
outcomes = combinations(49, 6)
percentage = (successful_outcomes / outcomes) * 100
return "You have a {:8f}% chance of matching at least {} numbers".format(percentage, n)
# Test
for i in range(5, 1, -1):
print(probability_at_least(i))
print("-----------------------------------------------------")
You have a 0.001888% chance of matching at least 5 numbers ----------------------------------------------------- You have a 0.101474% chance of matching at least 4 numbers ----------------------------------------------------- You have a 1.894190% chance of matching at least 3 numbers ----------------------------------------------------- You have a 14.561583% chance of matching at least 2 numbers -----------------------------------------------------
The first function above shows the probability of matching exactly 2, 3, 4 or 5 numbers whilst the second matches at least 2, 3, 4 or 5 numbers. As expected the probability gets much better the less numbers we need to match. However, prizes for matching 2 numbers are low and the odds still aren't very good.
It's clear at this point that playing the lottery is not a wise investment. However, perhaps all the numbers are a bit dull and aren't enough to persuade someone how unlikely they are to win. I am going to write a final function that will output a comparison between winning the lottery with 1 ticket to other unlikely events. The events that I will be comparing to are the following:
Killed by a shark = 1 in 3.7 million Succesfully apply to be a NASA astronout = 1 in 1525 Injured by a toilet = 1 in 10000 Struck by lightning = 1 in 114195 Meet love of your life on any given day = 1 in 562 Win an Olympic Gold Medal = 1 in 662000 Win an Oscar = 1 in 115000
# Import random module
import random
# Lottery outcomes
lottery = 13983816
# Comparison function
def compare_odds():
n = random.randint(1, 7)
if n == 1:
return "You are {} times more likely to be killed by a shark than win the 6/49 lottery".format(round(lottery
/ 3700000, 2))
if n == 2:
return "You are {} times more likely to succesfully apply to be a NASA Astronaut than win the 6/49 lottery".format(round(lottery
/ 1525, 2))
if n == 3:
return "You are {} times more likely to be injured by a toilet than win the 6/49 lottery".format(round(lottery
/ 10000, 2))
if n == 4:
return "You are {} times more likely to be struck by lightning than win the 6/49 lottery".format(round(lottery
/ 114195, 2))
if n == 5:
return "You are {} times more likely to meet the love of your life tomorrow than win the 6/49 lottery".format(round(lottery
/ 562, 2))
if n == 6:
return "You are {} times more likely to win an Olympic Gold than win the 6/49 lottery".format(round(lottery / 662000, 2))
if n == 7:
return "You are {} times more likely to win an Oscar than win the 6/49 lottery".format(round(lottery / 3700000, 2))
# Test
compare_odds()
'You are 122.46 times more likely to be struck by lightning than win the 6/49 lottery'
The odds are to win the 6/49 are very bad. Even if you buy many tickets or are happy to match a few numbers. The medical institute need to use the odds, create the app and help those who are adddicted.