Note: Click on "Kernel" > "Restart Kernel and Run All" in JupyterLab after finishing the exercises to ensure that your solution runs top to bottom without any errors. If you cannot run this file on your machine, you may want to open it in the cloud .
The exercises below assume that you have read the third part of Chapter 4.
The ...
's in the code cells indicate where you need to fill in code snippets. The number of ...
's within a code cell give you a rough idea of how many lines of code are needed to solve the task. You should not need to create any additional code cells for your final solution. However, you may want to use temporary code cells to try out some ideas.
In this exercise, you will model the throwing of dice within the context of a guessing game similar to the one shown in the "Example: Guessing a Coin Toss" section in Chapter 4 .
As the game involves randomness, we import the random module from the standard library
. To follow best practices, we set the random seed as well.
import random
random.seed(42)
A die has six sides that we labeled with integers 1
to 6
in this exercise. For a fair die, the probability for each side is the same.
Q1: Model a fair_die
as a list
object!
fair_die = ...
Q2: What function from the random module that we have seen already is useful for modeling a single throw of the
fair_die
? Write a simple expression (i.e., one function call) that draws one of the equally likely sides! Execute the cell a couple of times to "see" the probability distribution!
...
Let's check if the fair_die
is indeed fair. To do so, we create a little numerical experiment and throw the fair_die
100000
times. We track the six different outcomes in a list
object called throws
that we initialize with all 0
s for each outcome.
Q3: Complete the for
-loop below such that it runs 100000
times! In the body, use your answer to Q2 to simulate a single throw of the fair_die
and update the corresponding count in throws
!
Hints: You need to use the indexing operator []
and calculate an index
in each iteration of the loop. Do do not actually need the target variable provided by the for
-loop and may want to indicate that with an underscore _
.
throws = [0, 0, 0, 0, 0, 0]
for ... in ...:
...
...
...
throws
throws
contains the simulation results as absolute counts.
Q4: Complete the for
-loop below to convert the counts in throws
to relative frequencies stored in a list
called frequencies
! Round the frequencies to three decimals with the built-in round() function!
Hints: Initialize frequencies
just as throws
above. How many iterations does the for
-loop have? 6
or 100000
? You may want to obtain an index
variable with the enumerate() built-in.
frequencies = [0, 0, 0, 0, 0, 0]
for ... in ...:
...
frequencies
Q5: How could we adapt the list
object used above to model an unfair_die
where 1
is as likely as 2
, 2
is twice as likely as 3
, and 3
is twice as likely as 4
, 5
, or 6
, who are all equally likely?
unfair_die = ...
Q6: Copy your solution to Q2 for the unfair_die
! Execute the cell a couple of times to "see" the probability distribution!
...
Q7: Copy and adapt your solutions to Q3 and Q4 to calculate the frequencies
for the unfair_die
!
throws = [0, 0, 0, 0, 0, 0]
frequencies = [0, 0, 0, 0, 0, 0]
for ... in ...:
...
...
...
for ... in ...:
...
frequencies
guess = input("Guess the side of the die: ")
guess
...
Q9: Use a built-in constructor to cast guess
as an int
object!
Hint: Simply wrap guess
or input("Guess the side of the die: ")
with the constructor you choose.
...
Q10: What type of error is raised if guess
cannot be cast as an int
object?
< your answer >
Q11: Write a try
statement that catches the type of error (i.e., your answer to Q10) raised if the user's input cannot be cast as an int
object! Print out some nice error message notifying the user of the bad input!
try:
...
except ...:
...
Q12: Write a function get_guess()
that takes a user's input and checks if it is a valid side of the die! The function should return either an int
object between 1
and 6
or None
if the user enters something invalid.
Hints: You may want to re-use the try
statement from Q11. Instead of printing out an error message, you can also return
directly from the except
-clause (i.e., early exit) with None
. So, the user can make two kinds of input errors and maybe you want to model that with two distinct return None
statements. Also, you may want to allow the user to enter leading and trailing whitespace that gets removed without an error message.
def get_guess():
"""Process the user's input.
Returns:
guess (int / NoneType): either 1, 2, 3, 4, 5 or 6
if the input can be parsed and None otherwise
"""
...
# Check if the user entered an integer.
...
...
...
...
# Check if the user entered a valid side.
...
...
...
Q13 Test your function for all three cases!
get_guess()
Q14: Write an indefinite loop where in each iteration a fair_die
is thrown and the user makes a guess! Print out an error message if the user does not enter something that can be understood as a number between 1
and 6
! The game should continue until the user makes a correct guess.
...
...
...
...
...
...
...
...
...
...