{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "52fcc1c0-b9c1-4b0b-8b9d-86c3d419df6c",
   "metadata": {},
   "source": [
    "## PDSP 2026, Lecture 04, 20 August 2026"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "fb476c24-9826-4b02-b7a5-5a041cd848d2",
   "metadata": {},
   "outputs": [],
   "source": [
    "import math"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f32582e3-937d-4591-afe2-b5cbebf3333e",
   "metadata": {},
   "source": [
    "### Functions and modularity\n",
    "- Functions modularise code\n",
    "- Each function has an *interface contract* -- if the input $x$ is valid, the output is $f(x)$\n",
    "- Can change the implementation of the function so long as the interface contract is upheld\n",
    "    - Any one of our three implmentations of `isprime` can be used\n",
    "    - For instance, can use a naive implementation as a *prototype* and later replace by a more refined, optimised implementation"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "1789e9e2-1153-4f4f-98b2-609971f411f9",
   "metadata": {},
   "outputs": [],
   "source": [
    "def isprime(n):    # An equivalent defn, without a separate status variable\n",
    "    for i in range(2,n):\n",
    "        if n % i == 0:\n",
    "            return(False)\n",
    "    return(True)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "bf22177a-828b-4bba-92a0-6236c54737ff",
   "metadata": {},
   "outputs": [],
   "source": [
    "def primesupto(n):\n",
    "    primelist = []\n",
    "    for i in range(2,n+1):\n",
    "        if isprime(i):\n",
    "            primelist.append(i)\n",
    "    return(primelist)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "fe7d305f-282e-4771-91b5-66427b5dda8d",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[2, 3, 5, 7, 11, 13, 17, 19, 23, 29]"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "primesupto(30)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "490cf528-7fc7-4b1e-a865-ff208b496546",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67]"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "primesupto(70)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "a8e88816-1e50-498c-8b54-fba1ce94e016",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[2,\n",
       " 3,\n",
       " 5,\n",
       " 7,\n",
       " 11,\n",
       " 13,\n",
       " 17,\n",
       " 19,\n",
       " 23,\n",
       " 29,\n",
       " 31,\n",
       " 37,\n",
       " 41,\n",
       " 43,\n",
       " 47,\n",
       " 53,\n",
       " 59,\n",
       " 61,\n",
       " 67,\n",
       " 71,\n",
       " 73,\n",
       " 79,\n",
       " 83,\n",
       " 89,\n",
       " 97,\n",
       " 101,\n",
       " 103,\n",
       " 107,\n",
       " 109,\n",
       " 113,\n",
       " 127,\n",
       " 131,\n",
       " 137,\n",
       " 139,\n",
       " 149,\n",
       " 151,\n",
       " 157,\n",
       " 163,\n",
       " 167,\n",
       " 173,\n",
       " 179,\n",
       " 181,\n",
       " 191,\n",
       " 193,\n",
       " 197,\n",
       " 199,\n",
       " 211,\n",
       " 223,\n",
       " 227,\n",
       " 229,\n",
       " 233,\n",
       " 239,\n",
       " 241,\n",
       " 251,\n",
       " 257,\n",
       " 263,\n",
       " 269,\n",
       " 271,\n",
       " 277,\n",
       " 281,\n",
       " 283,\n",
       " 293,\n",
       " 307,\n",
       " 311,\n",
       " 313,\n",
       " 317,\n",
       " 331,\n",
       " 337,\n",
       " 347,\n",
       " 349,\n",
       " 353,\n",
       " 359,\n",
       " 367,\n",
       " 373,\n",
       " 379,\n",
       " 383,\n",
       " 389,\n",
       " 397,\n",
       " 401,\n",
       " 409,\n",
       " 419,\n",
       " 421,\n",
       " 431,\n",
       " 433,\n",
       " 439,\n",
       " 443,\n",
       " 449,\n",
       " 457,\n",
       " 461,\n",
       " 463,\n",
       " 467,\n",
       " 479,\n",
       " 487,\n",
       " 491,\n",
       " 499,\n",
       " 503,\n",
       " 509,\n",
       " 521,\n",
       " 523,\n",
       " 541,\n",
       " 547,\n",
       " 557,\n",
       " 563,\n",
       " 569,\n",
       " 571,\n",
       " 577,\n",
       " 587,\n",
       " 593,\n",
       " 599,\n",
       " 601,\n",
       " 607,\n",
       " 613,\n",
       " 617,\n",
       " 619,\n",
       " 631,\n",
       " 641,\n",
       " 643,\n",
       " 647,\n",
       " 653,\n",
       " 659,\n",
       " 661,\n",
       " 673,\n",
       " 677,\n",
       " 683,\n",
       " 691,\n",
       " 701,\n",
       " 709,\n",
       " 719,\n",
       " 727,\n",
       " 733,\n",
       " 739,\n",
       " 743,\n",
       " 751,\n",
       " 757,\n",
       " 761,\n",
       " 769,\n",
       " 773,\n",
       " 787,\n",
       " 797,\n",
       " 809,\n",
       " 811,\n",
       " 821,\n",
       " 823,\n",
       " 827,\n",
       " 829,\n",
       " 839,\n",
       " 853,\n",
       " 857,\n",
       " 859,\n",
       " 863,\n",
       " 877,\n",
       " 881,\n",
       " 883,\n",
       " 887,\n",
       " 907,\n",
       " 911,\n",
       " 919,\n",
       " 929,\n",
       " 937,\n",
       " 941,\n",
       " 947,\n",
       " 953,\n",
       " 967,\n",
       " 971,\n",
       " 977,\n",
       " 983,\n",
       " 991,\n",
       " 997]"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "primesupto(1000)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "317ed237-2d5c-4dc6-928b-568775df2a24",
   "metadata": {},
   "source": [
    "### First $n$ primes\n",
    "What if we want a list of the first $n$ primes?\n",
    "- Generate numbers 2,3,... and check if each one is a prime\n",
    "- Stop when we have generated $n$ primes\n",
    "\n",
    "We don't know the upper bound of the list 2,3,...\n",
    "- Can't use `range()`\n",
    "\n",
    "Instead, a new kind of loop\n",
    "- \"Manually\" generate the sequence\n",
    "- Stop when we reach the terminating condition\n",
    "\n",
    "```\n",
    "while (condition):\n",
    "  statement 1\n",
    "  ...\n",
    "  statement k\n",
    "```\n",
    "\n",
    "- If the `condition` evaluates to `True` the block of k statements is executed\n",
    "- After this, the condition is checked again and the same process is repeated\n",
    "- Compare to `if` where the condition is evaluated once\n",
    "\n",
    "```\n",
    "if (condition):\n",
    "  statement 1\n",
    "  ...\n",
    "  statement k\n",
    "```\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "29f1c291-6b2e-4187-af2f-6b40742d422b",
   "metadata": {},
   "outputs": [],
   "source": [
    "def nprimes(n):\n",
    "    primelist = []\n",
    "    i = 2\n",
    "    while (len(primelist) < n):\n",
    "        if (isprime(i)):\n",
    "            primelist.append(i)\n",
    "        i = i+1\n",
    "    return(primelist)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "06fea4bc-3d2d-4d90-b8a2-4cde7f9c55df",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71]"
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "nprimes(20)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "3e529fee-4c81-463e-bf21-7b0cb0e73439",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[2,\n",
       " 3,\n",
       " 5,\n",
       " 7,\n",
       " 11,\n",
       " 13,\n",
       " 17,\n",
       " 19,\n",
       " 23,\n",
       " 29,\n",
       " 31,\n",
       " 37,\n",
       " 41,\n",
       " 43,\n",
       " 47,\n",
       " 53,\n",
       " 59,\n",
       " 61,\n",
       " 67,\n",
       " 71,\n",
       " 73,\n",
       " 79,\n",
       " 83,\n",
       " 89,\n",
       " 97,\n",
       " 101,\n",
       " 103,\n",
       " 107,\n",
       " 109,\n",
       " 113,\n",
       " 127,\n",
       " 131,\n",
       " 137,\n",
       " 139,\n",
       " 149,\n",
       " 151,\n",
       " 157,\n",
       " 163,\n",
       " 167,\n",
       " 173,\n",
       " 179,\n",
       " 181,\n",
       " 191,\n",
       " 193,\n",
       " 197,\n",
       " 199,\n",
       " 211,\n",
       " 223,\n",
       " 227,\n",
       " 229,\n",
       " 233,\n",
       " 239,\n",
       " 241,\n",
       " 251,\n",
       " 257,\n",
       " 263,\n",
       " 269,\n",
       " 271,\n",
       " 277,\n",
       " 281,\n",
       " 283,\n",
       " 293,\n",
       " 307,\n",
       " 311,\n",
       " 313,\n",
       " 317,\n",
       " 331,\n",
       " 337,\n",
       " 347,\n",
       " 349,\n",
       " 353,\n",
       " 359,\n",
       " 367,\n",
       " 373,\n",
       " 379,\n",
       " 383,\n",
       " 389,\n",
       " 397,\n",
       " 401,\n",
       " 409,\n",
       " 419,\n",
       " 421,\n",
       " 431,\n",
       " 433,\n",
       " 439,\n",
       " 443,\n",
       " 449,\n",
       " 457,\n",
       " 461,\n",
       " 463,\n",
       " 467,\n",
       " 479,\n",
       " 487,\n",
       " 491,\n",
       " 499,\n",
       " 503,\n",
       " 509,\n",
       " 521,\n",
       " 523,\n",
       " 541]"
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "nprimes(100)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "6c5f56cd-273a-4400-a10e-b30ab5bd3e73",
   "metadata": {},
   "source": [
    "### Infinite loops\n",
    "\n",
    "- Need to ensure that the statements make *progress* towards falsifying the condition\n",
    "- If the condition remains `True` forever, the loop never terminates\n",
    "- For instance, suppose there were only finitely many primes, say $M$. For any $n > M$, the length of `primelist` would saturate at $M$ so the condition `len(primelist) < n` would never become `False`"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e5c6e08c-8715-42a7-9715-e3f347359f09",
   "metadata": {},
   "source": [
    "### Looping --- `for` and `while`\n",
    "\n",
    "- `while` is more general than `for`\n",
    "- Can implement\n",
    "  ```\n",
    "\n",
    "  for x in l:\n",
    "    ...\n",
    "\n",
    "\n",
    "  ```\n",
    "  using `while` by explicitly going through `l` from first to last position\n",
    "```\n",
    "pos = 0\n",
    "while (pos < len(l)):\n",
    "  ...\n",
    "  pos = pos + 1\n",
    "```\n",
    "- Note that we have to move the position \"manually\" to ensure that we make progress towards termination\n",
    "- However, using `for` is preferred if it is clearly an iteration over a fixed sequence\n",
    "    - The intent is capture much more clearly\n",
    "    - In the `while` form it is slightly obfuscated"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "6a6023cb-3133-4aab-9f61-b163497bee5b",
   "metadata": {},
   "source": [
    "### Boolean datatypes\n",
    "- Usually an outcome of comparisons: `==`, `!=`, `<`, `<=`, `>`, `>=`\n",
    "- Useful shortcut\n",
    "    - Any \"empty\" value is interpreted as `False`\n",
    "    - So `0`, `[]`, `\"\"` (empty string) are all `False`\n",
    "    - Any other value is interpreted as `True`\n",
    "- Avoid comparisons such as `if x == 0` or `if l != []`\n",
    "    - Write `if not(x)`, `if l` instead"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "0f0a7e2b-29d6-4dfc-b20f-4302f425445c",
   "metadata": {},
   "outputs": [],
   "source": [
    "l = [1,2,3]\n",
    "if l: # if l != []\n",
    "    x = True\n",
    "else:\n",
    "    x = False"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "757e7331-9412-4be9-8f5b-46414f4a2ab4",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "x"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "id": "cd43451f-973b-4aaf-9d17-419c3becd917",
   "metadata": {},
   "outputs": [],
   "source": [
    "m = 0\n",
    "if not(m):\n",
    "    y = True\n",
    "else:\n",
    "    y = False"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "id": "6b057be1-1144-4674-84d3-224a8f04b889",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "execution_count": 13,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "y"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "63f2922d-6e64-46a8-9c1b-d730b3cb6319",
   "metadata": {},
   "source": [
    "- Be careful. You don't always get what you expect!"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "id": "411f5ea6-0438-41aa-9722-6beaac449367",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "7"
      ]
     },
     "execution_count": 14,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "7 or 5"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "52bf74e0-5ea1-4542-937a-31884788fc74",
   "metadata": {},
   "source": [
    "- Note that Python does not insist on brackets around the condition in `if` and `while`\n",
    "    - Can write `if (cond):` or `if cond:`, `while (cond):` or `while cond:`"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "60928e4d-e32d-4135-97f3-e6c8b92ed08a",
   "metadata": {},
   "source": [
    "### Variables, values and types\n",
    "- Variables (names) have no intrinsic types\n",
    "- Values have types\n",
    "    - A variable inherits the type of the value it currently holds\n",
    "- The type of value a variable holds can vary over time\n",
    "    - But not a good idea to use the same name for different types of values in the same piece of code\n",
    "    - Reduces readability, maintainability\n",
    "- The `type()` function returns the type of a variable that is currently assigned a value"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "id": "52367c6d-832d-4457-89d1-4322e363d878",
   "metadata": {},
   "outputs": [],
   "source": [
    "x = True"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "id": "69ec90e7-4bcf-408c-9e3f-bfa5cfffd0e2",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "bool"
      ]
     },
     "execution_count": 16,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "type(x)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "id": "d53ebb50-f105-4920-b5d9-04214f24c69e",
   "metadata": {},
   "outputs": [],
   "source": [
    "x = 5"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "id": "70ca1fa5-4a0f-4772-82de-2e21d808337c",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "int"
      ]
     },
     "execution_count": 18,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "type(x)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a38bb0d5-017e-4cce-a7fe-75da82a15f61",
   "metadata": {},
   "source": [
    "- The function `del()` unassigns a value from a name"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "id": "a26c969e-016b-47ef-9b1d-83c57f3b3dbc",
   "metadata": {},
   "outputs": [],
   "source": [
    "del(x)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "id": "f7593366-d9c8-4abd-bc34-d4779b4ee062",
   "metadata": {},
   "outputs": [
    {
     "ename": "NameError",
     "evalue": "name 'x' is not defined",
     "output_type": "error",
     "traceback": [
      "\u001b[31m---------------------------------------------------------------------------\u001b[39m",
      "\u001b[31mNameError\u001b[39m                                 Traceback (most recent call last)",
      "\u001b[36mCell\u001b[39m\u001b[36m \u001b[39m\u001b[32mIn[20]\u001b[39m\u001b[32m, line 1\u001b[39m\n\u001b[32m----> \u001b[39m\u001b[32m1\u001b[39m type(x)\n",
      "\u001b[31mNameError\u001b[39m: name 'x' is not defined"
     ]
    }
   ],
   "source": [
    "type(x)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "79fe9ec3-2cd3-4d6b-b757-138dc4960978",
   "metadata": {},
   "source": [
    "### Conditional statement\n",
    "`if` allows conditional execution\n",
    "\n",
    "```\n",
    "if condition:\n",
    "    statement 1\n",
    "    ...\n",
    "    statement k\n",
    "else:\n",
    "    statement 1'\n",
    "    ...\n",
    "    statement k'\n",
    "```\n",
    "- If `condition` evaluates to `True`, the first block is executed, otherwise the second block.\n",
    "- The `else:` block is optional. If there is no `else:` block and the `condition` evaluates to `False`, execution skips over to the next statement after the `if`"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f046bee2-92fe-4e2e-8deb-3248e86ed371",
   "metadata": {},
   "source": [
    "- Example: Compute the absolute value of a number"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "id": "24f50487-f9c8-4bf9-919b-c887a3d31462",
   "metadata": {},
   "outputs": [],
   "source": [
    "def myabs(x):  # myabs to avoid any confusion with built-in abs()\n",
    "    if x < 0:\n",
    "        return(-x)\n",
    "    else:\n",
    "        return(x)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "id": "e187eacf-c2bf-47c4-921b-032c2bba7533",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(9, 7)"
      ]
     },
     "execution_count": 22,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "myabs(-9), myabs(7)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "596eb09e-0a05-4581-9bc4-a231a220f17d",
   "metadata": {},
   "source": [
    "### Multiway branching --- `elif`\n",
    "\n",
    "Suppose we want to compute $sign(x) = \\begin{cases}\n",
    "                                x < 0 & = & -1,\\\\\n",
    "                                x = 0 & = & 0,\\\\\n",
    "                                x > 0 & = & 1\n",
    "\\end{cases}$"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "677afd4c-c594-4d94-b3d6-a3a6747ad95a",
   "metadata": {},
   "source": [
    "In Python, we would have to nest `if` statements like this:\n",
    "```\n",
    "if x < 0:\n",
    "    return(-1)\n",
    "else:\n",
    "    if x == 0:\n",
    "        return(0):\n",
    "    else:\n",
    "        return(1)\n",
    "```\n",
    "- As we see, the indentation of the nested `if` pushes the code to the right\n",
    "- With more cases, this would become worse\n",
    "- Python provides `elif` to avoid this cascaded nesting\n",
    "\n",
    "```\n",
    "if x < 0:\n",
    "    return(-1)\n",
    "elif x == 0:\n",
    "    return(0):\n",
    "else:\n",
    "    return(1)\n",
    "```\n",
    "- Can have as many `elif` blocks as you need\n",
    "- `else` is still optional"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "id": "253f2c14-2cfe-4feb-8cb6-2dc9ac66d2ff",
   "metadata": {},
   "outputs": [],
   "source": [
    "def sign(x):\n",
    "    if x < 0:\n",
    "        return(-1)\n",
    "    elif x == 0:\n",
    "        return(0)\n",
    "    else:\n",
    "        return(1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "id": "d84b5a77-d385-40b1-87c9-80d3efdfa5b7",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "-1"
      ]
     },
     "execution_count": 24,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "sign(-7)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "id": "8d6fe007-1c7a-4353-8c38-2af16cad8a80",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "1"
      ]
     },
     "execution_count": 25,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "sign(8)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "id": "bfc807fa-f603-48fa-9857-a09be9f52ab3",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "0"
      ]
     },
     "execution_count": 26,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "sign(0)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "4aa3ced2-2f5e-4435-b9fb-5ecc8e80ace6",
   "metadata": {},
   "source": [
    "### Lists\n",
    "- Sequences of values, indexed by position\n",
    "- For a list with `n` values, valid positions are `0` to `n-1`\n",
    "    - `len(l)` gives the length of a list\n",
    "- Accessing a position beyond `len(l)-1` results in `IndexError`"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "id": "bafaf95d-a547-4a85-9204-f5b887886d65",
   "metadata": {},
   "outputs": [],
   "source": [
    "l = list(range(20,40))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "id": "5512bba4-f07f-4e78-9162-26251cf9d284",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(20, 23, 39)"
      ]
     },
     "execution_count": 28,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "len(l), l[3], l[19]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "id": "354250d2-89e2-41d3-974e-a006b9e87367",
   "metadata": {},
   "outputs": [
    {
     "ename": "IndexError",
     "evalue": "list index out of range",
     "output_type": "error",
     "traceback": [
      "\u001b[31m---------------------------------------------------------------------------\u001b[39m",
      "\u001b[31mIndexError\u001b[39m                                Traceback (most recent call last)",
      "\u001b[36mCell\u001b[39m\u001b[36m \u001b[39m\u001b[32mIn[29]\u001b[39m\u001b[32m, line 1\u001b[39m\n\u001b[32m----> \u001b[39m\u001b[32m1\u001b[39m l[\u001b[32m20\u001b[39m]\n",
      "\u001b[31mIndexError\u001b[39m: list index out of range"
     ]
    }
   ],
   "source": [
    "l[20]"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "2bdb0f59-f594-43f9-af16-4cb925aef827",
   "metadata": {},
   "source": [
    "- What about indices below `0`?\n",
    "- Index `-j` is interpreted as `len(l)-j`\n",
    "    - Useful for accessing values from the end of the list\n",
    "    - Valid indices in reverse are `-1`, `-2`, ..., `-len(l)`"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "id": "6838faf7-f93d-4603-8330-02f6520592b1",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(39, 20)"
      ]
     },
     "execution_count": 30,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "l[-1], l[-20]"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "8dbe1201-3d56-4abf-889d-319c5ffed710",
   "metadata": {},
   "source": [
    "### Slices\n",
    "- Recall that `nprimes(n)` computed the first `n` primes"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "id": "3e52482b-01df-4949-b560-8fe712ae0bf7",
   "metadata": {},
   "outputs": [],
   "source": [
    "def isprime(n):\n",
    "    for j in range(2,n):\n",
    "        if n % j == 0:\n",
    "            return(False)\n",
    "    return(True)\n",
    "\n",
    "def nprimes(n):\n",
    "    plist = []\n",
    "    j = 2\n",
    "    while (len(plist) < n):\n",
    "        if isprime(j):\n",
    "            plist.append(j)\n",
    "        j = j+1\n",
    "    return(plist)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 32,
   "id": "300baf8c-548a-4c5b-910d-8d5195ff2c13",
   "metadata": {},
   "outputs": [],
   "source": [
    "first20primes = nprimes(20)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 33,
   "id": "09827cba-4c1f-4341-8957-6b9534ebf99e",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71]"
      ]
     },
     "execution_count": 33,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "first20primes"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "0458775d-1b7e-40b5-a7b8-43d301a0a1fc",
   "metadata": {},
   "source": [
    "- What are the primes from 11 to 15?\n",
    "- Need a sublist of the original list\n",
    "- `l[i:j]` is the list `[l[i], l[i+1], ..., l[j-1]]`\n",
    "- Similar to\n",
    "  ```\n",
    "  newl = []\n",
    "  for k in range(i,j):\n",
    "     newl.append(k)\n",
    "  ```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 34,
   "id": "cfec7a4f-12d0-4649-af9c-e1da6fd3c835",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[37, 41, 43, 47, 53]"
      ]
     },
     "execution_count": 34,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "first20primes[11:16]"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ae97a899-5c3f-4688-a626-3e4b03b0e69d",
   "metadata": {},
   "source": [
    "- like `range()` if the indices don't make sense, you get an empty list"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 35,
   "id": "481ebf33-abd9-4553-9a6f-72c89666b16b",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[]"
      ]
     },
     "execution_count": 35,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "first20primes[11:10]"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "717be12f-1cc5-467c-a6dd-5c1e6fcbf616",
   "metadata": {},
   "source": [
    "- Unlike accessing `l[i]`, can give upper bound beyond the list\n",
    "- `l[i:len(l)+10]` is interpreted as `l[i:len(l)]`"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 36,
   "id": "d659a3ce-0a6c-4712-8fe2-9600ccaea5f9",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[37, 41, 43, 47, 53, 59, 61, 67, 71]"
      ]
     },
     "execution_count": 36,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "first20primes[11:40]"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e4e9080f-3e3a-49ca-87a4-8a4139cd6077",
   "metadata": {},
   "source": [
    "- Can omit the upper bound, defaults to `len(l)`"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 37,
   "id": "3719ebac-0f22-4017-932e-9c7cbfe80b98",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[53, 59, 61, 67, 71]"
      ]
     },
     "execution_count": 37,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "first20primes[15:]"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d8785f2f-59f6-44db-a5fb-ccc257aa88b8",
   "metadata": {},
   "source": [
    "- Likewise, omit the lower bound, defaults to `0`"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 38,
   "id": "045ab934-6f7b-4446-a1f2-28807c43804a",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[2, 3, 5, 7, 11, 13, 17, 19, 23, 29]"
      ]
     },
     "execution_count": 38,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "first20primes[:10]"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "744a56eb-fde4-41bb-afcf-f7dae5828ee1",
   "metadata": {},
   "source": [
    "- Omit both lower and upper bound to get a `full slice`\n",
    "    - Full slice returns a new list that is a copy of the list\n",
    "    - Significance will become clearer later"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 39,
   "id": "a4faa69f-8d87-4964-8796-807150cb88fa",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71]"
      ]
     },
     "execution_count": 39,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "first20primes[:]"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "0aa73a52-4791-4782-9208-77cd277207d9",
   "metadata": {},
   "source": [
    "### More about `range()`\n",
    "- `range(i,j)` generates the sequence `i,i+1,...,j-1`\n",
    "- `range(n)` generates the sequence `0,1,...,n-1` -- implicitly starts with `0`\n",
    "- What if we want to skip over some numbers\n",
    "    - All even numbers from `4` to `40`\n",
    "- Optional third argument is the step size\n",
    "    - `range(i,j,k)` is `i,i+k,...,i+mk` for the largest `m` such that `i+mk < j` and `i+(m+1)k >= j`"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 40,
   "id": "f2ab16e0-7a31-438c-9f7f-b3b1c46906ac",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40]"
      ]
     },
     "execution_count": 40,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "list(range(4,41,2)) # Even numbers from 4 to 40"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 41,
   "id": "ce51aa70-ee82-4392-8c3f-c1228249ec75",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38]"
      ]
     },
     "execution_count": 41,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "list(range(4,40,2)) # Even numbers from 4 to 38"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "8b65dd7d-da94-45c5-ab25-310317ad1090",
   "metadata": {},
   "source": [
    "- Can also count down -- give a negative step!"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 42,
   "id": "ca8d8dab-3f16-408f-ae73-484f4de52a0c",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[10, 9, 8, 7, 6, 5, 4, 3, 2, 1]"
      ]
     },
     "execution_count": 42,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "list(range(10,0,-1))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 43,
   "id": "6ce9997a-cdd7-4d6c-81f2-5968ef329db8",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[10, 8, 6, 4, 2, 0]"
      ]
     },
     "execution_count": 43,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "list(range(10,-1,-2))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ccbdb6e5-3de4-411f-9645-b60aaee3bc17",
   "metadata": {},
   "source": [
    "- `range(i,j,k)` generate `i, i+k,...` so that the sequence does not *cross* `j`\n",
    "- Depending on whether it is increasing or decreasing, the last value will be less than `j` or greater than `j`"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "fa7f15c3-a6ff-44c5-82c0-3c90aca306f9",
   "metadata": {},
   "source": [
    "### Stepped slices\n",
    "- Can similarly give a third argument in a slice"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 44,
   "id": "5267700f-c7a2-445f-bfb7-53b3793e7ad5",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[5, 13, 23, 37, 47, 61]"
      ]
     },
     "execution_count": 44,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "first20primes[2:20:3]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 45,
   "id": "82ba70be-8956-4614-964a-c4666a6cbd85",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[71, 67, 61, 59, 53, 47, 43, 41, 37, 31, 29, 23, 19, 17, 13, 11, 7, 5, 3]"
      ]
     },
     "execution_count": 45,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "first20primes[19:0:-1]"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "128a21d6-92bf-4d07-8e12-e5cd8294a20e",
   "metadata": {},
   "source": [
    "- Explain the following output. (Hint, what is `l[-1]`?)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 46,
   "id": "1a1319aa-d681-4355-aa21-47bc33aa8132",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[]"
      ]
     },
     "execution_count": 46,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "first20primes[19:-1:-1]"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d3397778-f929-4143-ad87-35a6cd65c7dd",
   "metadata": {},
   "source": [
    "- Can omit upper and lower bounds but give a step\n",
    "- `l[::-1]` is the entire list in reverse\n",
    "    - Note that the default lower and upper bound are determined by the step"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 47,
   "id": "b28ca6d6-e8a7-489d-8e57-b411900bdbf3",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[71, 67, 61, 59, 53, 47, 43, 41, 37, 31, 29, 23, 19, 17, 13, 11, 7, 5, 3, 2]"
      ]
     },
     "execution_count": 47,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "first20primes[::-1]"
   ]
  }
 ],
 "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.13.5"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
