Programming
Simulating a March Madness Tournament
Predicting the outcome of a sports tournament, especially one with a single-elimination bracket, is notoriously difficult. This Python code provides a simple yet effective way to simulate a tournament, taking into account both team seeding and their betting odds to determine game winners probabilistically.
Ryan McBride
Ryan McBride
alt

Source: Todd Greene on Unsplash

1. Defining a Team with dataclass

The code starts by defining a Team class using Python's @dataclass decorator. This is a convenient way to create classes primarily used to store data, automatically generating methods like __init__, __repr__, and __eq__.


import random
from dataclasses import dataclass

@dataclass
class Team:
    name: str
    seed: int
    odds: int
   
  • name: The name of the team (e.g., "Auburn", "Duke").
  • seed: The team's seeding in the tournament (lower numbers are better, e.g., 1 for a top seed).
  • odds: A numerical representation of the team's chances of winning the entire tournament, typically from betting markets (lower numbers indicate better chances).

2. Team Odds and First Round Matchups

The team_odds dictionary stores the initial odds for various teams. Teams not explicitly listed default to a very high odds value (1,000,000), effectively making them longshots.

The first_round list sets up the initial matchups. Each element in this list is a tuple containing two Team objects. Notice how it handles teams not in team_odds or play-in games (like "Alabama ST/Saint Francis U" or "San Diego State/North Carolina") by providing a default high odds value.


team_odds = {
    "Auburn": 340,
    "Duke": 360,
    # ... (truncated for brevity) ...
    "UC Irvine": 100000,
    "Yale": 100000,
}

first_round = [
    # SOUTH
    (Team("Auburn", seed=1, odds=team_odds.get("Auburn", 1000000)), Team("Alabama ST/Saint Francis U", seed=16, odds=1000000)),
    # ... (truncated for brevity) ...
]
   

3. Simulating a Single Game (simulate_game)

This is the heart of the simulation, determining the winner of a single matchup. It combines both seed and odds to calculate a winning probability for each team.


def simulate_game(team1, team2):
    # Calculate seed weights (lower seed is better)
    team1_seed_weight = 1 / (team1.seed)
    team2_seed_weight = 1 / (team2.seed)

    # Calculate odds weights (lower odds value is better)
    max_odds = max(team1.odds, team2.odds)
    team1_odds_weight = max_odds / team1.odds
    team2_odds_weight = max_odds / team2.odds

    # Combine weights. odds_priority_multiplier gives odds a stronger influence.
    odds_priority_multiplier = 10
    
    team1_combined_weight = team1_seed_weight + (team1_odds_weight * odds_priority_multiplier)
    team2_combined_weight = team2_seed_weight + (team2_odds_weight * odds_priority_multiplier)

    # Convert to probabilities
    total_combined_weight = team1_combined_weight + team2_combined_weight
    team1_prob = 100 * (team1_combined_weight / total_combined_weight)
    team2_prob = 100 * (team2_combined_weight / total_combined_weight)

    # Get winner based on probabilities
    winner = random.choices([team1, team2], weights=[team1_prob, team2_prob], k=1)[0]

    print(
        f"{team1.name}-{team1.seed} (Odds: {team1.odds}, Prob: {team1_prob:.1f}%) vs "
        f"{team2.name}-{team2.seed} (Odds: {team2.odds}, Prob: {team2_prob:.1f}%), "
        f"Winner: {winner.name}"
    )
    return winner
   
  • Seed Weight: A lower seed number means a higher weight (e.g., '1/1' for seed 1, '1/16' for seed 16).
  • Odds Weight: Lower odds (better chances) get a higher weight. The 'max_odds' ensures that dividing by a smaller 'odds' value results in a larger 'odds_weight'.
  • odds_priority_multiplier: This crucial variable allows you to adjust how much influence the betting odds have compared to the seed. A value of '10' means odds are considered 10 times more important than seeding in this simulation. You can experiment with this value!
  • Combined Weight & Probability: The seed and odds weights are combined, and then converted into winning probabilities for each team.
  • random.choices: This function from Python's 'random' module is used to pick a winner based on the calculated probabilities, making the simulation probabilistic.

4. Simulating the Entire Tournament (simulate_tournament)

This function takes the initial round's matchups and simulates the tournament round by round until only one team remains.


def simulate_tournament(first_round):
    current_games = first_round
    while len(current_games) > 0:
        print("
===== NEW ROUND =====")
        winners = []

        for team1, team2 in current_games:
            winner = simulate_game(team1, team2)
            winners.append(winner)

        if len(winners) == 1:
            return winners[0] # Tournament over, we have a champion!

        next_round = []
        for i in range(0, len(winners), 2):
            # Pair up winners for the next round
            next_round.append((winners[i], winners[i + 1]))

        current_games = next_round # Move to the next round with new matchups
    return None # Should not be reached in a complete bracket
   
  • The 'while' loop continues as long as there are games to be played.
  • In each round, it iterates through the current matchups, calling 'simulate_game' for each.
  • The winners are collected, and if only one winner remains, the tournament is over.
  • Otherwise, the winners are paired up for the 'next_round' to continue the simulation.

5. Running the Simulation

Finally, the script calls 'simulate_tournament' with the 'first_round' matchups and prints the ultimate champion.


if __name__ == "__main__":
    winner = simulate_tournament(first_round)
    print(f"
{winner.name} wins the tournament!")
   

How to Run This Code

  1. Save the code as a Python file (e.g., bracket_sim.py).
  2. Open a terminal or command prompt.
  3. Navigate to the directory where you saved the file.
  4. Run the script using: python bracket_sim.py

Each time you run it, you'll get a different simulated outcome due to the random nature of 'random.choices'!

Further Exploration

This simulation is a great starting point. Here are some ideas for enhancement:

  • Multiple Simulations: Run the 'simulate_tournament' function hundreds or thousands of times and count how many times each team wins to get a probability distribution of tournament winners.
  • Bracket Visualization: Integrate with a library to draw the bracket as it progresses or after the final winner is determined.
  • More Factors: Add more attributes to the 'Team' dataclass (e.g., recent form, injuries, home advantage) and incorporate them into the 'simulate_game' logic.
  • Adjusting Influence: Experiment with the 'odds_priority_multiplier' to see how much more dominant higher-seeded/better-odds teams become.
  • User Input: Allow users to define their own teams and matchups.

This code provides a fun and insightful way to model probabilistic outcomes in competitive scenarios!

Full Code Here

import random
from dataclasses import dataclass
 
 
@dataclass
class Team:
    name: str
    seed: int
    odds: int
 
 
team_odds = {
    "Auburn": 340,
    "Duke": 360,
    "Florida": 450,
    "Houston": 600,
    "Alabama": 1100,
    "Tennessee": 1300,
    "Michigan State": 2200,
    "St. John's": 2200,
    "Iowa State": 2500,
    "Kentucky": 3500,
    "Texas Tech": 4000,
    "Kansas": 5000,
    "Connecticut": 6000,
    "Arizona": 5000,
    "Gonzaga": 5000,
    "Wisconsin": 5000,
    "Maryland": 5000,
    "Clemson": 6000,
    "BYU": 6600,
    "Texas A&M": 6600,
    "Purdue": 8000,
    "Marquette": 8000,
    "Michigan": 8000,
    "Missouri": 8000,
    "Creighton": 10000,
    "Illinois": 10000,
    "St. Mary's": 10000,
    "Mississippi State": 10000,
    "UCLA": 10000,
    "Ole Miss": 10000,
    "Louisville": 10000,
    "Oregon": 15000,
    "Memphis": 15000,
    "Baylor": 20000,
    "New Mexico": 20000,
    "Vanderbilt": 20000,
    "Arkansas": 25000,
    "VCU": 25000,
    "Indiana": 30000,
    "Georgia": 30000,
    "Texas": 35000,
    "Utah State": 35000,
    "North Carolina": 50000,
    "San Diego State": 50000,
    "Xavier": 50000,
    "Boise State": 50000,
    "Oklahoma": 50000,
    "West Virginia": 50000,
    "Drake": 50000,
    "UC San Diego": 50000,
    "Ohio State": 100000,
    "Colorado State": 100000,
    "UAB": 100000,
    "Grand Canyon": 100000,
    "McNeese": 100000,
    "UC Irvine": 100000,
    "Yale": 100000,
}
 
first_round = [
    # SOUTH
    (Team("Auburn", seed=1, odds=team_odds.get("Auburn", 1000000)), Team("Alabama ST/Saint Francis U", seed=16, odds=1000000)),
    (Team("Louisville", seed=8, odds=team_odds.get("Louisville", 1000000)), Team("Creighton", seed=9, odds=team_odds.get("Creighton", 1000000))),
    (Team("Michigan", seed=5, odds=team_odds.get("Michigan", 1000000)), Team("UC San Diego", seed=12, odds=team_odds.get("UC San Diego", 1000000))),
    (Team("Texas A&M", seed=4, odds=team_odds.get("Texas A&M", 1000000)), Team("Yale", seed=13, odds=team_odds.get("Yale", 1000000))),
    (Team("Ole Miss", seed=6, odds=team_odds.get("Ole Miss", 1000000)), Team("San Diego State/North Carolina", seed=11, odds=team_odds.get("San Diego State", 1000000) or team_odds.get("North Carolina", 1000000))),
    (Team("Iowa State", seed=3, odds=team_odds.get("Iowa State", 1000000)), Team("Lipscomb", seed=14, odds=1000000)),
    (Team("Marquette", seed=7, odds=team_odds.get("Marquette", 1000000)), Team("New Mexico", seed=10, odds=team_odds.get("New Mexico", 1000000))),
    (Team("Michigan State", seed=2, odds=team_odds.get("Michigan State", 1000000)), Team("Bryant", seed=15, odds=1000000)),
    # WEST
    (Team("Florida", seed=1, odds=team_odds.get("Florida", 1000000)), Team("Norfolk St.", seed=16, odds=1000000)),
    (Team("Connecticut", seed=8, odds=team_odds.get("Connecticut", 1000000)), Team("Oklahoma", seed=9, odds=team_odds.get("Oklahoma", 1000000))),
    (Team("Memphis", seed=5, odds=team_odds.get("Memphis", 1000000)), Team("Colorado State", seed=12, odds=team_odds.get("Colorado State", 1000000))),
    (Team("Maryland", seed=4, odds=team_odds.get("Maryland", 1000000)), Team("Grand Canyon", seed=13, odds=team_odds.get("Grand Canyon", 1000000))),
    (Team("Missouri", seed=6, odds=team_odds.get("Missouri", 1000000)), Team("Drake", seed=11, odds=team_odds.get("Drake", 1000000))),
    (Team("Texas Tech", seed=3, odds=team_odds.get("Texas Tech", 1000000)), Team("UNC Wilmington", seed=14, odds=1000000)),
    (Team("Kansas", seed=7, odds=team_odds.get("Kansas", 1000000)), Team("Arkansas", seed=10, odds=team_odds.get("Arkansas", 1000000))),
    (Team("St. John's", seed=2, odds=team_odds.get("St. John's", 1000000)), Team("Omaha", seed=15, odds=1000000)),
    # EAST
    (Team("Duke", seed=1, odds=team_odds.get("Duke", 1000000)), Team("America/Mount St Mary's", seed=16, odds=1000000)),
    (Team("Mississippi State", seed=8, odds=team_odds.get("Mississippi State", 1000000)), Team("Baylor", seed=9, odds=team_odds.get("Baylor", 1000000))),
    (Team("Oregon", seed=5, odds=team_odds.get("Oregon", 1000000)), Team("Liberty", seed=12, odds=1000000)),
    (Team("Arizona", seed=4, odds=team_odds.get("Arizona", 1000000)), Team("Akron", seed=13, odds=1000000)),
    (Team("BYU", seed=6, odds=team_odds.get("BYU", 1000000)), Team("VCU", seed=11, odds=team_odds.get("VCU", 1000000))),
    (Team("Wisconsin", seed=3, odds=team_odds.get("Wisconsin", 1000000)), Team("Montana", seed=14, odds=1000000)),
    (Team("St. Mary's", seed=7, odds=team_odds.get("St. Mary's", 1000000)), Team("Vanderbilt", seed=10, odds=team_odds.get("Vanderbilt", 1000000))),
    (Team("Alabama", seed=2, odds=team_odds.get("Alabama", 1000000)), Team("Robert Morris", seed=15, odds=1000000)),
    # MIDWEST
    (Team("Houston", seed=1, odds=team_odds.get("Houston", 1000000)), Team("SIU Edwardsville", seed=16, odds=1000000)),
    (Team("Gonzaga", seed=8, odds=team_odds.get("Gonzaga", 1000000)), Team("Georgia", seed=9, odds=team_odds.get("Georgia", 1000000))),
    (Team("Clemson", seed=5, odds=team_odds.get("Clemson", 1000000)), Team("McNeese", seed=12, odds=team_odds.get("McNeese", 1000000))),
    (Team("Purdue", seed=4, odds=team_odds.get("Purdue", 1000000)), Team("High Point", seed=13, odds=1000000)),
    (Team("Illinois", seed=6, odds=team_odds.get("Illinois", 1000000)), Team("Texas/Xavier", seed=11, odds=team_odds.get("Texas", 1000000) or team_odds.get("Xavier", 1000000))),
    (Team("Kentucky", seed=3, odds=team_odds.get("Kentucky", 1000000)), Team("Troy", seed=14, odds=1000000)),
    (Team("UCLA", seed=7, odds=team_odds.get("UCLA", 1000000)), Team("Utah State", seed=10, odds=team_odds.get("Utah State", 1000000))),
    (Team("Tennessee", seed=2, odds=team_odds.get("Tennessee", 1000000)), Team("Wofford", seed=15, odds=1000000)),
]
 
 
def simulate_game(team1, team2):
    # Calculate seed weights (lower seed is better)
    team1_seed_weight = 1 / (team1.seed)
    team2_seed_weight = 1 / (team2.seed)
 
    # Calculate odds weights (lower odds value is better)
    # We use a large number divided by odds to give higher weight to lower odds
    max_odds = max(team1.odds, team2.odds)
    team1_odds_weight = max_odds / team1.odds
    team2_odds_weight = max_odds / team2.odds
 
    # Combine weights. You can adjust the multiplier for odds to prioritize it more.
    # A higher multiplier for odds_weight means odds will have a stronger influence.
    # Here, we're giving odds a significantly higher influence than seeding.
    odds_priority_multiplier = 10
   
    team1_combined_weight = team1_seed_weight + (team1_odds_weight * odds_priority_multiplier)
    team2_combined_weight = team2_seed_weight + (team2_odds_weight * odds_priority_multiplier)
 
    # Convert to probabilities
    total_combined_weight = team1_combined_weight + team2_combined_weight
    team1_prob = 100 * (team1_combined_weight / total_combined_weight)
    team2_prob = 100 * (team2_combined_weight / total_combined_weight)
 
    # Get winner based on probabilities
    winner = random.choices([team1, team2], weights=[team1_prob, team2_prob], k=1)[0]
 
    print(
        f"{team1.name}-{team1.seed} (Odds: {team1.odds}, Prob: {team1_prob:.1f}%) vs "
        f"{team2.name}-{team2.seed} (Odds: {team2.odds}, Prob: {team2_prob:.1f}%), "
        f"Winner: {winner.name}"
    )
 
    return winner
 
 
def simulate_tournament(first_round):
    current_games = first_round
    while len(current_games) > 0:
        print("
===== NEW ROUND =====")
        winners = []
 
        for team1, team2 in current_games:
            winner = simulate_game(team1, team2)
            winners.append(winner)
 
        if len(winners) == 1:
            return winners[0]
 
        next_round = []
        for i in range(0, len(winners), 2):
            next_round.append((winners[i], winners[i + 1]))
 
        current_games = next_round
    return None
 
 
winner = simulate_tournament(first_round)
print(f"
{winner.name} wins the tournament!")

Results

===== NEW ROUND =====
Auburn-1 (Odds: 340, Prob: 100.0%) vs Alabama ST/Saint Francis U-16 (Odds: 1000000, Prob: 0.0%), Winner: Auburn
Louisville-8 (Odds: 10000, Prob: 50.0%) vs Creighton-9 (Odds: 10000, Prob: 50.0%), Winner: Louisville
Michigan-5 (Odds: 8000, Prob: 86.1%) vs UC San Diego-12 (Odds: 50000, Prob: 13.9%), Winner: Michigan
Texas A&M-4 (Odds: 6600, Prob: 93.8%) vs Yale-13 (Odds: 100000, Prob: 6.2%), Winner: Texas A&M
Ole Miss-6 (Odds: 10000, Prob: 83.3%) vs San Diego State/North Carolina-11 (Odds: 50000, Prob: 16.7%), Winner: Ole Miss
Iowa State-3 (Odds: 2500, Prob: 99.7%) vs Lipscomb-14 (Odds: 1000000, Prob: 0.3%), Winner: Iowa State
Marquette-7 (Odds: 8000, Prob: 71.3%) vs New Mexico-10 (Odds: 20000, Prob: 28.7%), Winner: Marquette
Michigan State-2 (Odds: 2200, Prob: 99.8%) vs Bryant-15 (Odds: 1000000, Prob: 0.2%), Winner: Michigan State
Florida-1 (Odds: 450, Prob: 100.0%) vs Norfolk St.-16 (Odds: 1000000, Prob: 0.0%), Winner: Florida
Connecticut-8 (Odds: 6000, Prob: 89.2%) vs Oklahoma-9 (Odds: 50000, Prob: 10.8%), Winner: Connecticut
Memphis-5 (Odds: 15000, Prob: 86.9%) vs Colorado State-12 (Odds: 100000, Prob: 13.1%), Winner: Memphis
Maryland-4 (Odds: 5000, Prob: 95.2%) vs Grand Canyon-13 (Odds: 100000, Prob: 4.8%), Winner: Grand Canyon
Missouri-6 (Odds: 8000, Prob: 86.1%) vs Drake-11 (Odds: 50000, Prob: 13.9%), Winner: Missouri
Texas Tech-3 (Odds: 4000, Prob: 99.6%) vs UNC Wilmington-14 (Odds: 1000000, Prob: 0.4%), Winner: Texas Tech
Kansas-7 (Odds: 5000, Prob: 83.2%) vs Arkansas-10 (Odds: 25000, Prob: 16.8%), Winner: Kansas
St. John's-2 (Odds: 2200, Prob: 99.8%) vs Omaha-15 (Odds: 1000000, Prob: 0.2%), Winner: St. John's
Duke-1 (Odds: 360, Prob: 100.0%) vs America/Mount St Mary's-16 (Odds: 1000000, Prob: 0.0%), Winner: Duke
Mississippi State-8 (Odds: 10000, Prob: 66.6%) vs Baylor-9 (Odds: 20000, Prob: 33.4%), Winner: Baylor
Oregon-5 (Odds: 15000, Prob: 98.5%) vs Liberty-12 (Odds: 1000000, Prob: 1.5%), Winner: Oregon
Arizona-4 (Odds: 5000, Prob: 99.5%) vs Akron-13 (Odds: 1000000, Prob: 0.5%), Winner: Arizona
BYU-6 (Odds: 6600, Prob: 79.0%) vs VCU-11 (Odds: 25000, Prob: 21.0%), Winner: BYU
Wisconsin-3 (Odds: 5000, Prob: 99.5%) vs Montana-14 (Odds: 1000000, Prob: 0.5%), Winner: Wisconsin
St. Mary's-7 (Odds: 10000, Prob: 66.6%) vs Vanderbilt-10 (Odds: 20000, Prob: 33.4%), Winner: St. Mary's
Alabama-2 (Odds: 1100, Prob: 99.9%) vs Robert Morris-15 (Odds: 1000000, Prob: 0.1%), Winner: Alabama
Houston-1 (Odds: 600, Prob: 99.9%) vs SIU Edwardsville-16 (Odds: 1000000, Prob: 0.1%), Winner: Houston
Gonzaga-8 (Odds: 5000, Prob: 85.6%) vs Georgia-9 (Odds: 30000, Prob: 14.4%), Winner: Gonzaga
Clemson-5 (Odds: 6000, Prob: 94.3%) vs McNeese-12 (Odds: 100000, Prob: 5.7%), Winner: Clemson
Purdue-4 (Odds: 8000, Prob: 99.2%) vs High Point-13 (Odds: 1000000, Prob: 0.8%), Winner: Purdue
Illinois-6 (Odds: 10000, Prob: 77.7%) vs Texas/Xavier-11 (Odds: 35000, Prob: 22.3%), Winner: Illinois
Kentucky-3 (Odds: 3500, Prob: 99.6%) vs Troy-14 (Odds: 1000000, Prob: 0.4%), Winner: Kentucky
UCLA-7 (Odds: 10000, Prob: 77.7%) vs Utah State-10 (Odds: 35000, Prob: 22.3%), Winner: UCLA
Tennessee-2 (Odds: 1300, Prob: 99.9%) vs Wofford-15 (Odds: 1000000, Prob: 0.1%), Winner: Tennessee
 
===== NEW ROUND =====
Auburn-1 (Odds: 340, Prob: 96.7%) vs Louisville-8 (Odds: 10000, Prob: 3.3%), Winner: Auburn
Michigan-5 (Odds: 8000, Prob: 45.2%) vs Texas A&M-4 (Odds: 6600, Prob: 54.8%), Winner: Michigan
Ole Miss-6 (Odds: 10000, Prob: 20.1%) vs Iowa State-3 (Odds: 2500, Prob: 79.9%), Winner: Iowa State
Marquette-7 (Odds: 8000, Prob: 21.6%) vs Michigan State-2 (Odds: 2200, Prob: 78.4%), Winner: Marquette
Florida-1 (Odds: 450, Prob: 93.0%) vs Connecticut-8 (Odds: 6000, Prob: 7.0%), Winner: Florida
Memphis-5 (Odds: 15000, Prob: 86.9%) vs Grand Canyon-13 (Odds: 100000, Prob: 13.1%), Winner: Memphis
Missouri-6 (Odds: 8000, Prob: 33.3%) vs Texas Tech-3 (Odds: 4000, Prob: 66.7%), Winner: Missouri
Kansas-7 (Odds: 5000, Prob: 30.4%) vs St. John's-2 (Odds: 2200, Prob: 69.6%), Winner: St. John's
Duke-1 (Odds: 360, Prob: 98.2%) vs Baylor-9 (Odds: 20000, Prob: 1.8%), Winner: Duke
Oregon-5 (Odds: 15000, Prob: 25.2%) vs Arizona-4 (Odds: 5000, Prob: 74.8%), Winner: Arizona
BYU-6 (Odds: 6600, Prob: 42.9%) vs Wisconsin-3 (Odds: 5000, Prob: 57.1%), Winner: BYU
St. Mary's-7 (Odds: 10000, Prob: 10.0%) vs Alabama-2 (Odds: 1100, Prob: 90.0%), Winner: Alabama
Houston-1 (Odds: 600, Prob: 89.3%) vs Gonzaga-8 (Odds: 5000, Prob: 10.7%), Winner: Houston
Clemson-5 (Odds: 6000, Prob: 56.9%) vs Purdue-4 (Odds: 8000, Prob: 43.1%), Winner: Purdue
Illinois-6 (Odds: 10000, Prob: 26.0%) vs Kentucky-3 (Odds: 3500, Prob: 74.0%), Winner: Illinois
UCLA-7 (Odds: 10000, Prob: 11.6%) vs Tennessee-2 (Odds: 1300, Prob: 88.4%), Winner: Tennessee
 
===== NEW ROUND =====
Auburn-1 (Odds: 340, Prob: 95.9%) vs Michigan-5 (Odds: 8000, Prob: 4.1%), Winner: Auburn
Iowa State-3 (Odds: 2500, Prob: 76.1%) vs Marquette-7 (Odds: 8000, Prob: 23.9%), Winner: Iowa State
Florida-1 (Odds: 450, Prob: 97.0%) vs Memphis-5 (Odds: 15000, Prob: 3.0%), Winner: Florida
Missouri-6 (Odds: 8000, Prob: 21.6%) vs St. John's-2 (Odds: 2200, Prob: 78.4%), Winner: St. John's
Duke-1 (Odds: 360, Prob: 93.2%) vs Arizona-4 (Odds: 5000, Prob: 6.8%), Winner: Duke
BYU-6 (Odds: 6600, Prob: 14.4%) vs Alabama-2 (Odds: 1100, Prob: 85.6%), Winner: Alabama
Houston-1 (Odds: 600, Prob: 92.9%) vs Purdue-4 (Odds: 8000, Prob: 7.1%), Winner: Houston
Illinois-6 (Odds: 10000, Prob: 11.6%) vs Tennessee-2 (Odds: 1300, Prob: 88.4%), Winner: Tennessee
 
===== NEW ROUND =====
Auburn-1 (Odds: 340, Prob: 87.8%) vs Iowa State-3 (Odds: 2500, Prob: 12.2%), Winner: Auburn
Florida-1 (Odds: 450, Prob: 82.6%) vs St. John's-2 (Odds: 2200, Prob: 17.4%), Winner: Florida
Duke-1 (Odds: 360, Prob: 75.0%) vs Alabama-2 (Odds: 1100, Prob: 25.0%), Winner: Duke
Houston-1 (Odds: 600, Prob: 68.3%) vs Tennessee-2 (Odds: 1300, Prob: 31.7%), Winner: Houston
 
===== NEW ROUND =====
Auburn-1 (Odds: 340, Prob: 56.4%) vs Florida-1 (Odds: 450, Prob: 43.6%), Winner: Florida
Duke-1 (Odds: 360, Prob: 61.6%) vs Houston-1 (Odds: 600, Prob: 38.4%), Winner: Houston
 
===== NEW ROUND =====
Florida-1 (Odds: 450, Prob: 56.6%) vs Houston-1 (Odds: 600, Prob: 43.4%), Winner: Florida
 
Florida wins the tournament!

March Madness 2024 Prediction Results

Round 1

  • Auburn X
  • Creighton
  • Michigan X
  • Texas A&M X
  • Ole Miss X
  • Iowa State X
  • New Mexico
  • Michigan St X
  • Florida X
  • UConn X
  • Colorado St
  • Maryland
  • Drake
  • Texas Tech X
  • Arkansas
  • St John's X
  • Duke X
  • Baylor X
  • Oregon X
  • Arizona X
  • BYU X
  • Wisconsin X
  • Saint Mary's X
  • Alabama X
  • Houston X
  • Gonzaga X
  • McNeese
  • Purdue X
  • Illinois X
  • Kentucky X
  • UCLA X
  • Tennessee X

25/32

Round 2

  • Auburn X
  • Michigan X
  • Ole Miss
  • Michigan St
  • Florida X
  • Maryland
  • Texas Tech
  • Arkansas
  • Duke X
  • Arizona X
  • BYU X
  • Alabama X
  • Houston X
  • Purdue X
  • Kentucky
  • Tennessee X

10/16

Sweet Sixteen

  • Auburn X
  • Michigan St
  • Florida X
  • Texas Tech
  • Duke X
  • Alabama X
  • Houston X
  • Tennessee X

6/8

Elite Eight

  • Auburn X
  • Florida X
  • Duke X
  • Houston X

4/4

Final Four

  • Florida X
  • Houston X

2/2

Championship

  • Florida X

1/1

Overall: 48/63 = 76% Correct!