{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "51f782f1",
   "metadata": {},
   "source": [
    "# 3.1 — Dictionaries & Nested Data\n",
    "\n",
    "\n",
    "**Goal:** store each record as a dictionary, and keep many records in a list or a dictionary. By the end you'll be able to read, change and loop over nested data.\n",
    "\n",
    "**How to use this notebook**\n",
    "\n",
    "- Run cells **top to bottom**. Click a cell and press **Shift + Enter** to run it and move on.\n",
    "- Cells marked **TODO** are yours to finish. Replace the `None` or the `...` with your code.\n",
    "- Under each TODO is a **check cell**. It runs quietly if your code is right. If it fails, it prints a message telling you what to look at. Read the message before you ask for help.\n",
    "- If you change something and things break, use **Kernel → Restart & Run All**."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "9fd0056b",
   "metadata": {},
   "source": [
    "## Part 1 — Why not just a list?\n",
    "\n",
    "Here's how you'd track two things about a shopping list with two lists:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "12b56785",
   "metadata": {},
   "outputs": [],
   "source": [
    "names = [\"Apple\", \"Bread\", \"Milk\"]\n",
    "qtys  = [4, 1, 2]\n",
    "\n",
    "# How many breads? You have to remember that Bread is at position 1.\n",
    "print(qtys[names.index(\"Bread\")])"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f75b0011",
   "metadata": {},
   "source": [
    "That works, but the two lists have to stay in step. If you add a name and forget the quantity, everything after that point is wrong, and Python won't warn you.\n",
    "\n",
    "A **dictionary** keeps each name and its values **together**. Keep going to Part 2."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "46ba0544",
   "metadata": {},
   "source": [
    "## Part 2 — One record is a dictionary\n",
    "\n",
    "A dictionary stores **key: value** pairs inside `{ }`.\n",
    "\n",
    "| What you want | Code | What it does |\n",
    "|---|---|---|\n",
    "| Read a value | `apple[\"qty\"]` | Gives `4`. Error if the key isn't there. |\n",
    "| Change a value | `apple[\"qty\"] = 3` | Replaces the value for that key |\n",
    "| Add a new key | `apple[\"colour\"] = \"red\"` | Adds a new key and value |\n",
    "| Check a key exists | `\"price\" in apple` | `True` or `False` |\n",
    "| Read safely | `apple.get(\"colour\", \"not set\")` | Gives the default if the key is missing |"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "9f49d30f",
   "metadata": {},
   "outputs": [],
   "source": [
    "apple = {\"name\": \"Apple\", \"qty\": 4, \"price\": 0.50}\n",
    "\n",
    "print(apple[\"qty\"])                    # 4\n",
    "apple[\"qty\"] = 3                       # change a value\n",
    "print(apple[\"qty\"])                    # 3\n",
    "print(\"price\" in apple)                # True\n",
    "print(apple.get(\"colour\", \"not set\"))  # not set"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "5d88d151",
   "metadata": {},
   "source": [
    "**Rule of thumb:** use `[ ]` when you know the key is there. Use `.get()` when it might not be."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "21af742d",
   "metadata": {},
   "source": [
    "### Exercise A: make a dictionary\n",
    "\n",
    "Make a dictionary called `book` with three keys: `\"title\"`, `\"author\"` and `\"pages\"`. Use any book you like."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "95c085dc",
   "metadata": {},
   "outputs": [],
   "source": [
    "# TODO: make a dictionary called book with keys \"title\", \"author\" and \"pages\"\n",
    "book = None"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "7718550d",
   "metadata": {},
   "outputs": [],
   "source": [
    "assert isinstance(book, dict), \"book should be a dictionary. Did you use { } ?\"\n",
    "assert set(book.keys()) == {\"title\", \"author\", \"pages\"}, \"check your key spelling: title, author, pages\"\n",
    "print(\"✅ Exercise A done\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "8c5ce68b",
   "metadata": {},
   "source": [
    "### Exercise B: change a value\n",
    "\n",
    "The book has one more page than you wrote down. Change `\"pages\"` to `413`, then print the book."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "b0043588",
   "metadata": {},
   "outputs": [],
   "source": [
    "# TODO: change book[\"pages\"] to 413, then print book"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "08f8b0f6",
   "metadata": {},
   "outputs": [],
   "source": [
    "assert book[\"pages\"] == 413, \"book['pages'] should be 413\"\n",
    "print(\"✅ Exercise B done\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "6c3efaa7",
   "metadata": {},
   "source": [
    "### Exercise C: read a key that might be missing\n",
    "\n",
    "Not every book has a publisher listed. Use `.get()` to store `book.get(\"publisher\", \"not set\")` in a variable called `publisher`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "aea2af56",
   "metadata": {},
   "outputs": [],
   "source": [
    "# TODO: store book.get(\"publisher\", \"not set\") in a variable called publisher\n",
    "publisher = None"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "5d2fc8e5",
   "metadata": {},
   "outputs": [],
   "source": [
    "assert publisher == \"not set\", \"the book has no publisher key, so you should get 'not set'\"\n",
    "print(\"✅ Exercise C done\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f44bfe0b",
   "metadata": {},
   "source": [
    "> **Try this, but don't worry if the error is confusing:** `book[\"publisher\"]` (no `.get`) makes a `KeyError`. That's Python saying \"that key isn't in here.\" It's the most common error in this unit. The fix is to check the spelling, or use `.get()` when the key might be missing."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "60f8b19a",
   "metadata": {},
   "source": [
    "## Part 3 — A list of records\n",
    "\n",
    "When you have many records of the same shape, put them in a list. Loop over the list to visit each record."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "5e15a9d3",
   "metadata": {},
   "outputs": [],
   "source": [
    "items = [\n",
    "    {\"name\": \"Apple\", \"qty\": 4, \"price\": 0.50},\n",
    "    {\"name\": \"Bread\", \"qty\": 1, \"price\": 2.25},\n",
    "    {\"name\": \"Milk\",  \"qty\": 2, \"price\": 1.80},\n",
    "]\n",
    "\n",
    "for item in items:\n",
    "    print(item[\"name\"], item[\"qty\"])"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "1f00fc11",
   "metadata": {},
   "source": [
    "### Exercise D: add up a total\n",
    "\n",
    "Each item's value is `qty * price`. Use a loop to add up the value of **all** the items, store it in `total_value`, and print it.\n",
    "\n",
    "Start with `total_value = 0` and add to it inside the loop."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "2987befe",
   "metadata": {},
   "outputs": [],
   "source": [
    "# TODO: add up qty * price for every item in items. Store the result in total_value.\n",
    "total_value = 0"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "63e5e62f",
   "metadata": {},
   "outputs": [],
   "source": [
    "expected = sum(i[\"qty\"] * i[\"price\"] for i in items)\n",
    "assert abs(total_value - expected) < 0.001, f\"expected {expected}, got {total_value}. Is the loop adding inside it?\"\n",
    "print(\"✅ Exercise D done\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "986a0296",
   "metadata": {},
   "source": [
    "## Part 4 — A dictionary of records (look up by key)\n",
    "\n",
    "If you want to find a record by its name, make the name the key. Compare these two:\n",
    "\n",
    "- A **list** of records: you loop through to find `\"Bread\"`.\n",
    "- A **dictionary** of records: you ask for `inventory[\"bread\"]` directly."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "95ad5365",
   "metadata": {},
   "outputs": [],
   "source": [
    "inventory = {\n",
    "    \"apple\": {\"qty\": 4, \"price\": 0.50},\n",
    "    \"bread\": {\"qty\": 1, \"price\": 2.25},\n",
    "}\n",
    "\n",
    "print(inventory[\"bread\"][\"price\"])     # 2.25\n",
    "\n",
    "# .items() gives you each key and its value together\n",
    "for name, details in inventory.items():\n",
    "    print(name, details[\"qty\"])"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a0819fa9",
   "metadata": {},
   "source": [
    "### Exercise E: build the dictionary from your list\n",
    "\n",
    "Make a new, empty dictionary called `by_name`. Loop over `items` and, for each item, add an entry where:\n",
    "\n",
    "- the **key** is the item's name, and\n",
    "- the **value** is a dictionary with `\"qty\"` and `\"price\"` (not the name again).\n",
    "\n",
    "Example result for one item: `by_name[\"Apple\"] = {\"qty\": 4, \"price\": 0.50}`"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "305dc780",
   "metadata": {},
   "outputs": [],
   "source": [
    "# TODO: build by_name from items. Key = item name. Value = {\"qty\": ..., \"price\": ...}\n",
    "by_name = {}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "56abb2d5",
   "metadata": {},
   "outputs": [],
   "source": [
    "assert len(by_name) == len(items), \"you should have one entry per item\"\n",
    "first = items[0]\n",
    "assert by_name[first[\"name\"]] == {\"qty\": first[\"qty\"], \"price\": first[\"price\"]}, \"check the value for the first item\"\n",
    "print(\"✅ Exercise E done\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "5939a055",
   "metadata": {},
   "source": [
    "### Exercise F: find the lowest stock\n",
    "\n",
    "Find the **name** of the item with the smallest `qty`, using a loop over `by_name.items()`. Store the name in `lowest`.\n",
    "\n",
    "Start with `lowest = None` and `lowest_qty = None`, and update them when you find a smaller quantity."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "85dff7a9",
   "metadata": {},
   "outputs": [],
   "source": [
    "# TODO: find the name with the smallest qty in by_name. Store the name in lowest.\n",
    "lowest = None\n",
    "lowest_qty = None"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "0a3de8b7",
   "metadata": {},
   "outputs": [],
   "source": [
    "expected = min(by_name, key=lambda n: by_name[n][\"qty\"])\n",
    "assert lowest == expected, f\"expected {expected}, got {lowest}\"\n",
    "print(\"✅ Exercise F done\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c6b06334",
   "metadata": {},
   "source": [
    "## Part 5 — Nested data (a dictionary inside a dictionary, with lists inside)\n",
    "\n",
    "Real data often has layers. A gradebook might look like this: each student has a dictionary of subjects, and each subject has a **list** of marks."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "b553d0f4",
   "metadata": {},
   "outputs": [],
   "source": [
    "gradebook = {\n",
    "    \"Priya\": {\"math\": [88, 92, 79], \"science\": [75, 81]},\n",
    "    \"Sam\":   {\"math\": [65, 70, 72], \"science\": [90, 85]},\n",
    "}\n",
    "\n",
    "print(gradebook[\"Priya\"])              # the whole record for Priya\n",
    "print(gradebook[\"Priya\"][\"math\"])      # [88, 92, 79]\n",
    "print(gradebook[\"Priya\"][\"math\"][1])   # 92: the second math mark"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "932707b9",
   "metadata": {},
   "source": [
    "**How to read it:** go left to right, one layer at a time.\n",
    "\n",
    "`gradebook[\"Priya\"][\"math\"][1]`\n",
    "1. the student (`\"Priya\"`), then\n",
    "2. the subject (`\"math\"`), then\n",
    "3. the position in that list (`1`, which is the **second** mark, since counting starts at 0)."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "62736e11",
   "metadata": {},
   "source": [
    "### Exercise G: add a mark\n",
    "\n",
    "Sam got a 95 in science. Add `95` to the end of Sam's science list.\n",
    "\n",
    "Use `.append()`, which adds an item to the end of a list."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "b71e0e1b",
   "metadata": {},
   "outputs": [],
   "source": [
    "# TODO: add 95 to the end of gradebook[\"Sam\"][\"science\"]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "fce3363e",
   "metadata": {},
   "outputs": [],
   "source": [
    "assert gradebook[\"Sam\"][\"science\"][-1] == 95, \"95 should be the last science mark for Sam\"\n",
    "assert len(gradebook[\"Sam\"][\"science\"]) == 3, \"Sam should now have 3 science marks\"\n",
    "print(\"✅ Exercise G done\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "88a3fb80",
   "metadata": {},
   "source": [
    "### Exercise H: write a function\n",
    "\n",
    "Write a function called `average` that takes a list of numbers and returns their average.\n",
    "\n",
    "Average = the total divided by how many there are. Use `sum()` and `len()`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "60a872a5",
   "metadata": {},
   "outputs": [],
   "source": [
    "# TODO: write a function called average(marks) that returns the average of the list\n",
    "def average(marks):\n",
    "    pass"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "da374a04",
   "metadata": {},
   "outputs": [],
   "source": [
    "assert abs(average([10, 20, 30]) - 20) < 0.001, \"average of 10, 20, 30 should be 20\"\n",
    "assert abs(average(gradebook[\"Priya\"][\"math\"]) - (88 + 92 + 79) / 3) < 0.001, \"check Priya's math average\"\n",
    "print(\"✅ Exercise H done. Priya's math average:\", round(average(gradebook[\"Priya\"][\"math\"]), 1))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a189872e",
   "metadata": {},
   "source": [
    "### Exercise I: loop through every student\n",
    "\n",
    "Make a new dictionary called `math_avgs`. For each student, store their **math** average in it, using the `average` function from Exercise H.\n",
    "\n",
    "Example: `math_avgs[\"Priya\"]` should hold Priya's math average."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "87d34e86",
   "metadata": {},
   "outputs": [],
   "source": [
    "# TODO: loop through gradebook and store each student's math average in math_avgs\n",
    "math_avgs = {}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "5ee552e3",
   "metadata": {},
   "outputs": [],
   "source": [
    "assert set(math_avgs.keys()) == set(gradebook.keys()), \"you should have one math average per student\"\n",
    "assert abs(math_avgs[\"Sam\"] - average(gradebook[\"Sam\"][\"math\"])) < 0.001, \"check Sam's math average\"\n",
    "print(\"✅ Exercise I done\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "98fcbc1f",
   "metadata": {},
   "source": [
    "## Part 6 — Safe looping\n",
    "\n",
    "Two things trip people up when they loop over a dictionary:\n",
    "\n",
    "1. **Changing a dictionary while you loop over it** can break the loop. If you need to add or remove entries, first make a copy of the keys, then loop over the copy.\n",
    "2. **Two records with the same key** overwrite each other with no error. Decide what your key is before you start. For example, if two students can have the same name, use a student ID as the key."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "ac17ef21",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Safe: loop over a copy of the keys\n",
    "for name in list(gradebook.keys()):\n",
    "    if name == \"Sam\":\n",
    "        gradebook[name][\"math\"].append(100)   # changing values is fine\n",
    "\n",
    "print(gradebook[\"Sam\"][\"math\"])"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "8f37d375",
   "metadata": {},
   "source": [
    "## Part 7 — Your turn: your own record\n",
    "\n",
    "Think about the app you're building. Pick **one** record from it (one item, one student, one book, one player, one budget category).\n",
    "\n",
    "Write a dictionary for that one record. Use at least three keys. Don't copy the examples above. Use your own names."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "2287bcb8",
   "metadata": {},
   "outputs": [],
   "source": [
    "# TODO: make a dictionary called my_record for one record from your app. At least 3 keys.\n",
    "my_record = None"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "22992cf7",
   "metadata": {},
   "outputs": [],
   "source": [
    "assert isinstance(my_record, dict), \"my_record should be a dictionary\"\n",
    "assert len(my_record) >= 3, \"use at least 3 keys\"\n",
    "print(\"✅ Exercise J done. Your record:\", my_record)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "708072f4",
   "metadata": {},
   "source": [
    "Now answer in one or two sentences, in a markdown cell (double-click this cell to edit it):\n",
    "\n",
    "> **My data choice:** I'm using a *list / dictionary* of records because ______________. The key for each record is ______________."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c5b5c22f",
   "metadata": {},
   "source": [
    "## Part 8 — More practice in other contexts\n",
    "\n",
    "The same ideas show up everywhere. Each of these uses a list or a dictionary of records, so practise picking the right loop for the question you're asking."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e61c95cf",
   "metadata": {},
   "source": [
    "### Context 1: Library\n",
    "\n",
    "Each book is a dictionary. Find all the books longer than 300 pages and put their **titles** in a list called `long_books`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "236f2f6a",
   "metadata": {},
   "outputs": [],
   "source": [
    "books = [\n",
    "    {\"title\": \"Dune\", \"pages\": 412, \"borrowed\": False},\n",
    "    {\"title\": \"Holes\", \"pages\": 233, \"borrowed\": True},\n",
    "    {\"title\": \"Emma\", \"pages\": 474, \"borrowed\": False},\n",
    "]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "ffdbbcf9",
   "metadata": {},
   "outputs": [],
   "source": [
    "# TODO: make long_books, a list of titles for books with more than 300 pages\n",
    "long_books = []"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "9797fc49",
   "metadata": {},
   "outputs": [],
   "source": [
    "assert long_books == [\"Dune\", \"Emma\"], f\"expected ['Dune', 'Emma'], got {long_books}\"\n",
    "print(\"✅ Library done\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "73db6e17",
   "metadata": {},
   "source": [
    "### Context 2: Sports team\n",
    "\n",
    "Each player's stats are a dictionary inside a dictionary. Add up **all** the goals for the team and store the total in `team_goals`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "cea767a0",
   "metadata": {},
   "outputs": [],
   "source": [
    "players = {\n",
    "    \"Ana\": {\"goals\": 3, \"assists\": 1},\n",
    "    \"Ben\": {\"goals\": 0, \"assists\": 4},\n",
    "    \"Cara\": {\"goals\": 5, \"assists\": 2},\n",
    "}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "c47baef6",
   "metadata": {},
   "outputs": [],
   "source": [
    "# TODO: add up goals for every player into team_goals\n",
    "team_goals = 0"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "ca6e4c91",
   "metadata": {},
   "outputs": [],
   "source": [
    "assert team_goals == 8, f\"expected 8, got {team_goals}\"\n",
    "print(\"✅ Sports team done\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "2045fe10",
   "metadata": {},
   "source": [
    "### Context 3: Recipe\n",
    "\n",
    "A recipe is a dictionary of ingredients and amounts in grams. Make a new dictionary called `double` that has **twice** each amount. Don't change the original `recipe`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "fa8ff2a9",
   "metadata": {},
   "outputs": [],
   "source": [
    "recipe = {\"flour\": 250, \"sugar\": 100, \"butter\": 80}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "5969ea2f",
   "metadata": {},
   "outputs": [],
   "source": [
    "# TODO: make double, a new dictionary with each amount in recipe multiplied by 2\n",
    "double = {}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "89dcb52b",
   "metadata": {},
   "outputs": [],
   "source": [
    "assert double[\"flour\"] == 500, \"flour should be 500\"\n",
    "assert recipe[\"flour\"] == 250, \"don't change the original recipe\"\n",
    "print(\"✅ Recipe done\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "718572a3",
   "metadata": {},
   "source": [
    "### Context 4: Bike shop stock\n",
    "\n",
    "Find the names of every part with **no stock** (`stock` is `0`). Store them in a list called `out_of_stock`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "d3b24a4d",
   "metadata": {},
   "outputs": [],
   "source": [
    "parts = [\n",
    "    {\"name\": \"tube\", \"stock\": 2},\n",
    "    {\"name\": \"brake pad\", \"stock\": 0},\n",
    "    {\"name\": \"chain\", \"stock\": 5},\n",
    "    {\"name\": \"cable\", \"stock\": 0},\n",
    "]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "c9a0cb92",
   "metadata": {},
   "outputs": [],
   "source": [
    "# TODO: make out_of_stock, a list of names where stock is 0\n",
    "out_of_stock = []"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "492b8ce7",
   "metadata": {},
   "outputs": [],
   "source": [
    "assert out_of_stock == [\"brake pad\", \"cable\"], f\"got {out_of_stock}\"\n",
    "print(\"✅ Bike shop done\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "db5fd165",
   "metadata": {},
   "source": [
    "### Context 5: School timetable (nested lists inside a dictionary)\n",
    "\n",
    "Each day maps to a **list** of classes. How many classes are on Monday? Store the number in `monday_count`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "d660198a",
   "metadata": {},
   "outputs": [],
   "source": [
    "timetable = {\n",
    "    \"Mon\": [\"Math\", \"Comp Sci\", \"English\"],\n",
    "    \"Tue\": [\"Science\"],\n",
    "}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "ce2a130e",
   "metadata": {},
   "outputs": [],
   "source": [
    "# TODO: store the number of classes on Monday in monday_count\n",
    "monday_count = None"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "1d1c5655",
   "metadata": {},
   "outputs": [],
   "source": [
    "assert monday_count == 3, f\"expected 3, got {monday_count}\"\n",
    "print(\"✅ Timetable done\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "80dfc3c6",
   "metadata": {},
   "source": [
    "## You're done with this lesson when…\n",
    "\n",
    "- [ ] I can make a dictionary, change a value, and add a new key\n",
    "- [ ] I can look up a key safely with `.get()`\n",
    "- [ ] I can loop over a list of records\n",
    "- [ ] I can loop over a dictionary of records with `.items()`\n",
    "- [ ] I can read a value from nested data, layer by layer\n",
    "- [ ] I've finished the practice in other contexts (library, team, recipe, bike shop, timetable)\n",
    "- [ ] I can say why I chose a list or a dictionary for my app"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "ed922105",
   "metadata": {},
   "outputs": [],
   "source": [
    "print(\"3.1 complete. Next: 3.2 Saving & Loading Files.\")"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "name": "python"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
