{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "6a9f1e4f-66c6-44b6-b30d-d2af118baaf3",
   "metadata": {},
   "source": [
    "# Control Structures"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "801f8b9c-5732-4189-8c72-daaccb7bf6d3",
   "metadata": {
    "editable": true,
    "slideshow": {
     "slide_type": ""
    },
    "tags": [
     "hide-input",
     "thebe-init",
     "runnable"
    ]
   },
   "outputs": [],
   "source": [
    "import sys\n",
    "from pathlib import Path\n",
    "\n",
    "current = Path.cwd()\n",
    "for parent in [current, *current.parents]:\n",
    "    if (parent / '_config.yml').exists():\n",
    "        project_root = parent  # ← Add project root, not chapters\n",
    "        break\n",
    "else:\n",
    "    project_root = Path.cwd().parent.parent\n",
    "\n",
    "sys.path.insert(0, str(project_root))\n",
    "\n",
    "from shared import thinkpython, diagram, jupyturtle"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c3568ceb",
   "metadata": {},
   "source": [
    "```{contents}\n",
    ":local:\n",
    ":depth: 2\n",
    "```\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "34382656",
   "metadata": {},
   "source": [
    "The three fundamental control structures in computer programming, dictating the order in which instructions are executed within a program, are:\n",
    "\n",
    "1. Sequence logic (sequential flow)\n",
    "2. Selection logic (conditional flow)\n",
    "3. Iteration logic (repetitive flow)\n",
    "\n",
    "By default, programming languages execute statements `sequentially`. Lines of instructions are executed in a defined `sequential` order unless `selection/conditional` statements (if/elif/else) or `iteration` statements (for/while loops) are used. \n",
    "\n",
    "In addition to conditional and iteration, there are other flow control tools such as:\n",
    "- Loop control statements (break, continue) to exit or skip iterations.\n",
    "- Function control (return) to exit a function early.\n",
    "- Exceptions (try/except/raise) to handle or redirect error flow. "
   ]
  },
  {
   "cell_type": "markdown",
   "id": "6bdd7342",
   "metadata": {},
   "source": [
    "Below are examples of conditions and decision-making with `if`, `elif`, and `else`."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "856775a0",
   "metadata": {},
   "source": [
    "## Conditional Statements"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "47038366-9312-4ced-8051-8fb3c81f3a85",
   "metadata": {},
   "source": [
    "The main topic of conditionals is the `if` statement, which executes different code depending on the program's state. `if` is a Python keyword. `if` statements have the same structure as function definitions: a\n",
    "**header** followed by an indented statement or sequence of statements called a **block**.\n",
    "\n",
    "The boolean expression after `if` is called the **condition**.\n",
    "If it is true, the statements in the indented block run. If not, they don't. \n",
    "There is no limit to the number of statements that can appear in the block, but there has to be at least one. Occasionally, it is useful to have a block that does nothing -- usually as a placeholder for code you haven't written yet.\n",
    "In that case, you can use the `pass` statement, which does nothing."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a1cec2e7",
   "metadata": {},
   "source": [
    "To write useful programs, we almost always need the ability to check conditions and adjust the program's behavior accordingly, which involves: \n",
    "- boolean expressions for `True`/`False` decision (e.g., `5 > 3` is `True`), and \n",
    "- logical operators for combining Boolean expressions (e.g.,`2 > 1` `and` `3 > 2` is `True`).\n",
    "\n",
    "Python uses if statements to handle conditional logic, offering several structures to control program flow: \n",
    "1. **conditional** execution (`if`),\n",
    "2. **alternative** execution (`if`/`else`),\n",
    "3. **chained** execution (`if`/`elif`/`else`),\n",
    "4. **nested** conditions, and\n",
    "5. the **`match`** Statement*\n",
    "\n",
    "*not covered presently"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "310f954c",
   "metadata": {},
   "source": [
    "### Boolean Expressions\n",
    "\n",
    "A **boolean expression** is an expression that is either `True` or `False`.\n",
    "For example, the following expressions use the equals operator, `==`, which compares two values and produces `True` if they are equal and `False` otherwise. Remember that there are six relational/comparison operators: `==` `!=` `>` `<` `>=` `<=`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 55,
   "id": "88ea6c58",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "True False\n"
     ]
    }
   ],
   "source": [
    "t_f_1 = 5 == 5\n",
    "t_f_2 = 5 == 7\n",
    "print(t_f_1, t_f_2)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f451fc2d",
   "metadata": {},
   "source": [
    "A common error is to use a **single equal sign** (`=`) instead of a **double equal sign** (`==`).\n",
    "Remember that `=` assigns a value to a variable and `==` compares two values."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "61078e01",
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "x = 5       ### assignment\n",
    "y = 7       ### assignment"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 57,
   "id": "44e9b98f",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "False"
      ]
     },
     "execution_count": 57,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "x == y      ### comparison/relational"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "34a158f5",
   "metadata": {},
   "source": [
    "`True` and `False` are special values that belong to the type `bool`;\n",
    "they are not strings:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 58,
   "id": "42e0217f",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "<class 'bool'>\n",
      "<class 'bool'>\n"
     ]
    }
   ],
   "source": [
    "print(type(True))\n",
    "print(type(False))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "7b3735dd",
   "metadata": {},
   "source": [
    "The `==` operator is one of the **6 relational operators**; the others are:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "32e92b94",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "x != y               # x is not equal to y\n",
    "x > y                # x is greater than y\n",
    "x < y                # x is less than y\n",
    "x >= y               # x is greater than or equal to y\n",
    "x <= y               # x is less than or equal to y"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f969458c",
   "metadata": {},
   "source": [
    "### Logical operators\n",
    "\n",
    "To **combine** boolean values into expressions, we can use **logical operators**.\n",
    "The most common are: \n",
    "`and`, \n",
    "` or`, and \n",
    "`not`.\n",
    "The meaning of these operators is similar to their meaning in English.\n",
    "For example, the value of the following expression is `True` only if `x` is greater than `0` *and* less than `10`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "d3e0fb57",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "x = 5, y = 7\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "print(f\"x = {x}, y = {y}\")\n",
    "\n",
    "x > 0 and x < 10"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "7721ec31",
   "metadata": {},
   "source": [
    "The following expression is `True` if *either or both* of the conditions is true, that is, if the number is divisible by 2 *or* 3:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "10fa578a",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "x % 2 == 0 or y % 7 == 0    ### % is modulus operator, returns remainder of division"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "de6b5ba5",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "False"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "x // 2 == 0 or x // 3 == 0    ### // is floor division operator, returns quotient of division"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "933e14be",
   "metadata": {},
   "source": [
    "Finally, the `not` operator negates a boolean expression, so the following expression is `True` if `x > y` is `False`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 62,
   "id": "e9ff45f0",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "execution_count": 62,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "not x > y"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a1fbef53",
   "metadata": {},
   "source": [
    "Strictly speaking, the operands of a logical operator should be boolean expressions, but Python is not very strict.\n",
    "Any **nonzero** number is interpreted as `True` (**\"truthy\"**):"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 63,
   "id": "59970d58",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "execution_count": 63,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "42 and True"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "4d2b415f",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "False"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "0 or False"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d745d726",
   "metadata": {},
   "source": [
    "This flexibility can be useful, but there are some subtleties to it that can be confusing.\n",
    "You might want to avoid it."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f162ea65",
   "metadata": {},
   "source": [
    "### Conditional execution (`if`)\n",
    "Conditional gives us the ability to check the conditions and is the simplest form of the `if` statement:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "9e4ac2be",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "x\n",
      "x is positive\n"
     ]
    }
   ],
   "source": [
    "print(f\"x\")\n",
    "\n",
    "if x > 0:\n",
    "    print('x is positive')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "6c431798",
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "if x < 0:\n",
    "    pass        # TODO: need to handle negative values!\n",
    "                # if x < 0 is not true, then the program will just \n",
    "                # continue to run without doing anything"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e5dc20a1",
   "metadata": {},
   "source": [
    "### Alternative Execution (`else`)\n",
    "\n",
    "An `if` statement can have a second part, called an `else` clause. If the condition is true, the first indented statement runs; otherwise, the second indented statement runs. For example:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "5cb461f6",
   "metadata": {
    "tags": [
     "skip-execution"
    ]
   },
   "outputs": [
    {
     "name": "stdin",
     "output_type": "stream",
     "text": [
      "Please enter an integer:  3\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "num is odd\n"
     ]
    }
   ],
   "source": [
    "num = int(input(\"Please enter an integer: \")) \n",
    "\n",
    "if num % 2 == 0:                ### % modulus operator\n",
    "    print(\"num is even\")\n",
    "else:\n",
    "    print(\"num is odd\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "2db892ff",
   "metadata": {},
   "source": [
    "In this example, if `num` is even, the remainder when `num` is divided by `2` is `0`, so the condition is `True` and the program displays `num is even`. \n",
    "\n",
    "If `num` is odd, the remainder is `1`, so the condition is false, and the program displays `num is odd`.\n",
    "\n",
    "Since the condition must be true or false, exactly one of the alternatives will run. The alternatives are called **branches**."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "35a12ccb",
   "metadata": {},
   "source": [
    "### Chained Conditional (`elif`)\n",
    "Sometimes there are more than two possibilities, and we need more than two branches. One way to express a computation like that is a **chained conditional**, which includes an `elif` clause.\n",
    "\n",
    "`elif` is an abbreviation of \"else if\" and is used to add multiple conditions inside an `if` block. There is no limit on the number of `elif` clauses. \n",
    "\n",
    "If there is an `else` clause, it has to be at the end, but there doesn’t have to be one.\n",
    "\n",
    "Note that:\n",
    "- Each condition is checked in order.\n",
    "- If the first is false, the next is checked, and so on.\n",
    "- If one of them is true, the corresponding branch runs, and the `if` statement ends.\n",
    "- Even if more than one condition is true, only the first true branch runs."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 93,
   "id": "e35f3784",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "x is medium\n"
     ]
    }
   ],
   "source": [
    "x = 7                       ### sample value to classify\n",
    "\n",
    "if x > 10:\n",
    "    print(\"x is large\")     ### runs only when x is greater than 10\n",
    "elif x > 5:\n",
    "    print(\"x is medium\")    ### runs when x is 6–10\n",
    "else:\n",
    "    print(\"x is small\")     ### runs when x is 5 or less"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 94,
   "id": "ce48e87f",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "positive\n"
     ]
    }
   ],
   "source": [
    "num = 7  # try different values\n",
    "\n",
    "if num > 0:\n",
    "    print(\"positive\")\n",
    "elif num == 0:\n",
    "    print(\"neither positive nor negative\")\n",
    "elif num < 0:\n",
    "    print(\"negative\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e2627f2d",
   "metadata": {},
   "source": [
    "### Nested Conditionals\n",
    "\n",
    "One conditional can also be nested within another. We could have written a conditional to compare two numbers:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "01381c7c",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "x: 5; y: 7\n",
      "x is less than y\n"
     ]
    }
   ],
   "source": [
    "x = 5; y = 7\n",
    "print(f\"x: {x}; y: {y}\")\n",
    "\n",
    "if x == y:\n",
    "    print('x and y are equal')\n",
    "else:\n",
    "    if x < y:\n",
    "        print('x is less than y')\n",
    "    else:\n",
    "        print('x is greater than y')"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f9e0d822",
   "metadata": {},
   "source": [
    "In this example, the outer `if` statement contains two branches:\n",
    "- The first branch contains a simple statement.\n",
    "- The second branch contains another `if` statement with two branches of its own.\n",
    "\n",
    "Those two branches are both simple `print` statements, although they could have been conditional statements as well.\n",
    "\n",
    "Although the indentation of the statements makes the structure apparent, **nested conditionals** can be difficult to read. I suggest you avoid them whenever possible.\n",
    "\n",
    "**Logical operators** often simplify nested conditional statements.\n",
    "Here's an example with a nested conditional."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 69,
   "id": "ff945d3f",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "x is a positive single-digit number.\n"
     ]
    }
   ],
   "source": [
    "if 0 < x:\n",
    "    if x < 10:\n",
    "        print('x is a positive single-digit number.')\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ef461460",
   "metadata": {},
   "source": [
    "The `print` statement runs only if we make it past both conditionals, so we get the same effect with the `and` operator."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 70,
   "id": "593fef85",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "x is a positive single-digit number.\n"
     ]
    }
   ],
   "source": [
    "if 0 < x and x < 10:\n",
    "    print('x is a positive single-digit number.')"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "85f7af2b",
   "metadata": {},
   "source": [
    "For this kind of condition, Python provides a more concise option:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 71,
   "id": "7e2ca9cf",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "x is a positive single-digit number.\n"
     ]
    }
   ],
   "source": [
    "if 0 < x < 10:\n",
    "    print('x is a positive single-digit number.')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "ch02-control-conditionals-exercise-q",
   "metadata": {
    "tags": [
     "thebe-interactive"
    ]
   },
   "outputs": [],
   "source": [
    "### Exercise: Apply a Discount Rule\n",
    "# Use if, elif, and else to assign a discount rate.\n",
    "# Orders of 1000 or more get 15%; orders of 500 or more get 10%; smaller orders get 0%.\n",
    "# Print exactly:\n",
    "# Discount rate: 0.1\n",
    "# Discount amount: 75.0\n",
    "order_total = 750\n",
    "### Your code starts here.\n",
    "\n",
    "\n",
    "\n",
    "### Your code ends here."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "ch02-control-conditionals-exercise-a",
   "metadata": {
    "tags": [
     "hide-input"
    ]
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Discount rate: 0.1\n",
      "Discount amount: 75.0\n"
     ]
    }
   ],
   "source": [
    "### Solution\n",
    "order_total = 750\n",
    "\n",
    "if order_total >= 1000:\n",
    "    discount_rate = 0.15\n",
    "elif order_total >= 500:\n",
    "    discount_rate = 0.10\n",
    "else:\n",
    "    discount_rate = 0\n",
    "\n",
    "discount_amount = order_total * discount_rate\n",
    "\n",
    "print(\"Discount rate:\", discount_rate)\n",
    "print(\"Discount amount:\", discount_amount)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "efb4e97f-7d84-45c2-a942-8751c10b3ff6",
   "metadata": {},
   "source": [
    "## `while` Loops"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "39a3fcd8",
   "metadata": {},
   "source": [
    "A Python while loop repeatedly executes a block of code as long as a specified **condition** remains true. Once the condition evaluates to false, the program continues with the statement following the loop. \n",
    "\n",
    "The syntax of Python `while` loop is:\n",
    "```python\n",
    "while condition:\n",
    "    <body>\n",
    "```\n",
    "where \n",
    "\n",
    "- `while`: is the keyword that begins the loop header.\n",
    "- **condition** is an *expression* evaluated for truthiness that defines the exit condition.\n",
    "- **<body>** consists of one or more statements to execute in each *iteration*.\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "8afb942e",
   "metadata": {},
   "source": [
    "As a general rule:\n",
    "- Use `while` when you don't know how many times the loop will run in advance (e.g., processing until input validation succeeds, or until a condition becomes true).\n",
    "- Use `for` when you know the number of iterations upfront or are iterating through a sequence (list, string, range, etc.), or looping through a file."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "95ab6493",
   "metadata": {},
   "source": [
    "Although all condition-based, there are several common patterns of `while` loops:\n",
    "\n",
    "| Type | Also Called | Condition Location | Key Feature | Use Case |\n",
    "|------|-------------|-------------------|-------------|----------|\n",
    "| **Condition**-Controlled | Standard | At the top (header) | Repeats while a condition is `True` | When you know the exit condition upfront |\n",
    "| **Count**-Controlled | Counter | At the top (header) | Uses incrementing/decrementing counter variable | When you know how many iterations you need |\n",
    "| **Sentinel**-Controlled | Infinite with break | In the body | Runs infinite loop; breaks on special value | Reading input until user says \"quit\" |"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "fdf0f2cd",
   "metadata": {},
   "source": [
    "### Condition-Controlled (Indefinite)\n",
    "\n",
    "In condition-controlled while loops, you have no idea how many times it will run; it depends on what happens during the loop. "
   ]
  },
  {
   "cell_type": "markdown",
   "id": "31a6733a",
   "metadata": {},
   "source": [
    "The syntax of a standard while loop is:\n",
    "\n",
    "```python\n",
    "while [condition]:\n",
    "    [statement(s)]\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "15b34f54",
   "metadata": {},
   "source": [
    "Here's a concrete example: rolling a random number between 1 and 10 until we get a 7. The loop checks if `num != 7` at the beginning of each iteration. As long as the rolled number is not 7, it prints the result and rolls again. When we finally roll a 7, the condition becomes false and the loop stops."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 122,
   "id": "b1b22e4a",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Rolled: 6\n",
      "Rolled: 6\n",
      "Rolled: 6\n",
      "Rolled: 8\n",
      "Rolled: 5\n",
      "Rolled: 1\n",
      "Rolled: 7\n"
     ]
    }
   ],
   "source": [
    "import random\n",
    "num = 0\n",
    "while num != 7:                 ### could be 1 try, could be 100\n",
    "    num = random.randint(1, 10)\n",
    "    print(f\"Rolled: {num}\")\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "90c0747b",
   "metadata": {},
   "source": [
    "### Count-Controlled Loops (Definite)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "24eb4dc7",
   "metadata": {},
   "source": [
    "In count-controlled while loops, you control exactly how many times the loop will run before it starts."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "7567ddf4",
   "metadata": {},
   "source": [
    "The syntax for a counter-controlled loop:\n",
    "\n",
    "```python\n",
    "[counter] = [initial value]\n",
    "while [counter] [comparison] [limit]:\n",
    "    [statement(s)]\n",
    "    [counter] += [increment]  # or -= for decrement\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "167ebde3",
   "metadata": {},
   "source": [
    "In the following example, the while loop runs as long as the variable count is less than 5. A `while` loop requires a **counter** to increment/decrement variable to be ready. In this example, we need to define an **indexing variable**, count."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 96,
   "id": "4c394aa6",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "count is: 1\n",
      "count is: 2\n",
      "count is: 3\n",
      "count is: 4\n"
     ]
    }
   ],
   "source": [
    "count = 1                   ### initialize the variable\n",
    "while count < 5:            ### condition to check\n",
    "    print(f'count is: {count}') ### format string to print count\n",
    "    count = count+1             ### increment count to avoid infinite loop"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "6ea84d16",
   "metadata": {},
   "source": [
    "### Sentinel-Controlled Loop\n",
    "\n",
    "A sentinel value is a special value that signals the end of input. A classic example is reading user input until \"quit\" is entered.\n",
    "\n",
    "The syntax for a sentinel value loop:\n",
    "\n",
    "```python\n",
    "while True:\n",
    "    [input/process data]\n",
    "    if [sentinel value detected]:\n",
    "        break\n",
    "    [process the data]\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "bf900442",
   "metadata": {},
   "source": [
    "For example, to create a guessing game, we can do:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "9970da86-79d7-4dd9-bf63-59ff93664c6e",
   "metadata": {
    "tags": [
     "skip-execution"
    ]
   },
   "outputs": [
    {
     "name": "stdin",
     "output_type": "stream",
     "text": [
      "Enter an int between 0 and 7 (or 'quit' to stop):  1\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Sorry, try again.\n"
     ]
    },
    {
     "name": "stdin",
     "output_type": "stream",
     "text": [
      "Enter an int between 0 and 7 (or 'quit' to stop):  2\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Sorry, try again.\n"
     ]
    },
    {
     "name": "stdin",
     "output_type": "stream",
     "text": [
      "Enter an int between 0 and 7 (or 'quit' to stop):  3\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "You guessed right! It's 3!\n"
     ]
    }
   ],
   "source": [
    "import random    ### import the random module\n",
    "num = random.randint(1, 7)    ### randomly generate 1 < num < 7\n",
    "\n",
    "while True:\n",
    "    value = input(\"Enter an int between 0 and 7 (or 'quit' to stop): \")\n",
    "    if value.lower() == 'quit':\n",
    "        print(\"Exiting the loop.\")\n",
    "        break\n",
    "    else:\n",
    "        value = int(value)\n",
    "        if value == num:\n",
    "            print(f\"You guessed right! It's {num}!\")\n",
    "            break\n",
    "        else:\n",
    "            print(\"Sorry, try again.\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a0910673",
   "metadata": {},
   "source": [
    "### Infinite Loops\n",
    "\n",
    "An **infinite loop** is a while loop that never stops because its condition never becomes False. This happens when you forget to update the variable controlling the condition.\n",
    "\n",
    "For example, this code would loop forever:\n",
    "```python\n",
    "count = 1\n",
    "while count < 5:\n",
    "    print(f'count is: {count}')\n",
    "    ### Oops! We forgot to increment count — condition never changes!\n",
    "```\n",
    "\n",
    "**Prevention**: Always make sure your loop variable changes in a way that will eventually make the condition False."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "ch02-control-while-exercise-q",
   "metadata": {
    "tags": [
     "thebe-interactive"
    ]
   },
   "outputs": [],
   "source": [
    "### Exercise: Run a Reorder Loop\n",
    "# Use a while loop to simulate daily sales until inventory reaches the reorder point.\n",
    "# Subtract 6 units each day.\n",
    "# Print exactly:\n",
    "# Day 1 inventory: 22\n",
    "# Day 2 inventory: 16\n",
    "# Day 3 inventory: 10\n",
    "# Reorder now\n",
    "inventory = 28\n",
    "reorder_point = 10\n",
    "daily_sales = 6\n",
    "day = 0\n",
    "### Your code starts here.\n",
    "\n",
    "\n",
    "\n",
    "### Your code ends here."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "ch02-control-while-exercise-a",
   "metadata": {
    "tags": [
     "hide-input"
    ]
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Day 1 inventory: 22\n",
      "Day 2 inventory: 16\n",
      "Day 3 inventory: 10\n",
      "Reorder now\n"
     ]
    }
   ],
   "source": [
    "### Solution\n",
    "inventory = 28\n",
    "reorder_point = 10\n",
    "daily_sales = 6\n",
    "day = 0\n",
    "\n",
    "while inventory > reorder_point:\n",
    "    day += 1\n",
    "    inventory -= daily_sales\n",
    "    print(f\"Day {day} inventory: {inventory}\")\n",
    "\n",
    "print(\"Reorder now\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "507ec64b",
   "metadata": {},
   "source": [
    "## `for` Loops"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "48f29d6d-a1b7-4762-bc8c-904b9e073fb8",
   "metadata": {},
   "source": [
    "A `for` loop repeats a block of code by iterating through a sequence, so it typically runs a known, fixed number of times without manual index bookkeeping.\n",
    "\n",
    "Common kinds of `for` loops:\n",
    "1. Loop through a sequence (`list`, `tuple`, `string`).\n",
    "2. Loop using `range()` to control the number of iterations.\n",
    "3. Loop with `enumerate()` to get both index and value.\n",
    "4. Loop with `zip()` to iterate over multiple sequences in parallel.\n",
    "5. Nested loops (loop within a loop).\n",
    "6. Loop through files to process each line."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "fc842fce",
   "metadata": {},
   "source": [
    "### For Loop Syntax and Components\n",
    "\n",
    "Every `for` loop has key parts:\n",
    "\n",
    "- **Header**: The `for` statement line that defines the loop. It ends with a **colon** (`:`).\n",
    "- **Loop variable**: The variable (e.g., `item`) that holds the current element in each iteration.\n",
    "- **Sequence**: The collection being iterated (list, string, range, etc.).\n",
    "- **Body**: The indented block of code that runs each iteration.\n",
    "- **Indentation**: Python uses indentation to define the body—typically 4 spaces. Every line in the body must be indented the same amount.\n",
    "\n",
    "```python\n",
    "for item in sequence:\n",
    "    # body: this block runs once per item\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "37ecfb54-9dfb-4db0-88b7-2f81e84e91e3",
   "metadata": {},
   "source": [
    "### Loop through sequences\n",
    "\n",
    "The most common use of `for` loops is to iterate over a sequence (list, tuple, string, etc.) and process each element one at a time. The loop variable automatically takes on the value of each item as the loop executes.\n",
    "\n",
    "- Loop through a list with `for` and `in`.\n",
    "- Iterate over items in a sequence with a loop variable, **one item at a time**."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "5520cae5",
   "metadata": {},
   "source": [
    "#### Looping with `range()`\n",
    "\n",
    "The `range()` function generates a sequence of numbers that a `for` loop can step through **one at a time**. \n",
    "\n",
    "The syntax of the range function is: \n",
    "\n",
    "```python\n",
    "range(start, stop, step)\n",
    "```\n",
    "where the function parameters are:\n",
    "- start – where to begin (inclusive, default to 0)\n",
    "- stop – where to end (**exclusive**)\n",
    "- step – how much to increment each time"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "aa63dd26",
   "metadata": {},
   "source": [
    "We can use a `for` loop that uses the `range` function to display a sequence of numbers. Observe the examples below for what the parameters do for us."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "d8bee5da",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0 1 2 3 4 5 6 7 8 9 "
     ]
    }
   ],
   "source": [
    "for i in range(10):       ### start\n",
    "    print(i, end=' ')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "cd86745e",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1 2 3 4 "
     ]
    }
   ],
   "source": [
    "for i in range(1, 5):    ### start, stop\n",
    "    print(i, end=' ')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "c0a8ee15",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1 3 5 7 9 "
     ]
    }
   ],
   "source": [
    "for i in range(1, 10, 2): ### start, stop, step\n",
    "    print(i, end=' ')"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d2b1d5d0",
   "metadata": {},
   "source": [
    "#### Lists\n",
    "\n",
    "Lists are one of the most common Python sequences. When you loop over a list, the loop variable takes on each element in order, letting you process each item one at a time."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 58,
   "id": "cbc19581",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1 2 3 4 5 "
     ]
    }
   ],
   "source": [
    "### loop through an integer list\n",
    "nums = [1, 2, 3, 4, 5]\n",
    "for num in nums:               ### n loops\n",
    "    print(num, end=\" \")         ### print n times of whatever"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "2d0d9073",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "apple banana cherry "
     ]
    }
   ],
   "source": [
    "### looping through a string list\n",
    "fruits = [\"apple\", \"banana\", \"cherry\"]\n",
    "for fruit in fruits:\n",
    "    print(fruit, end=\" \")                   ### apple banana cherry"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "1f31a59f",
   "metadata": {},
   "source": [
    "#### Strings\n",
    "\n",
    "We can also loop through strings because strings are sequences as well. We can:\n",
    "\n",
    "1. directly loop through a string, or\n",
    "2. turn a string into a list for better manipulation."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "c6c4ab9f",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "a b c d e \n",
      "w e   a r e   a l l   j u s t   p r i s o n e r s   h e r e   o f   o u r   o w n   d e v i c e "
     ]
    }
   ],
   "source": [
    "s = 'abcde'\n",
    "for char in s:\n",
    "    print(char, end=\" \")                   ### a b c d e\n",
    "\n",
    "print()                                   ### print a newline\n",
    "\n",
    "lyrics = 'we are all just prisoners here of our own device'\n",
    "for word in lyrics:\n",
    "    print(word, end=\" \")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "15e668ea",
   "metadata": {},
   "source": [
    "To turn a string into a list of words, then loop through it:\n",
    "\n",
    "- Using `split` to make a `list` of words\n",
    "- Use `for` to loop through them."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "bf4286c6",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "we are all just prisoners here of our own device\n",
      "['we', 'are', 'all', 'just', 'prisoners', 'here', 'of', 'our', 'own', 'device']\n"
     ]
    }
   ],
   "source": [
    "lyrics = 'we are all just prisoners here of our own device'\n",
    "\n",
    "print(lyrics)            ### string\n",
    "lyrics = lyrics.split()  ### list\n",
    "print(lyrics)            "
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a32336aa",
   "metadata": {},
   "source": [
    "Now we can loop through the word list and use a **conditional statement** to create programs. For example,"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "01a4956d",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "prisoners is a long word!!\n",
      "device is a long word!!\n"
     ]
    }
   ],
   "source": [
    "for word in lyrics:\n",
    "    if len(word) >= 5:\n",
    "        print(f\"{word} is a long word!!\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "388df449",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "device found\n"
     ]
    }
   ],
   "source": [
    "for word in lyrics:\n",
    "    if word == \"device\":\n",
    "        print(\"device found\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "db2b0a80",
   "metadata": {},
   "source": [
    "#### Tuples\n",
    "\n",
    "Tuples are also sequences that can be looped through just like lists. They behave the same way in loops, but tuples are **immutable** (cannot be changed after creation).\n",
    "\n",
    "Two common patterns:\n",
    "\n",
    "- Simple iteration over a single tuple\n",
    "- **Tuple unpacking** when looping over a list of tuples"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "id": "25671829",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "red green blue \n",
      "(1, 2) (3, 4) (5, 6) "
     ]
    }
   ],
   "source": [
    "# Example tuple (single sequence)\n",
    "colors = (\"red\", \"green\", \"blue\")\n",
    "for color in colors:\n",
    "    print(color, end=\" \")        ### red green blue\n",
    "\n",
    "print()\n",
    "\n",
    "# Example list of tuples (for unpacking)\n",
    "coordinates = [(1, 2), (3, 4), (5, 6)]\n",
    "for x, y in coordinates:\n",
    "    print(f\"({x}, {y})\", end=\" \")  ### (1, 2) (3, 4) (5, 6)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "75863e70",
   "metadata": {},
   "source": [
    "#### Dictionaries\n",
    "\n",
    "We can also loop through dictionaries. When looping through a dictionary:\n",
    "- Looping through the dictionary directly gives you the **keys**\n",
    "- To get **values**, use `.values()`\n",
    "- To get **both keys and values**, use `.items()`\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 62,
   "id": "6a069f9e",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "name age major \n",
      "Alice 20 Data Science \n",
      "name: Alice | age: 20 | major: Data Science | "
     ]
    }
   ],
   "source": [
    "# Example dictionary\n",
    "student = {\"name\": \"Alice\", \"age\": 20, \"major\": \"Data Science\"}\n",
    "\n",
    "# Loop through keys (default)\n",
    "for key in student:\n",
    "    print(key, end=\" \")            ### name age major\n",
    "print()\n",
    "\n",
    "# Loop through values\n",
    "for value in student.values():\n",
    "    print(value, end=\" \")          ### Alice 20 Data Science\n",
    "print()\n",
    "\n",
    "# Loop through both keys and values\n",
    "for key, value in student.items():\n",
    "    print(f\"{key}: {value}\", end=\" | \")   ### name: Alice | age: 20 | major: Data Science |"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "347ebde9",
   "metadata": {},
   "source": [
    "### `enumerate`\n",
    "\n",
    "Sometimes you need both the **position** (index) and the **value** of items in a sequence. The `enumerate()` function gives you both: it pairs each element with its index, starting from 0 by default. This is useful when you need to:\n",
    "\n",
    "- Track which position you're at in the loop\n",
    "- Use index-based logic conditionally (e.g., \"do something special for the third item\")\n",
    "- Display results with numbering (e.g., \"1. apple, 2. banana\")\n",
    "- Work with data where position matters (e.g., pandas columns with statistics) "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "e87433f3",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0 apple 1 banana 2 cherry "
     ]
    }
   ],
   "source": [
    "fruits = [\"apple\", \"banana\", \"cherry\"]\n",
    "\n",
    "for idx, fruit in enumerate(fruits):    ### user start= to control the starting index of the enumeration\n",
    "    print(idx, fruit, end=\" \")          ### 0 apple 1 banana 2 cherry"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "id": "6b2fb23f",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "   age  height  weight\n",
      "0   23     165      60\n",
      "1   25     170      65\n",
      "2   31     178      80\n",
      "3   19     160      55 \n",
      "\n",
      "Index(['age', 'height', 'weight'], dtype='object') \n",
      "\n",
      "1. age: mean = 24.5\n",
      "2. height: mean = 168.2\n",
      "3. weight: mean = 65.0\n"
     ]
    }
   ],
   "source": [
    "import pandas as pd\n",
    "\n",
    "# Simple DataFrame\n",
    "df = pd.DataFrame({\n",
    "    \"age\":    [23, 25, 31, 19],\n",
    "    \"height\": [165, 170, 178, 160],\n",
    "    \"weight\": [60, 65, 80, 55]\n",
    "})\n",
    "\n",
    "print(df, \"\\n\")\n",
    "\n",
    "print(df.columns, \"\\n\")  ### Index(['age', 'height', 'weight'], dtype='object')\n",
    "\n",
    "# Use enumerate to see column order and summary stats\n",
    "for idx, col in enumerate(df.columns, start=1):\n",
    "    mean_val = df[col].mean()\n",
    "    print(f\"{idx}. {col}: mean = {mean_val:.1f}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ec88295a",
   "metadata": {},
   "source": [
    "### Nested Loops\n",
    "\n",
    "A nested loop is a loop inside another loop. The inner loop runs fully for each iteration of the outer loop.\n",
    "Use nested loops for tasks like building grids, tables, or pairwise comparisons."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "7c20ad1e",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "A1 A2 A3 \n",
      "B1 B2 B3 \n",
      "C1 C2 C3 \n"
     ]
    }
   ],
   "source": [
    "rows = [\"A\", \"B\", \"C\"]\n",
    "cols = [1, 2, 3]\n",
    "\n",
    "for r in rows:\n",
    "    for c in cols:\n",
    "        print(f\"{r}{c}\", end=\" \")\n",
    "    print()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "db5d74bc",
   "metadata": {},
   "source": [
    "Or, using the `range` function, to print out a multiplication table:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "id": "9a86b9ea",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "2\t 4\t 6\t 8\t 10\t 12\t 14\t 16\t 18\t \n",
      "3\t 6\t 9\t 12\t 15\t 18\t 21\t 24\t 27\t \n",
      "4\t 8\t 12\t 16\t 20\t 24\t 28\t 32\t 36\t \n",
      "5\t 10\t 15\t 20\t 25\t 30\t 35\t 40\t 45\t \n",
      "6\t 12\t 18\t 24\t 30\t 36\t 42\t 48\t 54\t \n",
      "7\t 14\t 21\t 28\t 35\t 42\t 49\t 56\t 63\t \n",
      "8\t 16\t 24\t 32\t 40\t 48\t 56\t 64\t 72\t \n",
      "9\t 18\t 27\t 36\t 45\t 54\t 63\t 72\t 81\t \n"
     ]
    }
   ],
   "source": [
    "for i in range(2, 10):\n",
    "    print(f\"{i}\\t\", end=\" \")\n",
    "    for j in range(2, 10):\n",
    "        print(f\"{i*j}\\t\", end=\" \")\n",
    "    print()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d9c73068",
   "metadata": {},
   "source": [
    "### Loop Control Statements\n",
    "\n",
    "You can control the execution of any loop (`while` or `for`) using the following statements:\n",
    "\n",
    "- **`break`** – Immediately exits the loop, even if the condition is still `True` (for `while`) or there are more items (for `for`).  \n",
    "- **`continue`** – Skips the remainder of the current iteration and returns to the top of the loop to check the condition (for `while`) or move to the next item (for `for`).  \n",
    "- **`pass`** - Used to write empty loops (also used for empty control statements, functions, and classes).\n",
    "- **`else` clause** – Executes only if the loop finishes normally without a `break`, and does **not** run if the loop is terminated by a `break` statement."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "ad005f14",
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "### break statement example\n",
    "\n",
    "i = 1\n",
    "while i < 6:\n",
    "    print(i, end=\" \")\n",
    "    if i == 3:\n",
    "        break\n",
    "    i += 1"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "cb715a5e",
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "### continue statement example\n",
    "\n",
    "i = 0\n",
    "while i < 6:\n",
    "    i += 1\n",
    "    if i == 3:\n",
    "        continue\n",
    "    print(i, end=\" \")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "id": "363ed881",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Value of i : 13\n"
     ]
    }
   ],
   "source": [
    "### pass statement example\n",
    "\n",
    "a = 'geeksforgeeks'\n",
    "i = 0\n",
    "while i < len(a):\n",
    "    i += 1\n",
    "    pass\n",
    "  \n",
    "print('Value of i :', i)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "202c7f9c",
   "metadata": {},
   "source": [
    "`pass` works similarly as `continue` in `while` loop with distinctions:\n",
    "| Feature | `pass` | `continue` |\n",
    "| :--- | :--- | :--- |\n",
    "| **Definition** | A null operation; it literally does nothing. | Skips the remainder of the current loop iteration. |\n",
    "| **Context** | Can be used anywhere (loops, functions, classes, `if` statements). | **Only** allowed inside loops (`for` or `while`). |\n",
    "| **Impact on Flow** | Execution continues to the next statement in the block. | Execution jumps back to the start of the loop for the next cycle. |\n",
    "| **Primary Use** | Syntactic placeholder (prevents \"empty block\" errors). | Logic control (skips specific items based on a condition). |\n",
    "| **Example Scenario** | Creating an empty function for future implementation. | Printing only odd numbers by skipping even ones. |"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 34,
   "id": "44e32ad5",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1 2 3 \n",
      "Loop finished normally!\n",
      "\n",
      "1 2 3 \n",
      "\n",
      "apple banana cherry \n",
      "After all fruits processed!\n"
     ]
    }
   ],
   "source": [
    "### else clause with while loop (no break)\n",
    "count = 1\n",
    "while count < 4:\n",
    "    print(count, end=\" \")\n",
    "    count += 1\n",
    "else:\n",
    "    print(\"\\nLoop finished normally!\")  # This runs because no break occurred\n",
    "\n",
    "print()\n",
    "\n",
    "### else clause with while loop (with break)\n",
    "count = 1\n",
    "while count < 10:\n",
    "    print(count, end=\" \")\n",
    "    if count == 3:\n",
    "        break\n",
    "    count += 1\n",
    "else:\n",
    "    print(\"\\nLoop finished normally!\")  # This does NOT run because break terminated the loop\n",
    "\n",
    "print(\"\\n\")\n",
    "\n",
    "### else clause with for loop (no break)\n",
    "fruits = [\"apple\", \"banana\", \"cherry\"]\n",
    "for fruit in fruits:\n",
    "    print(fruit, end=\" \")\n",
    "else:\n",
    "    print(\"\\nAfter all fruits processed!\")  # This runs because no break occurred"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "ch02-control-for-exercise-q",
   "metadata": {
    "tags": [
     "thebe-interactive"
    ]
   },
   "outputs": [],
   "source": [
    "### Exercise: Summarize Regional Sales\n",
    "# Use a for loop with enumerate to print each region number and sales amount.\n",
    "# Then print the total.\n",
    "# Print exactly:\n",
    "# 1. North: 120\n",
    "# 2. South: 95\n",
    "# 3. West: 140\n",
    "# Total sales: 355\n",
    "regions = [\"North\", \"South\", \"West\"]\n",
    "sales = [120, 95, 140]\n",
    "### Your code starts here.\n",
    "\n",
    "\n",
    "\n",
    "### Your code ends here."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "ch02-control-for-exercise-a",
   "metadata": {
    "tags": [
     "hide-input"
    ]
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1. North: 120\n",
      "2. South: 95\n",
      "3. West: 140\n",
      "Total sales: 355\n"
     ]
    }
   ],
   "source": [
    "### Solution\n",
    "regions = [\"North\", \"South\", \"West\"]\n",
    "sales = [120, 95, 140]\n",
    "\n",
    "total_sales = 0\n",
    "for position, region in enumerate(regions, start=1):\n",
    "    amount = sales[position - 1]\n",
    "    total_sales += amount\n",
    "    print(f\"{position}. {region}: {amount}\")\n",
    "\n",
    "print(\"Total sales:\", total_sales)"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "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.12.13"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
