{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Tutorial A9 – Solutions" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "__1__ Write a set of functions that can be used to maintain a shopping-list saved to a file on disk. We want to represent the shopping list in memory as a dictionary with items to buy as keys and quantities as values. On disk we need a text file with two columns (items, quantity). In the first line, add a comment explaining the content (starting with a `#`).\n", "We need the following functions (names are of course free to change):\n", " \n", " - `read`: the function should read a file from disk in the expected format and return a shopping-list dictionary. The function needs to handle the situation in which no file is found to read from." ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [], "source": [ "def read(f):\n", " \"\"\"Read a shopping list\n", " \n", " Args:\n", " f: Shopping-list file on disk\n", " \n", " Returns:\n", " Shopping-list dictionary\n", " \"\"\"\n", " \n", " d = {}\n", " \n", " try:\n", " with open(f) as f_:\n", " for c, line in enumerate(f_):\n", " if line.startswith(\"#\"):\n", " continue\n", " try:\n", " item, q = line.split()\n", " d[item] = int(q)\n", "\n", " except (IndexError, ValueError):\n", " print(\"Parsing error on line {c}\")\n", " \n", " except FileNotFoundError:\n", " print(\"No existing shopping-list found. Creating a new one.\") \n", " \n", " return d" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ " - `write`: the function should get a dictionary and write the current state of the shopping-list to disk." ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [], "source": [ "def write(d, f):\n", " \"\"\"Write a shopping list\n", " \n", " Args:\n", " d: Shopping-list dictionary\n", " f: Shopping-list file on disk\n", " \n", " Returns:\n", " None\n", " \"\"\"\n", " \n", " with open(f, \"w\") as f_:\n", " f_.write(\"# Shopping-list\\n\")\n", " f_.write(\"# By this item; In this amount\\n\")\n", " for k, v in d.items():\n", " f_.write(f\"{k} {v}\\n\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ " - `add_item`: the function should get a new item we need to buy (string) and a quantity (integer; let's neglect units here for the sake of simplicity). The item should be added to our dictionary and the file on disk should be updated automatically. The function needs to know the current state of the shopping-list (the location of the file on disk). __Advanced__ If an item we want to add to the list is already in there, add the quantities." ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [], "source": [ "def add_item(item, quantity=1, f=None):\n", " \"\"\"Add item to shopping list\n", " \n", " Args:\n", " d: Shopping-list dictionary\n", " item (str): What to buy?\n", " qunatity (int): How much to buy?\n", " f: Shopping-list file on disk\n", " \n", " Returns:\n", " Updated dictionary\n", " \"\"\"\n", " \n", " if not f:\n", " f = \"io/shopping_list.dat\"\n", " \n", " d = read(f)\n", " \n", " if item in d:\n", " d[item] += quantity\n", " else:\n", " d[item] = quantity\n", " \n", " write(d, f)\n", " \n", " return d" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ " - __Advanced__ `cross_off_item`: the function should get an item we have bought and a quantity. Subtract the quantity from the corresponding item in the list. Remove the item completely, if we have bought enough. Print a message, if the item was not in the list in the first place." ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [], "source": [ "def cross_off_item(item, quantity=1, f=None):\n", " \"\"\"Add item to shopping list\n", " \n", " Args:\n", " d: Shopping-list dictionary\n", " item (str): What have you bought?\n", " qunatity (int): How much?\n", " f: Shopping-list file on disk\n", " \n", " Returns:\n", " Updated dictionary\n", " \"\"\"\n", " \n", " if not f:\n", " f = \"io/shopping_list.dat\"\n", " \n", " d = read(f)\n", " \n", " if item in d:\n", " d[item] -= quantity\n", " if d[item] < 1:\n", " del d[item]\n", " else:\n", " print(\"Bought item was not on your list.\")\n", " \n", " write(d, f)\n", " \n", " return d" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ " - __Advanced__ `pretty_print`: the function should display the content of the shopping-list dictionary in a nicer format. Print for each item the quantities after a newline and indented by four spaces." ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [], "source": [ "def pretty_print(d):\n", " for k, v in d.items():\n", " print(f\"{k}:\\n {v}\\n\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ " - Demonstrate your functions in action." ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "No existing shopping-list found. Creating a new one.\n", "Milk:\n", " 1\n", "\n" ] } ], "source": [ "# Add our first item\n", "d = add_item(\"Milk\")\n", "pretty_print(d)" ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Milk:\n", " 1\n", "\n", "Sugar:\n", " 1\n", "\n" ] } ], "source": [ "# And another one\n", "d = add_item(\"Sugar\")\n", "pretty_print(d)" ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Milk:\n", " 2\n", "\n", "Sugar:\n", " 1\n", "\n" ] } ], "source": [ "# Actually I will need more milk\n", "d = add_item(\"Milk\")\n", "pretty_print(d)" ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "# Shopping-list\n", "# By this item; In this amount\n", "Milk 2\n", "Sugar 1\n" ] } ], "source": [ "# Show how the file looks like\n", "with open(\"io/shopping_list.dat\") as f_:\n", " for line in f_:\n", " print(line.strip())" ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Sugar:\n", " 1\n", "\n" ] } ], "source": [ "# Went shopping and bought ...\n", "d = cross_off_item(\"Milk\", quantity=3)\n", "pretty_print(d)" ] }, { "cell_type": "code", "execution_count": 11, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Bought item was not on your list.\n", "Sugar:\n", " 1\n", "\n" ] } ], "source": [ "# ... and ...\n", "d = cross_off_item(\"Beer\", quantity=6)\n", "pretty_print(d)" ] } ], "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.6.10" }, "toc": { "base_numbering": 1, "nav_menu": {}, "number_sections": true, "sideBar": true, "skip_h1_title": false, "title_cell": "Table of Contents", "title_sidebar": "Contents", "toc_cell": false, "toc_position": {}, "toc_section_display": true, "toc_window_display": false } }, "nbformat": 4, "nbformat_minor": 4 }