{ "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 }