# JUNTO Practice: Probability, NCAA Basketball Pool

Discussed on July 28, 2020.

There are 64 teams who play single elimination tournament, hence 6 rounds, and you have to predict all the winners in all 63 games. Your score is then computed as follows, 32 points for correctly predicting the final winner, 16 points for each correct finalist, and so on, down to 1 point for every correctly predicted winner for the first round. (The maximum number of points you can get is thus 192.) Knowing nothing about any team, you flip fair coins to decide every one of your 63 bets. Compute the expected number of points.

## Solutions

Click to see:

### Oscar Martinez

I believe that the expected number of points is 31.5.

``````import numpy as np
from numba import jit

@jit
def play_tourney(teams=64):
rounds = int(np.log(teams / 2) / np.log(2))

bracket = [np.arange(teams)]
remaining_teams = teams
for i in range(rounds + 1):
remaining_teams = remaining_teams // 2
match_arr = np.random.randint(
0, 2, (remaining_teams)
) + (np.arange(remaining_teams) * 2)
match_arr = bracket[i][match_arr]
bracket.append(match_arr)

return bracket[1:]

vec_play_tourney = np.vectorize(play_tourney)

@jit
def score(results, bets, max_points=32):
points = 0
for i, r in enumerate(results):
points += np.sum(r == bets[i]) * (
max_points // r.shape
)

return points

vec_score = np.vectorize(score)

@jit
def simulate(simulations, teams=64, max_points=32):
points = 0
for i in range(simulations):
bets = play_tourney(teams)
results = play_tourney(teams)
points += score(results, bets, max_points)
return points / simulations

print(simulate(10000))
``````
``````31.2232
``````

### John Lekberg

I believe that the expected number of points is about 31.5.

I created a Python function that simulates the betting and took the mean of 1,000,000 samples:

``````import numpy as np

N_TEAM = 64
N_ROUND = 6

ROUND_POINTS = np.array(
[
2 ** n
for n in range(N_ROUND)
for _ in range(2 ** (N_ROUND - (n + 1)))
]
)

def random_outcome(N):
"""Sample the random variable 'the outcomes of the
single-elimination tournament'.
"""
teams = np.repeat([np.arange(N_TEAM)], N, axis=0)

rounds = []
for _ in range(N_ROUND):
dim = list(teams.shape)
dim //= 2
#
group_offset = np.arange(dim) * 2
win_offset = np.random.randint(2, size=dim)
win_index = group_offset + win_offset
teams = np.take_along_axis(teams, win_index, axis=1)
#
rounds.append(teams)

return np.concatenate(rounds, axis=1)

def random_total_points(N):
"""Sample the random variable 'the total number of points
from randomly betting'.
"""
bet = random_outcome(N)
result = random_outcome(N)
correct = bet == result
total_points = correct @ ROUND_POINTS

random_total_points(1_000_000).mean()
``````
``````31.519703
``````

### Daniel Bassett

I believe that the expected number of points is about 31.55.

``````import numpy as np

def simulate(n):
i = 0
results = [0 for i in range(n)]
while i < len(results):
round1 = np.random.choice(
[0, 1], size=(32,), p=[63.0 / 64, 1.0 / 64]
)
round2 = np.random.choice(
[0, 2], size=(16,), p=[31.0 / 32, 1.0 / 32]
)
round3 = np.random.choice(
[0, 4], size=(8,), p=[15.0 / 16, 1.0 / 16]
)
round4 = np.random.choice(
[0, 8], size=(4,), p=[7.0 / 8, 1.0 / 8]
)
round5 = np.random.choice(
[0, 16], size=(2,), p=[3.0 / 4, 1.0 / 4]
)
round6 = np.random.choice([0, 32], size=(1,))

tournament = [
sum(round1),
sum(round2),
sum(round3),
sum(round4),
sum(round5),
sum(round6),
]
results[i] = sum(tournament)

i += 1

return sum(results) / len(results)

print(simulate(100000))
``````
``````31.55746
``````