From b56eed576b93237524fe387aacc12c626aa08cef Mon Sep 17 00:00:00 2001 From: Alexander Hess Date: Sun, 1 Nov 2020 22:17:07 +0100 Subject: [PATCH] Add instructor notes for chapter 03 --- 03_conditionals/01_exercises_solved.ipynb | 283 ++++++++++++++++++++++ 03_conditionals/02_exercises_solved.ipynb | 171 +++++++++++++ 2 files changed, 454 insertions(+) create mode 100644 03_conditionals/01_exercises_solved.ipynb create mode 100644 03_conditionals/02_exercises_solved.ipynb diff --git a/03_conditionals/01_exercises_solved.ipynb b/03_conditionals/01_exercises_solved.ipynb new file mode 100644 index 0000000..1ae912a --- /dev/null +++ b/03_conditionals/01_exercises_solved.ipynb @@ -0,0 +1,283 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Note**: Click on \"*Kernel*\" > \"*Restart Kernel and Run All*\" in [JupyterLab](https://jupyterlab.readthedocs.io/en/stable/) *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 ](https://mybinder.org/v2/gh/webartifex/intro-to-python/develop?urlpath=lab/tree/03_conditionals/01_exercises.ipynb)." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Chapter 3: Conditionals & Exceptions (Coding Exercises)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The exercises below assume that you have read [Chapter 3 ](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/develop/03_conditionals/00_content.ipynb).\n", + "\n", + "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." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Discounting Customer Orders" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Q1**: Write a function `discounted_price()` that takes the positional arguments `unit_price` (of type `float`) and `quantity` (of type `int`) and implements a discount scheme for a line item in a customer order as follows:\n", + "\n", + "- if the unit price is over 100 dollars, grant 10% relative discount\n", + "- if a customer orders more than 10 items, one in every five items is for free\n", + "\n", + "Only one of the two discounts is granted, whichever is better for the customer.\n", + "\n", + "The function should then return the overall price for the line item. Do not forget to round appropriately." + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "def discounted_price(unit_price, quantity):\n", + " \"\"\"Calculate the price of a line item in an order.\n", + "\n", + " Args:\n", + " unit_price (float): price of one ordered item\n", + " quantity (int): number of items ordered\n", + "\n", + " Returns:\n", + " line_item_price (float)\n", + " \"\"\"\n", + " # One could implement type casting\n", + " # to ensure correct input data.\n", + " unit_price = float(unit_price)\n", + " quantity = int(quantity)\n", + "\n", + " # Calculate the line item revenue if only\n", + " # the first discount scheme is applied.\n", + " if unit_price <= 100:\n", + " scheme_a = unit_price * quantity\n", + " else:\n", + " scheme_a = 0.9 * unit_price * quantity\n", + "\n", + " # Calculate the line item revenue if only\n", + " # the second discount scheme is applied.\n", + " # \"One in every five\" means we need to figure out\n", + " # how many full groups of five are contained.\n", + " if quantity <= 10:\n", + " scheme_b = unit_price * quantity\n", + " else:\n", + " groups_of_five = quantity // 5\n", + " scheme_b = unit_price * (quantity - groups_of_five)\n", + "\n", + " # Choose the better option for the customer.\n", + " return round(min(scheme_a, scheme_b), 2)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Q2**: Calculate the final price for the following line items of an order:\n", + "- $7$ smartphones @ $99.00$ USD\n", + "- $3$ workstations @ $999.00$ USD\n", + "- $19$ GPUs @ $879.95$ USD\n", + "- $14$ Raspberry Pis @ $35.00$ USD" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "693.0" + ] + }, + "execution_count": 2, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "discounted_price(99, 7)" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "2697.3" + ] + }, + "execution_count": 3, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "discounted_price(999, 3)" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "14079.2" + ] + }, + "execution_count": 4, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "discounted_price(879.95, 19)" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "420.0" + ] + }, + "execution_count": 5, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "discounted_price(35, 14)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Q3**: Calculate the last two line items with order quantities of $20$ and $15$. What do you observe?" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "14079.2" + ] + }, + "execution_count": 6, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "discounted_price(879.95, 20)" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "420.0" + ] + }, + "execution_count": 7, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "discounted_price(35, 15)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + " " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Q4**: Looking at the `if`-`else`-logic in the function, why do you think the four example line items in **Q2** were chosen as they were?" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + " < your answer >" + ] + } + ], + "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.8.6" + }, + "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 +} diff --git a/03_conditionals/02_exercises_solved.ipynb b/03_conditionals/02_exercises_solved.ipynb new file mode 100644 index 0000000..72a61a5 --- /dev/null +++ b/03_conditionals/02_exercises_solved.ipynb @@ -0,0 +1,171 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Note**: Click on \"*Kernel*\" > \"*Restart Kernel and Run All*\" in [JupyterLab](https://jupyterlab.readthedocs.io/en/stable/) *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 ](https://mybinder.org/v2/gh/webartifex/intro-to-python/develop?urlpath=lab/tree/03_conditionals/02_exercises.ipynb)." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Chapter 3: Conditionals & Exceptions (Coding Exercises)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The exercises below assume that you have read [Chapter 3 ](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/develop/03_conditionals/00_content.ipynb).\n", + "\n", + "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." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Fizz Buzz" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The kids game [Fizz Buzz ](https://en.wikipedia.org/wiki/Fizz_buzz) is said to be often used in job interviews for entry-level positions. However, opinions vary as to how good of a test it is (cf., [source ](https://news.ycombinator.com/item?id=16446774)).\n", + "\n", + "In its simplest form, a group of people starts counting upwards in an alternating fashion. Whenever a number is divisible by $3$, the person must say \"Fizz\" instead of the number. The same holds for numbers divisible by $5$ when the person must say \"Buzz.\" If a number is divisible by both numbers, one must say \"FizzBuzz.\" Probably, this game would also make a good drinking game with the \"right\" beverages." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Q1**: First, create a list `numbers` with the numbers from 1 through 100. You could type all numbers manually, but there is, of course, a smarter way. The built-in [range() ](https://docs.python.org/3/library/functions.html#func-range) may be useful here. Read how it works in the documentation. To make the output of [range() ](https://docs.python.org/3/library/functions.html#func-range) a `list` object, you have to wrap it with the [list() ](https://docs.python.org/3/library/functions.html#func-list) built-in (i.e., `list(range(...))`)." + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "numbers = list(range(1, 101))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Q2**: Loop over the `numbers` list and *replace* numbers for which one of the two (or both) conditions apply with text strings `\"Fizz\"`, `\"Buzz\"`, or `\"FizzBuzz\"` using the indexing operator `[]` and the assignment statement `=`.\n", + "\n", + "In [Chapter 1 ](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/develop/01_elements/03_content.ipynb#Who-am-I?-And-how-many?), we saw that Python starts indexing with `0` as the first element. Keep that in mind.\n", + "\n", + "So in each iteration of the `for`-loop, you have to determine an `index` variable as well as check the actual `number` for its divisors.\n", + "\n", + "Hint: the order of the conditions is important!" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "for number in numbers:\n", + " # We know that numbers goes from 1 through 100\n", + " # so the index is just \"number minus 1\".\n", + " index = number - 1\n", + "\n", + " if (number % 3 == 0) and (number % 5 == 0):\n", + " numbers[index] = \"FizzBuzz\"\n", + " elif number % 3 == 0:\n", + " numbers[index] = \"Fizz\"\n", + " elif number % 5 == 0:\n", + " numbers[index] = \"Buzz\"" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [], + "source": [ + "# Alternative: use the enumerate() built-in.\n", + "\n", + "numbers = list(range(1, 101))\n", + "\n", + "for index, number in enumerate(numbers):\n", + " # Use `number % 15 == 0` instead\n", + " # and re-order the clauses.\n", + " if number % 15 == 0:\n", + " numbers[index] = \"FizzBuzz\"\n", + " elif number % 5 == 0:\n", + " numbers[index] = \"Buzz\"\n", + " elif number % 3 == 0:\n", + " numbers[index] = \"Fizz\"" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Q3**: Create a loop that prints out either the number or any of the Fizz Buzz substitutes in `numbers`! Do it in such a way that the output is concise!" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "1 2 Fizz 4 Buzz Fizz 7 8 Fizz Buzz 11 Fizz 13 14 FizzBuzz 16 17 Fizz 19 Buzz Fizz 22 23 Fizz Buzz 26 Fizz 28 29 FizzBuzz 31 32 Fizz 34 Buzz Fizz 37 38 Fizz Buzz 41 Fizz 43 44 FizzBuzz 46 47 Fizz 49 Buzz Fizz 52 53 Fizz Buzz 56 Fizz 58 59 FizzBuzz 61 62 Fizz 64 Buzz Fizz 67 68 Fizz Buzz 71 Fizz 73 74 FizzBuzz 76 77 Fizz 79 Buzz Fizz 82 83 Fizz Buzz 86 Fizz 88 89 FizzBuzz 91 92 Fizz 94 Buzz Fizz 97 98 Fizz Buzz " + ] + } + ], + "source": [ + "for number in numbers:\n", + " print(number, end=\" \")" + ] + } + ], + "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.8.6" + }, + "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 +}