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 idea of this app development comes from a medical institute that aims to prevent and treat gambling addictions and 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:
The institute also wants us to consider historical data coming from the national 6/49 lottery game in Canada. The data set has data for 3,665 drawings, dating from 1982 to 2018.
Our goal is to write code that can enable users to answer probability questions about playing the lottery. Throughout the project, we'll need to calculate repeatedly probabilities and combinations. As a consequence, we'll start by writing two functions that we'll use often:
# Write a function named factorial
def factorial(n):
final_product = 1
for i in range(n,0,-1):
final_product *= i
return final_product
# Write a function named combinations
def combinations(n,k):
numerator = factorial(n)
denominator = factorial(k) * factorial(n-k)
return numerator/denominator
In the 6/49 lottery, six numbers are drawn from a set of 49 numbers that range from 1 to 49. A player wins the big prize if the six numbers on their tickets match all the six numbers drawn. If a player has a ticket with the numbers {13, 22, 24, 27, 42, 44}, he only wins the big prize if the numbers drawn are {13, 22, 24, 27, 42, 44}. If only one number differs, he doesn't win.
For the first version of the app, we want players to be able to calculate the probability of winning the big prize with the various numbers they play on a single ticket (for each ticket a player chooses six numbers out of 49). So, we'll start by building a function that calculates the probability of winning the big prize for any given ticket.
We discussed with the engineering team of the medical institute, and they told us we need to be aware of the following details when we write the function:
# Write a function that calculates the probability of winning
# the big prize
def one_ticket_probability(six_unique_numbers):
total_n_outcomes = combinations(49,6)
probability_one_ticket = 1/total_n_outcomes
percentage_form = 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(six_unique_numbers,
percentage_form, int(total_n_outcomes)))
test_1 = [3,12,25,37,41,5]
one_ticket_probability(test_1)
Your chances to win the big prize with the numbers [3, 12, 25, 37, 41, 5] are 0.0000072%. In other words, you have a 1 in 13,983,816 chances to win.
test_2 = [1,40,7,10,31,27]
one_ticket_probability(test_2)
Your chances to win the big prize with the numbers [1, 40, 7, 10, 31, 27] are 0.0000072%. In other words, you have a 1 in 13,983,816 chances to win.
We wrote a function that can tell users what is the probability of winning the big prize with a single ticket. For the first version of the app, however, users should also be able to compare their ticket against the historical lottery data in Canada and determine whether they would have ever won by now.
We'll focus on exploring the historical data coming from the Canada 6/49 lottery. The data set can be downloaded from Kaggle
The data set contains historical data for 3,665 drawings (each row shows data for a single drawing), dating from 1982 to 2018. For each drawing, we can find the six numbers drawn in the following six columns:
#Import relevant libraries
import pandas as pd
# Open the 649 csv file
data_set = pd.read_csv('649.csv')
# Print the number of rows and columns of the data set
print(data_set.shape)
(3665, 11)
# Print the first three rows of the data set
data_set.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 |
# Print the last three rows
data_set.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 |
We could see that our data set has 3665 rows and 11 columns
We're going to write a function that will enable users to compare their ticket against the historical lottery data in Canada and determine whether they would have ever won by now.
The engineering team told us that we need to be aware of the following details:
We'll now start working on writing this function.
# write a function named extract_numbers
def extract_numbers(row):
row = row[4:10]
row = set(row.values)
return row
winning_numbers = data_set.apply(extract_numbers, axis=1)
winning_numbers.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
# write a function named check_historical_occurence
def check_historical_occurrence(six_unique_numbers, historical_numbers):
'''
six_unique_numbers: a Python list
historical numbers: a pandas Series
'''
user_numbers_set = set(six_unique_numbers)
check_occurrence = historical_numbers == user_numbers_set
n_occurrences = check_occurrence.sum()
if n_occurrences == 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(six_unique_numbers, six_unique_numbers))
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(six_unique_numbers, n_occurrences,
six_unique_numbers))
# Test the function with a few inputs.
test_3 = [2, 16, 28, 9, 35, 49]
check_historical_occurrence(test_3,winning_numbers)
The combination [2, 16, 28, 9, 35, 49] 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 [2, 16, 28, 9, 35, 49] are 0.0000072%. In other words, you have a 1 in 13,983,816 chances to win.
# Test the function with a few inputs
test_4 = [33, 36, 37, 39, 8, 41]
check_historical_occurrence(test_4,winning_numbers)
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.
So far, we wrote two functions:
Lottery addicts usually play more than one ticket on a single drawing, thinking that this might increase their chances of winning significantly. Our purpose is to help them better estimate their chances of winning. In this section, we're going to write a function that will allow the users to calculate the chances of winning for any number of different tickets.
We've talked with the engineering team and they gave us the following information:
# Write a function named multi_ticket_probability() that
# prints the probability of winning the big prize depending on the
# number of different tickets played.
def multi_ticket_probability(n_tickets):
t_n_outcomes = combinations(49,6)
probability = n_tickets / t_n_outcomes
percentage_form = probability * 100
if n_tickets == 1:
print('''Your chances to win the big prize with one ticket are {:.6f}%.
In other words, you have a 1 in {:,} chances to win.'''.format(percentage_form, int(t_n_outcomes)))
else:
combinations_simplified = round(t_n_outcomes / n_tickets)
print('''Your chances to win the big prize with {:,} different tickets are {:.6f}%.
In other words, you have a 1 in {:,} chances to win.'''.format(n_tickets, percentage_form,
combinations_simplified))
# Test the function with the following inputs
test_5 = [1, 10, 100, 10000, 1000000, 6991908, 13983816]
for test_5 in test_5:
multi_ticket_probability(test_5)
print('------------------------') # output delimiter
Your chances to win the big prize with one ticket are 0.000007%. In other words, you have a 1 in 13,983,816 chances to win. ------------------------ Your chances to win the big prize with 10 different 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 with 100 different tickets are 0.000715%. In other words, you have a 1 in 139,838 chances to win. ------------------------ Your chances to win the big prize with 10,000 different tickets are 0.071511%. In other words, you have a 1 in 1,398 chances to win. ------------------------ Your chances to win the big prize with 1,000,000 different tickets are 7.151124%. In other words, you have a 1 in 14 chances to win. ------------------------ Your chances to win the big prize with 6,991,908 different tickets are 50.000000%. In other words, you have a 1 in 2 chances to win. ------------------------ Your chances to win the big prize with 13,983,816 different tickets are 100.000000%. In other words, you have a 1 in 1 chances to win. ------------------------
So far, we wrote three main functions:
In this section, we're going to write one more function to allow the users to calculate probabilities for two, three, four, or five winning numbers.
For extra context, 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. As a consequence, the users might be interested in knowing the probability of having two, three, four, or five winning numbers.
These are the engineering details we'll need to be aware of:
# Write a function named probability_less_6()
def probability_less_6(n_winning_numbers):
n_combinations_ticket = combinations(6, n_winning_numbers)
n_combinations_remaining = combinations(43, 6 - n_winning_numbers)
successful_outcomes = n_combinations_ticket * n_combinations_remaining
n_combinations_total = combinations(49, 6)
probability = successful_outcomes / n_combinations_total
probability_percentage = probability * 100
combinations_simplified = round(n_combinations_total/successful_outcomes)
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_winning_numbers, probability_percentage,
int(combinations_simplified)))
for test_input in [2, 3, 4, 5]:
probability_less_6(test_input)
print('--------------------------') # output delimiter
Your chances of having 2 winning numbers with this ticket are 13.237803%. In other words, you have a 1 in 8 chances to win. -------------------------- Your chances of having 3 winning numbers with this ticket are 1.765040%. In other words, you have a 1 in 57 chances to win. -------------------------- Your chances of having 4 winning numbers with this ticket are 0.096862%. In other words, you have a 1 in 1,032 chances to win. -------------------------- Your chances of having 5 winning numbers with this ticket are 0.001845%. In other words, you have a 1 in 54,201 chances to win. --------------------------
We managed to write four main functions for our app:
Possible features for a second version of the app include: