Lesson 5 - Guided Project: The Odds of the Lottery
Welcome to the Guided Project
Imagine the DATATWEETS Lotto has just launched. It is a 6/49 draw: every ticket picks 6 distinct numbers from 1 to 49, and a winning ticket must match all six numbers the machine draws. Players keep asking the same questions. What are my odds? Do I get anything for matching some of the numbers? If I buy a hundred tickets, am I getting close? And surely my late grandmother’s birthday is luckier than random picks?
Your job in this project is to build a small probability tool that answers those questions honestly — with exact numbers, not slogans. You will apply everything from this module: counting, combinations, the multiplication and complement rules, and the discipline of computing a real probability instead of guessing one.
By the end of this lesson, you will be able to:
- Count a lottery’s sample space with combinations and reason about its size
- Write a function that returns the exact probability of any outcome
- Compute the chance of partial wins (matching some but not all numbers)
- Translate tiny probabilities into plain language people can actually feel
You only need Python’s built-in math module and a little numpy to check your work. Let’s begin.
Step 1: Count the Sample Space
Before any probability, you need the sample space — the total number of possible tickets. A ticket is 6 numbers chosen from 49, and order does not matter (the draw 4, 8, 15, 16, 23, 42 is the same ticket no matter how you write it). That is exactly what a combination counts:
Python’s math.comb does it directly:
import math
total_combinations = math.comb(49, 6)
print(total_combinations)13983816There are 13,983,816 distinct tickets — just under fourteen million. Every one of them is equally likely to be drawn, so this single number is the foundation of the whole tool. From here on, every probability we compute is some count of favorable tickets divided by 13,983,816.
Why combinations, not permutations
If order mattered, there would be ordered picks. But the lottery does not care what sequence your numbers come in, so we divide out the orderings of each ticket. That division is the difference between a permutation and a combination — and it shrinks the count by 720 times.
Step 2: The Jackpot — One Ticket’s Chance
The jackpot goes to the ticket that matches all six drawn numbers. Exactly one of the 13,983,816 tickets does that, so the probability is one favorable outcome over the whole sample space:
Let’s wrap that in a function so the tool can answer “what are my odds?” for a single ticket:
def one_ticket_probability():
total = math.comb(49, 6)
p = 1 / total
print(f"Your chance of winning the jackpot with one ticket is {p:.10f}")
print(f"That's 1 in {total:,} — about a {p*100:.8f}% chance.")
return p
one_ticket_probability()Your chance of winning the jackpot with one ticket is 0.0000000715
That's 1 in 13,983,816 — about a 0.0000007151% chance.In plain words: roughly 1 in 14 million. That number is hard to feel, so anchor it. If you bought one ticket every single week, you would expect to win the jackpot about once every 269,000 years. A randomly chosen second in the last full week is more likely to be the exact second you were born than your ticket is to win. The honest headline our tool should print is simple: a single ticket almost certainly will not win.
Step 3: Partial Wins — Matching Exactly k Numbers
Most lotteries pay smaller prizes for matching some of the numbers, and players badly overestimate those chances too. So the tool needs to answer “what’s my probability of matching exactly k of the six?”
Here is the counting logic. Of the 49 numbers, 6 are winners (the ones drawn) and 43 are losers. To match exactly numbers, your ticket must contain of the 6 winners and the remaining of the 43 losers. Multiply the ways to choose each group:
The numerator is the multiplication rule for counting: choose your winners and your losers. Turn it into a function:
def match_k_probability(k):
total = math.comb(49, 6)
favorable = math.comb(6, k) * math.comb(43, 6 - k)
p = favorable / total
return favorable, p
for k in range(2, 7):
favorable, p = match_k_probability(k)
print(f"Match {k}: {favorable:>8,} tickets -> p = {p:.3e} (1 in {round(1/p):,})")Match 2: 1,851,150 tickets -> p = 1.324e-01 (1 in 8)
Match 3: 246,820 tickets -> p = 1.765e-02 (1 in 57)
Match 4: 13,545 tickets -> p = 9.686e-04 (1 in 1,032)
Match 5: 258 tickets -> p = 1.845e-05 (1 in 54,201)
Match 6: 1 tickets -> p = 7.151e-08 (1 in 13,983,816)Read down that table and the cliff is brutal. Matching 3 numbers happens about 1 in 57 times — common enough to keep people hooked. But each extra number you need sends the odds tumbling, and the drop steepens at every step: match 4 is about 1 in 1,000 (a roughly 18× drop), match 5 is 1 in 54,201 (another ~54×), and the jackpot is 1 in 14 million (a final ~258×). A bar chart on a log scale makes the steepness unmistakable:
Sanity-check with a simulation
You can confirm these exact numbers by playing the lottery millions of times in numpy. Draw a fixed winning set, simulate five million random tickets, and count the overlap:
import numpy as np
rng = np.random.default_rng(7)
winning = set(range(1, 7)) # any fixed 6 numbers
hits = np.zeros(7, dtype=int)
for _ in range(5_000_000):
ticket = set(rng.choice(49, size=6, replace=False) + 1)
hits[len(winning & ticket)] += 1
print(hits[3] / 5_000_000) # ~0.0176, matching the exact match-3 valueThe simulated match-3 rate lands near 0.0176, right on top of the exact 1.765e-02 — proof the combination formula is correct.
Step 4: How Many Tickets Buy a Real Chance?
A tempting workaround is to buy many tickets. So the tool should answer the natural follow-up: how many distinct tickets must you buy to have a 50% chance at the jackpot?
If you buy different tickets, your probability of winning is easiest to find through the complement: the chance of not winning with one ticket is , and for independent distinct tickets the chance of missing every time is that raised to the . Subtract from one:
Set that equal to 0.5 and solve for with logarithms:
total = math.comb(49, 6)
p = 1 / total
def tickets_for_probability(target):
# n such that 1 - (1 - p)**n = target
return math.log(1 - target) / math.log(1 - p)
print(f"Tickets for a 50% chance: {tickets_for_probability(0.50):,.0f}")
print(f"Tickets for a 10% chance: {tickets_for_probability(0.10):,.0f}")Tickets for a 50% chance: 9,692,842
Tickets for a 10% chance: 1,473,342To reach a coin-flip’s worth of hope, you would need to buy about 9.69 million different tickets. At even a dollar apiece that is nearly ten million dollars spent to reach a 50% chance at a prize that is usually far smaller — and the other half of the time you win nothing. The curve of probability against tickets bought tells the whole story:
The shape is the lesson. For any realistic number of tickets, the curve hugs the bottom of the chart. Buying ten tickets instead of one multiplies your chance by ten, which sounds great until you remember ten times almost-nothing is still almost-nothing.
Step 5: Debunk the “Lucky Numbers” Myth
The most common belief our tool has to confront: that some combinations are luckier than others. People avoid the numbers from last month’s draw (“they won’t come up again”), or they trust a famous winning sequence, or they pay extra for “hot” numbers.
The math is blunt. The draw is a uniform random choice among all 13,983,816 tickets, so every single combination has exactly the same probability:
total = math.comb(49, 6)
lucky_grandma = (4, 8, 15, 16, 23, 42) # a "lucky" birthday set
famous_winner = (3, 11, 19, 27, 38, 45) # a past winning draw
boring_sequence = (1, 2, 3, 4, 5, 6) # looks "impossible"
for name, combo in [("Lucky birthdays", lucky_grandma),
("Past winning draw", famous_winner),
("1-2-3-4-5-6", boring_sequence)]:
print(f"{name:>18}: 1 in {total:,} (p = {1/total:.3e})") Lucky birthdays: 1 in 13,983,816 (p = 7.151e-08)
Past winning draw: 1 in 13,983,816 (p = 7.151e-08)
1-2-3-4-5-6: 1 in 13,983,816 (p = 7.151e-08)Identical, to the last digit. 1-2-3-4-5-6 feels impossible, but it is exactly as likely as any scatter of “random-looking” numbers — it is just one ticket out of fourteen million, like all the rest. The machine has no memory of last month’s draw and no opinion about birthdays.
One real reason to avoid popular numbers
There is a single sensible twist: popular patterns (birthdays under 31, or a tidy diagonal on the play slip) are picked by many people. They are not less likely to win, but if they do, you split the jackpot with everyone else who chose them. So picking unpopular numbers does not raise your chance of winning — it only raises how much you’d keep if you won. That is the only edge that survives the math.
Take It Further
The tool is honest and complete, but you can push it further with the same counting tools:
- Add an “any prize” probability. Combine the partial-win cases (say, match 3 or better) with the addition rule. Since the cases are mutually exclusive, just sum their probabilities — what’s the chance a ticket wins anything?
- Model a bonus ball. Many real 6/49 games draw a 7th “bonus” number that upgrades a match-5 prize. Extend the counting to a
match 5 + bonuscategory and find its probability. - Estimate expected value. Assign a payout to each tier, multiply by its probability, sum them, and subtract the ticket price. Is the expected value of a ticket ever positive?
- Compare formats. Recompute the jackpot odds for a 6/45 and a 6/59 draw with
math.comb. How much does adding ten numbers to the pool change your chances?
Summary
You built a small, honest probability tool for a 6/49 lottery using only the counting and probability rules from this module. You counted the sample space with a combination — 13,983,816 tickets — and used it as the denominator for everything else. You wrote a function for the jackpot (1 in 14 million), a function for matching exactly numbers (match-3 at 1 in 57 falling to the jackpot at 1 in 14 million), solved for the 9.69 million tickets needed for a 50% chance, and proved that every combination — lucky, famous, or boring — shares the identical probability of .
Key Concepts
- Sample space via combinations — counts every distinct ticket because order does not matter.
- Probability as favorable / total — each outcome’s chance is its count of favorable tickets over 13,983,816.
- Partial-win counting — choose winners and losers: .
- The complement rule — the chance of winning with tickets is , easiest found through “not winning.”
- Uniform outcomes — in a fair draw every combination is equally likely; “lucky numbers” are a story, not a probability.
Why This Matters
This project is probability doing a public service. The same skills that price a lottery ticket also tell you whether a screening test’s “positive” should scare you, how often a rare error will slip past quality control, or what a “1-in-500-year flood” really means for the house you’re about to buy. A tiny probability is easy to wave away or to oversell; the honest move is to compute it exactly and then translate it into something a person can feel. We are not here to tell anyone how to spend a few dollars of fun. We are here to make sure that when the odds are 1 in 14 million, nobody mistakes them for 1 in a few thousand — because the difference, computed plainly, is the whole point of probability.
Next Steps
Continue to Module 4 - Conditional Probability & Bayes (next in the course)
Learn how new evidence updates a probability — the rule behind medical tests, spam filters, and honest reasoning under uncertainty.
Back to Module Overview
Return to the Probability Fundamentals module overview
Continue Building Your Skills
You just turned a deck of marketing slogans into exact numbers — and the numbers told a clearer story than any slogan could. That move, from a vague feeling about chance to a probability you can compute, check with a simulation, and explain in one sentence, is the core skill of this entire module. Next you’ll learn how a probability changes when new information arrives, the idea that powers everything from medical diagnosis to Bayesian machine learning. Onward.