Add new exercises set for chapter 04

This commit is contained in:
Alexander Hess 2020-03-12 00:53:56 +01:00
parent 8dea642ce9
commit c1ad5d8b96
2 changed files with 430 additions and 6 deletions

View file

@ -37,6 +37,28 @@
"## Recursion"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "skip"
}
},
"source": [
"A popular joke among programmers by an unknown author goes like this (cf., [discussion](https://www.quora.com/What-does-the-phrase-in-order-to-understand-recursion-you-must-first-understand-recursion-mean-to-you)):"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "-"
}
},
"source": [
"> \"In order to understand **recursion**, you must first understand **recursion**.\""
]
},
{
"cell_type": "markdown",
"metadata": {
@ -859,7 +881,7 @@
"name": "stdout",
"output_type": "stream",
"text": [
"37.3 µs ± 1.25 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)\n"
"35.2 µs ± 971 ns per loop (mean ± std. dev. of 7 runs, 100 loops each)\n"
]
}
],
@ -881,7 +903,7 @@
"name": "stdout",
"output_type": "stream",
"text": [
"11.4 ms ± 144 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)\n"
"11.2 ms ± 81.1 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)\n"
]
}
],
@ -903,7 +925,7 @@
"name": "stdout",
"output_type": "stream",
"text": [
"3.63 s ± 0 ns per loop (mean ± std. dev. of 1 run, 1 loop each)\n"
"3.67 s ± 0 ns per loop (mean ± std. dev. of 1 run, 1 loop each)\n"
]
}
],
@ -925,7 +947,7 @@
"name": "stdout",
"output_type": "stream",
"text": [
"5.93 s ± 0 ns per loop (mean ± std. dev. of 1 run, 1 loop each)\n"
"5.94 s ± 0 ns per loop (mean ± std. dev. of 1 run, 1 loop each)\n"
]
}
],
@ -4543,7 +4565,7 @@
"name": "stdout",
"output_type": "stream",
"text": [
"5.24 s ± 0 ns per loop (mean ± std. dev. of 1 run, 1 loop each)\n"
"5.22 s ± 0 ns per loop (mean ± std. dev. of 1 run, 1 loop each)\n"
]
}
],
@ -4824,7 +4846,7 @@
}
},
"source": [
"The `for` statement, on the contrary, makes the actual business logic more apparent by stripping all the **[boilerplate code](https://en.wikipedia.org/wiki/Boilerplate_code)** away."
"The `for` statement, on the contrary, makes the actual business logic more apparent by stripping all the **[boilerplate code](https://en.wikipedia.org/wiki/Boilerplate_code)** away. The variable that is automatically set by Python in each iteration of the loop (i.e., `element` in the example) is called the **target variable**."
]
},
{

View file

@ -0,0 +1,402 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"\n",
"# Chapter 4: Recursion & Looping"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Coding Exercises"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Read [Chapter 4](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/04_iteration_00_lecture.ipynb) of the book. Then, work through the exercises below. The `...` indicate where you need to fill in your answers. You should not need to create any additional code cells."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Throwing the Dice"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"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](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/master/04_iteration_00_lecture.ipynb#Example:-Guessing-a-Coin-Toss).\n",
"\n",
"As the game involves randomness, we import the [random](https://docs.python.org/3/library/random.html) module from the [standard library](https://docs.python.org/3/library/index.html). To follow best practices, we set the random seed as well."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import random"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"random.seed(42)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"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.\n",
"\n",
"**Q1**: Model a `fair_die` as a `list` object!"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"fair_die = ..."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q2**: What function from the [random](https://docs.python.org/3/library/random.html) 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!"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"..."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"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.\n",
"\n",
"**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`!\n",
"\n",
"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 `_`."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"throws = [0, 0, 0, 0, 0, 0]\n",
"\n",
"for ... in ...:\n",
" ...\n",
" ...\n",
" ...\n",
"\n",
"throws"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"`throws` contains the simulation results as absolute counts.\n",
"\n",
"**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()](https://docs.python.org/3/library/functions.html#round) function!\n",
"\n",
"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()](https://docs.python.org/3/library/functions.html#enumerate) built-in."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"frequencies = [0, 0, 0, 0, 0, 0]\n",
"\n",
"for ... in ...:\n",
" ...\n",
"\n",
"frequencies"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**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?"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"unfair_die = ..."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q6**: Copy your solution to **Q2** for the `unfair_die`! Execute the cell a couple of times to \"see\" the probability distribution!"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"..."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q7**: Copy and adapt your solutions to **Q3** and **Q4** to calculate the `frequencies` for the `unfair_die`!"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"throws = [0, 0, 0, 0, 0, 0]\n",
"frequencies = [0, 0, 0, 0, 0, 0]\n",
"\n",
"for ... in ...:\n",
" ...\n",
" ...\n",
" ...\n",
"\n",
"for ... in ...:\n",
" ...\n",
"\n",
"frequencies"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q8**: The built-in [input()](https://docs.python.org/3/library/functions.html#input) allows us to ask the user to enter a `guess`. What is the data type of the object returned by [input()](https://docs.python.org/3/library/functions.html#input)? Assume the user enters the `guess` as a number (i.e., \"1\", \"2\", ...) and not as a text (e.g., \"one\")."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"guess = input(\"Guess the side of the die: \")"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"guess"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"..."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q9**: Use a built-in constructor to cast `guess` as an `int` object!\n",
"\n",
"Hint: Simply wrap `guess` or `input(\"Guess the side of the die: \")` with the constructor you choose."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"..."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q10**: What type of error is raised if `guess` cannot be cast as an `int` object?"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
" ..."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**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!"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"try:\n",
" ...\n",
"except ...:\n",
" ..."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**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.\n",
"\n",
"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."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"def get_guess():\n",
" \"\"\"Process the user's input.\n",
" \n",
" Returns:\n",
" guess (int / NoneType): either 1, 2, 3, 4, 5 or 6\n",
" if the input can be parsed and None otherwise\n",
" \"\"\"\n",
" ...\n",
"\n",
" # Check if the user entered an integer.\n",
" ...\n",
" ...\n",
" ...\n",
" ...\n",
"\n",
" # Check if the user entered a valid side.\n",
" ...\n",
" ...\n",
" ..."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Q13** Test your function for all *three* cases!"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"get_guess()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**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."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"...\n",
"...\n",
"...\n",
"\n",
"...\n",
"...\n",
"...\n",
"...\n",
"...\n",
"...\n",
"..."
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.7.4"
},
"toc": {
"base_numbering": 1,
"nav_menu": {},
"number_sections": false,
"sideBar": true,
"skip_h1_title": true,
"title_cell": "Table of Contents",
"title_sidebar": "Contents",
"toc_cell": false,
"toc_position": {},
"toc_section_display": false,
"toc_window_display": false
}
},
"nbformat": 4,
"nbformat_minor": 4
}