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.
In this project, we are going to contribute to the development of a mobile app by writing a couple of functions that are mostly focused on calculating probabilities. The app is aimed to both prevent and treat lottery addiction by helping people better estimate their chances of winning.
The app idea comes from a medical institute which is specialized in treating gambling addictions. The institute already 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 can answer users the following questions:
Our goal in this project is to answer the following questions
- What is the probability of winning the big prize with a single ticket?
- What is the probability of winning the big prize if we play 40 different tickets (or any other number)?
- What is the probability of having at least five (or four, or three, or two) winning numbers on a single ticket?
The data set we ae using has 3665 drawings, dating from 1982 to 2018.
def factorial(n):
num = 1
for i in range(n):
num *= i + 1
return num
def combinations(n, k):
numerator = factorial(n)
denominator = factorial(n-k) * factorial(k)
return numerator/denominator
One-ticket Probability
We need to build a function that calculates the probability of winning the big prize for any given ticket. For each drawing, six numbers are drawn from a set of 49, and a player wins the big prize if the six numbers on their tickets match all six numbers.
The engineer team told us that we need to be aware of the following details when we write the function:
- Inside the app, the user inputs six different numbers from 1 to 49.
- Under the hood, the six numbers will come as a Python list and serve as an input to our function.
- The engineering team wants the function to print the probability value in a friendly way — in a way that people without any probability training are able to understand.
Below, we write the one_ticket_probability()
function, which takes in a list of six unique numbers and prints the probability of winning in a way that’s easy to understand.
def one_ticket_probability(ls):
outcome = combinations(49,6)
probability_one_ticket = 1/outcome
perc = probability_one_ticket * 100
print('''Your chances to win the big prize with the numbers {} are {:.7f}%.
In other words, you have a 1 in {:,} chances to win.'''.format(ls,
perc, int(outcome)))
test_1 = [32, 45, 12, 34, 22, 44]
one_ticket_probability(test_1)
Your chances to win the big prize with the numbers [32, 45, 12, 34, 22, 44] are 0.0000072%.
In other words, you have a 1 in 13,983,816 chances to win.
test_2 = [23, 11, 45, 13, 42, 34]
one_ticket_probability(test_2)
Your chances to win the big prize with the numbers [23, 11, 45, 13, 42, 34] are 0.0000072%.
In other words, you have a 1 in 13,983,816 chances to win.
Historical Data Check for Canada Lottery
The institute also wants us to consider the data coming from the national 6⁄49 lottery game in Canada. The data set contains historical data for 3,665 drawings, dating from 1982 to 2018 (the data set can be downloaded from here).
import pandas as pd
import numpy as np
hist_data = pd.read_csv('649.csv')
print(hist_data.shape)
(3665, 11)
hist_data.head(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 | |
---|---|---|---|---|---|---|---|---|---|---|---|
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 |
hist_data.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 |
def extract_numbers(row):
row = row[4:10]
row = set(row.values)
return row
win_num = hist_data.apply(extract_numbers, axis = 1)
win_num.head()
0 {3, 41, 11, 12, 43, 14}
1 {33, 36, 37, 39, 8, 41}
2 {1, 6, 39, 23, 24, 27}
3 {3, 9, 10, 43, 13, 20}
4 {34, 5, 14, 47, 21, 31}
dtype: object
def check_historical_occurrence(ls, st):
'''
ls: a Python list
st: a pandas Series
'''
ls = set(ls)
n_ls = ls == win_num
n_occ = n_ls.sum()
if n_occ == 0:
print('''The combination {} has never occured.
This doesn't mean it's more likely to occur now. Your chances to win the big prize in the next drawing using the combination {} are 0.0000072%.
In other words, you have a 1 in 13,983,816 chances to win.'''.format(ls, ls))
else:
print('''The number of times combination {} has occured in the past is {}.
Your chances to win the big prize in the next drawing using the combination {} are 0.0000072%.
In other words, you have a 1 in 13,983,816 chances to win.'''.format(ls, n_occ,
ls))
test_input_3 = [33, 36, 37, 39, 8, 41]
check_historical_occurrence(test_input_3, win_num)
The number of times combination {33, 36, 37, 39, 8, 41} has occured in the past is 1.
Your chances to win the big prize in the next drawing using the combination {33, 36, 37, 39, 8, 41} are 0.0000072%.
In other words, you have a 1 in 13,983,816 chances to win.
test_input_4 = [3, 2, 44, 22, 1, 44]
check_historical_occurrence(test_input_4, win_num)
The combination {1, 2, 3, 44, 22} has never occured.
This doesn't mean it's more likely to occur now. Your chances to win the big prize in the next drawing using the combination {1, 2, 3, 44, 22} are 0.0000072%.
In other words, you have a 1 in 13,983,816 chances to win.
Multi-ticket Probability
For the first version of the app, users should also be able to find the probability of winning if they play multiple different tickets. For instance, someone might intend to play 15 different tickets and they want to know the probability of winning the big prize.
The engineering team wants us to be aware of the following details when we’re writing the function:
- The user will input the number of different tickets they want to play (without inputting the specific combinations they intend to play).
- Our function will see an integer between 1 and 13,983,816 (the maximum number of different tickets).
- The function should print information about the probability of winning the big prize depending on the number of different tickets played.
The multi_ticket_probability()
function below takes in the number of tickets and prints probability information depending on the input.
def multi_ticket_probability(n_tickets):
n_outcomes = combinations(49, 6)
prob = n_tickets/n_outcomes
perc = prob * 100
if n_tickets == 1:
print('''Your chance to win the big prize if you buy {} ticket is {:.7f}%.
In other words, you have a 1 in {:,} chances to win.'''.format(n_tickets,
perc, int(n_outcomes)))
else:
comb = round(n_outcomes/n_tickets)
print('''Your chances to win the big prize if you buy {} tickets are {:.6f}%.
In other words, you have a 1 in {:,} chances to win.'''.format(n_tickets,
perc, int(comb)))
ts = [1, 10, 100, 10000, 1000000, 6991908, 13983816]
for i in ts:
multi_ticket_probability(i)
print('-----------------------------------')
Your chance to win the big prize if you buy 1 ticket is 0.0000072%.
In other words, you have a 1 in 13,983,816 chances to win.
-----------------------------------
Your chances to win the big prize if you buy 10 tickets are 0.000072%.
In other words, you have a 1 in 1,398,382 chances to win.
-----------------------------------
Your chances to win the big prize if you buy 100 tickets are 0.000715%.
In other words, you have a 1 in 139,838 chances to win.
-----------------------------------
Your chances to win the big prize if you buy 10000 tickets are 0.071511%.
In other words, you have a 1 in 1,398 chances to win.
-----------------------------------
Your chances to win the big prize if you buy 1000000 tickets are 7.151124%.
In other words, you have a 1 in 14 chances to win.
-----------------------------------
Your chances to win the big prize if you buy 6991908 tickets are 50.000000%.
In other words, you have a 1 in 2 chances to win.
-----------------------------------
Your chances to win the big prize if you buy 13983816 tickets are 100.000000%.
In other words, you have a 1 in 1 chances to win.
-----------------------------------
Less Winning Numbers — Function
In most 6⁄49 lotteries, there are smaller prizes if a player’s ticket match two, three, four, or five of the six numbers drawn. This means that players might be interested in finding out the probability of having two, three, four, or five winning numbers — for the first version of the app, users should be able to find those probabilities.
These are the details we need to be aware of when we write a function to make the calculations of those probabilities possible:
- Inside the app, the user inputs: six different numbers from 1 to 49; and an integer between 2 and 5 that represents the number of winning numbers expected
- Our function prints information about the probability of having a certain number of winning numbers
To calculate the probabilities, we tell the engineering team that the specific combination on the ticket is irrelevant and we only need the integer between 2 and 5 representing the number of winning numbers expected. Consequently, we will write a function named probability_less_6()
which takes in an integer and prints information about the chances of winning depending on the value of that integer.
def probability_less_6(n):
if (n < 2) or (n > 5):
print("Please input a number between 2 and 5")
else:
num_com = combinations(6, n)
pos_suc_out = combinations(49 - n, 6 - n)
tot_suc_out = num_com * pos_suc_out
tot_out = combinations(49,6)
prb_win = tot_suc_out/tot_out
perc = prb_win * 100
com_sim = round(tot_out/tot_suc_out)
print('''Your chances of having {} winning numbers with this ticket are {:.6f}%.
In other words, you have a 1 in {:,} chances to win.'''.format(n,
perc, int(com_sim)))
test = [2, 3, 4, 5]
for i in test:
probability_less_6(i)
print('---------------------------------------')
Your chances of having 2 winning numbers with this ticket are 19.132653%.
In other words, you have a 1 in 5 chances to win.
---------------------------------------
Your chances of having 3 winning numbers with this ticket are 2.171081%.
In other words, you have a 1 in 46 chances to win.
---------------------------------------
Your chances of having 4 winning numbers with this ticket are 0.106194%.
In other words, you have a 1 in 942 chances to win.
---------------------------------------
Your chances of having 5 winning numbers with this ticket are 0.001888%.
In other words, you have a 1 in 52,969 chances to win.
---------------------------------------