| Tennis |
Write a script that defines various functions that simulate different aspects
of Tennis: points, games, sets, and matches; these functions will build on
top of each other: e.g., the points function will help simulate games, the
games function will help simulate sets, and the sets function will help
simulate matches.
Our goal is to investiate the following issue:
Given the probability for which player A beats player B on a
single point, what is the probability that player A
wins a match from player B, using the standard rules (scoring) for
tennis?
For example, if the probability that player A beats player B on a single point
is 50%, we would expect each player to win about 50% of the matches.
How much better, per point, would player A have to be over player B, for player
A to win win 90% of the matches?
Would he/she have to be a bit better (win a single point with probability 51%)
or have to be a lot better (win a single point with probability 90%)?
Generally, what is the relationship between the probability of winning a single
point and the probability of winning an entire match (composed of sets,
composed of games, composed of points)?
Once we have investigated this issue, we can also investigate the same question
for different rules in tennis: by changing our functions/script we can
easily investigate changes like adjusting
- the minium number of points to win a game, games to win a set, or sets to
win a match.
- the number of points/games/sets needed to be ahead (always 2 in tennis) to
win a game/set/match.
All these rule changes would require us to change the simulation in a minor
way (by changing some numbers in our script); for radically different rules,
we would have to revise the Python code in our functions/script more
extensively.
Here are a summary of the rules of tennis: how to win games, sets, and matches
(which are actually all similar).
- Games consisist of points won by each player: to win a game, a player must
have won at least 4 points, and have won at least 2 more points than the
other player.
- Sets consisist of games won by each player: to win a set, a player must
have won at least 6 games, and have won at least 2 more games than the
other player.
- Matches consisist of sets won by each player: to win a match, a player must
have won at least 3 sets, and have won at least 2 more sets than the
other player.
Write your functions/script in the tennis.py module.
- Write a for loop using frange function, already written in
the tennis.py module.
It should print all the values from .45 to .55 inclusive, in
step of .01.
Some of these numbers may print a bit funny (don't worry about that now).
Put this code in a comment and leave it at the bottom of the
tennis.py module (writing the code specified below in between).
- Define the function point_winner with the header
point_winner(percent_A_win_point)
This function returns either 'A' or 'B' as the winner of one
point in a tennis game, given that percent_A_win_point's argument
will be a float in the range [0.0,1.0] where 0.0 means
A wins 0% of the points (never) and 1.0 means A wins 100% of the
points (always); if percent_A_win_point is .50 it means A
wins 50% of the points (half).
To simulate a point, we will use the rand function in the random
module.
Its header is random.random() -> float: (yes, a parameterless
function).
When called, it returns a random float in the range [0.0,1.0]
inclusive, such that each value in this range is equally likely.
So random.random is parametrless because it always returns a result
in the same range.
This function should return 'A' if the random number is <=
percent_A_win_point, and 'B' otherwise.
For example, if percent_A_win_point is .75, it means that 75% of
the random numbers generated will have a value <=
percent_A_win_point, so this function will return 'A' 75% of
the time.
- Define the function A_win_stats with the header
A_win_stats(percent_A_win_point, times_to_play, trace=False)
Primarily this function calls the point_winner function
times_to_play times and returns the percentage of points that A wins.
If trace is True it also prints out the details of each point.
So, if we executed the following script after defining the function
result = A_win_stats(.50, 10, True)
print('A won',str(result)+'%')
The console might contain (might, because random number are invovled) the
following trace and final print.
Playing 10 points with percent_A_win_point = 0.50
point 1 winner = B
point 2 winner = B
point 3 winner = A
point 4 winner = B
point 5 winner = B
point 6 winner = A
point 7 winner = A
point 8 winner = A
point 9 winner = A
point 10 winner = A
A won 60.0 percent of the points
A won 60.0%
Notice that all lines but the last are printed by the A_win_stats
function; the last is printed by the second statement above.
If instead our script specified trace=False, it would print only
A won 60.0%
So admittedly this function is strange because it primarily computes a value,
but optionally it outputs information to the console, tracing its actions.
Define the function A_win_stats and use the script above to test it with
different perecentages for A winning, both with tracing on and off.
With tracing off, play thousands or millions of points and observe that the
percentage of time A wins is very close to the argument passed to the first
parameter of A_win_stats.
Hint: my function is 13 lines long
- Define the function game_winner with the header
game_winner(percent_A_win_point)
This function simulates a full game of tennis by calling point_winner
repeatedly, until one player wins (according to the rules of tennis above):
the function returns 'A' or 'B'.
Hint: keep track of the number or points won by each player; write an
indefinite loop that terminates when one play has won the game according to
the rules; return the letter for that player.
While debugging this function you might print the winner of each point,
to see that the function is following the scoring rules correctly; later
you can comment-out this printing.
My function is 12 lines long.
- Make a copy of your original A_win_stats function and comment out
one version.
Modify the uncommented-out version so that it calls game_winner and
for the following script
result = A_win_stats(.50, 10, trace=True)
print('A won',str(result)+'%')
produces the following output on the console.
Notice that some of the words have changed.
Playing 10 games with percent_A_win_point = 0.5
game 1 winner = B
game 2 winner = A
game 3 winner = B
game 4 winner = B
game 5 winner = A
game 6 winner = B
game 7 winner = B
game 8 winner = A
game 9 winner = B
game 10 winner = A
A won 40.0 percent of the games
A won 40.0%
- Rewrite the function A_win_stats so that it can be used to call
either the point_winner or game_winner function and
print the right information point/points or
game/games.
Generalize it header to
A_win_stats(percent_A_win_point, play_function, times_to_play, trace=False, unit=None, suffix='s')
Doing so allows us to call A_win_stats in many different ways:
result = A_win_stats(.50, point__winner, 10, True, 'point','s')
result = A_win_stats(.50, game_winner, 10, True, 'game')
result = A_win_stats(.50, game_winner, 1000)
The first calls the point_winner function 10 times with tracing,
printing point/points.
The second calls the game_winner function 10 times with tracing,
printing game/games (with suffix binding to its default
argument 's').
The third calls the game_winner function 1000 times with no
tracing: the last three parameters bind to their default values, and because
tracing binds to False the other two parameters are never used.
After rewriting your A_win_stats function, ensure each of these three
function calls works as described above.
- Define the function set_winner with the header
set_winner(percent_A_win_point)
This function simulates a full set of tennis by calling game_winner
repeatedly, until one player wins (according to the rules of tennis above):
the function returns 'A' or 'B'.
Hint: set_winner and game_winner have identical structure; it
should be simple to copy/paste game_winner and then modify it to
define set_winner.
Write a script to call A_win_stats and play 10 sets with tracing on,
and then play 1,000 sets with tracing off.
- Define the function match_winner with the header
match_winner(percent_A_win_point)
This function simulates a full set of tennis by calling set_winner
repeatedly, until one player wins (according to the rules of tennis above):
the function returns 'A' or 'B'.
Hint: match_winner and set_winner and game_winner have
identical structure; it should be simple to copy/paste one of these
functions and then modify it to define match_winner
Write a script to call A_win_stats and play 10 matches with tracing on,
and then play 1,000 matches with tracing off.
- Write a script at the bottom of this module that prompts the user for
a range of winning percentages for player A (a minimum, maximum, and
step) and the number of matches to play, and computes and tabulates the
results showing how the differences in the percentage of winning a point,
compound to produce the differences in the percentages of winning a match.
Here is an example of my final script running.
I supplied default values to the prompting functions (they automatically appear
in brackets) and just pressed enter to use those default values when prompted.
Of course because we are using random numbers, your answer may be different.
What is surprising is how senstiive winning matches is to winning points: a
slightly better percentage for winning points translates into a much lareger
percentage for winning matches.
Enter minimum percentage[0.45]:
Enter maximum percentage[0.55]:
Enter percentage step[0.01]:
Enter matches to play[10000]:
with percent_A_win_point = 45.0% A wins 2.3% of the matches
with percent_A_win_point = 46.0% A wins 5.7% of the matches
with percent_A_win_point = 47.0% A wins 10.9% of the matches
with percent_A_win_point = 48.0% A wins 20.2% of the matches
with percent_A_win_point = 49.0% A wins 33.9% of the matches
with percent_A_win_point = 50.0% A wins 50.1% of the matches
with percent_A_win_point = 51.0% A wins 65.8% of the matches
with percent_A_win_point = 52.0% A wins 79.2% of the matches
with percent_A_win_point = 53.0% A wins 88.7% of the matches
with percent_A_win_point = 54.0% A wins 94.2% of the matches
with percent_A_win_point = 55.0% A wins 97.3% of the matches
An upcoming lecture (before the project is dues) will cover printing
float values nicely.
|