{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "52fcc1c0-b9c1-4b0b-8b9d-86c3d419df6c",
   "metadata": {},
   "source": [
    "## PDSP 2026, Lecture 03, 18 August 2026"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "63ccc526-e5a9-40f0-81c0-2c9b6c17c60f",
   "metadata": {},
   "source": [
    "### Generating sequences of numbers\n",
    "- `range(n)` generates the sequence `0, 1, 2, ..., n-1`\n",
    "- Use `list(range(n))` to display as a list"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "28b40d9c-b7bc-428d-9561-bd7918e2e259",
   "metadata": {},
   "outputs": [],
   "source": [
    "n = 17"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "9f2ac435-ef82-44a3-b2e4-15e1252137e0",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "17"
      ]
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "c1ec5ec0-7e4f-4418-b2de-1c34f6a0a98b",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "range(0, 17)"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "range(n)  # Like a list, but not quite"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "e6c324b5-e306-4735-ade0-4b262f969e24",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "list(range(n))  # Make it into a list"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "7f4235fd-cfcf-447d-96b2-13cb8175628d",
   "metadata": {},
   "source": [
    "- `range(n)` translates to `range(0,n)`, implicitly starting with `0`\n",
    "- Can add an explicit starting point: `range(i,n)` generates `i,i+1,...,n-1`"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "e1eb5b0d-2f91-43a9-95fb-b4418792e862",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "list(range(2,n))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "558267fe-5c21-4096-816a-129d85c9d85c",
   "metadata": {},
   "source": [
    "- If the starting point is $\\ge$ the target, `range` generates an empty sequence"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "88485a73-9765-4583-886b-48eb903d5e61",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[]"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "list(range(3,3))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "ebfc28cc-27d8-4ab6-96f8-714b6cc68451",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[]"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "list(range(7,4))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "765db988-1dad-4d92-b519-6e2c3a8c2cb3",
   "metadata": {},
   "source": [
    "### Numbers in Python\n",
    "- Numbers in Python can be integers (`int`) or reals -- actually rationals -- (`float`)\n",
    "- Internal representation is different, but arithmetic operation symbols are *overloaded* to apply to both types of numbers\n",
    "- `+`, `-`, `*` stand for addition, subtraction, multiplication, as usual\n",
    "- `/` is division, and always produces a `float`"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "e63441a0-f1fb-48ff-8b91-eb1e9a8a5dcb",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "2.0"
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "8/4"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "5b91203c-9283-4f9a-a60d-501de019ca16",
   "metadata": {},
   "source": [
    "- There are separate operators for *quotient* (`//`) and *remainder* (`%`)\n",
    "    - These can also be applied to `float` arguments, but the answer is also  `float`"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "3e1a2522-5741-42ac-987e-4f5c7b74a364",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "2"
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "8//4"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "78ed0d67-4ac8-4833-b0f2-64a3cb275cae",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "1"
      ]
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "7//4"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "f96040af-788b-4e7a-adc2-a806fbfbb33b",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "3"
      ]
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "7 % 4"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "id": "f63afc3c-531c-4299-b193-34bc1d4b966e",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(2.0, 3.0)"
      ]
     },
     "execution_count": 12,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "8.0//3.0, 8.0 % 5.0"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "id": "17a38c5a-fe3d-481c-8b14-0e983fc574f4",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(3.0, 0.15000000000000124)"
      ]
     },
     "execution_count": 13,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "9.3//3.05, 9.3 % 3.05"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f82b2e70-0861-45ee-a57b-7f0e7710061e",
   "metadata": {},
   "source": [
    "### Data types\n",
    "- A data type is a set of values with associated operations\n",
    "- Python has two numeric data types, `int` and `float`\n",
    "- In the FIFA example, we saw text data, which is of type `String` -- we shall examine this later\n",
    "- The boolean data type has two values `True` and `False`"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b75a9524-eb80-471c-8288-938d8ca39630",
   "metadata": {},
   "source": [
    "- Be careful when working with `float`\n",
    "- Decimal $\\to$ binary $\\to$ decimal can create strange \"inaccuracies\", like `9.3 % 3.05` below"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "id": "5cd34933-3f69-4e43-aba6-592a49802ec3",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(3.0, 0.15000000000000124)"
      ]
     },
     "execution_count": 14,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "9.3//3.05, 9.3 % 3.05"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "8e31db2b-2f1f-407c-89c5-8cf0d1628db5",
   "metadata": {},
   "source": [
    "### Checking if a number is prime\n",
    "- Checking if `n` is a prime: assume it is, and flag that is not if we find a factor between `2` and `n-1`"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "id": "53c19aff-13f6-4815-9fb6-850bf78196c5",
   "metadata": {},
   "outputs": [],
   "source": [
    "n = 17\n",
    "isprime = True\n",
    "for i in range(2,n):\n",
    "    if n % i == 0:\n",
    "        isprime = False"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "id": "5f60087c-1b58-4684-b766-1c1d15443760",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(17, True)"
      ]
     },
     "execution_count": 16,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "n, isprime"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "id": "34dc01de-fa9d-40e5-984c-7910723cebd4",
   "metadata": {},
   "outputs": [],
   "source": [
    "n = 18\n",
    "isprime = True\n",
    "for i in range(2,n):\n",
    "    if n % i == 0:\n",
    "        isprime = False"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "id": "64951be9-b394-46f7-8cf0-971ae91873f5",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(18, False)"
      ]
     },
     "execution_count": 18,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "n, isprime"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "27ca1643-04dc-4095-9874-9d2e15590799",
   "metadata": {},
   "source": [
    "### Optimising the search for factors\n",
    "- Factors occur in pairs, sufficient to check from $2$ to $\\sqrt{n}$\n",
    "- Python has a function `sqrt` to compute square roots\n",
    "- However it is not automatically available"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "id": "c0186a4a-3222-4efa-aae0-ee27aa05653a",
   "metadata": {},
   "outputs": [
    {
     "ename": "NameError",
     "evalue": "name 'sqrt' 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[19]\u001b[39m\u001b[32m, line 1\u001b[39m\n\u001b[32m----> \u001b[39m\u001b[32m1\u001b[39m sqrt(n)\n",
      "\u001b[31mNameError\u001b[39m: name 'sqrt' is not defined"
     ]
    }
   ],
   "source": [
    "sqrt(n)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "2d200330-4af5-4fe1-b9d2-92f8f64ecc1e",
   "metadata": {},
   "source": [
    "### Libraries\n",
    "- Libraries are collections of code implementing different groups of functions relevant to a given theme\n",
    "- We will later see libraries specific to data science, machine learning\n",
    "- The `math` library has mathematical functions like `sqrt`, `log`, `sin`, `cos` etc\n",
    "- We `import` the `math` library to use it\n",
    "    - Note that we use `math.sqrt` to tell Python the full context of the function `sqrt`\n",
    "    - This is useful in case two different libraries have different functions with the same name"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "id": "fb476c24-9826-4b02-b7a5-5a041cd848d2",
   "metadata": {},
   "outputs": [],
   "source": [
    "import math"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "id": "75a572c6-0cd5-4845-b094-0807623574af",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "4.123105625617661"
      ]
     },
     "execution_count": 21,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "n = 17\n",
    "math.sqrt(n)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "59074a8d-7148-4f67-996c-fee9a6e03010",
   "metadata": {},
   "source": [
    "### Optimised primality checking\n",
    "- We can optimize our search for factors by restricting the range to `(2,math.sqrt(n))`\n",
    "- `range` expects only `int` arguments, so use `int()` to convert `math.sqrt(n)` to an `int` -- truncates the fractional part"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "id": "d15308bf-556a-4dfc-a248-6ef85539dbdd",
   "metadata": {},
   "outputs": [
    {
     "ename": "TypeError",
     "evalue": "'float' object cannot be interpreted as an integer",
     "output_type": "error",
     "traceback": [
      "\u001b[31m---------------------------------------------------------------------------\u001b[39m",
      "\u001b[31mTypeError\u001b[39m                                 Traceback (most recent call last)",
      "\u001b[36mCell\u001b[39m\u001b[36m \u001b[39m\u001b[32mIn[22]\u001b[39m\u001b[32m, line 3\u001b[39m\n\u001b[32m      1\u001b[39m n = \u001b[32m17\u001b[39m\n\u001b[32m      2\u001b[39m isprime = \u001b[38;5;28;01mTrue\u001b[39;00m\n\u001b[32m----> \u001b[39m\u001b[32m3\u001b[39m \u001b[38;5;28;01mfor\u001b[39;00m i \u001b[38;5;28;01min\u001b[39;00m range(\u001b[32m2\u001b[39m,math.sqrt(n)):\n\u001b[32m      4\u001b[39m     \u001b[38;5;28;01mif\u001b[39;00m n % i == \u001b[32m0\u001b[39m:\n\u001b[32m      5\u001b[39m         isprime = \u001b[38;5;28;01mFalse\u001b[39;00m\n",
      "\u001b[31mTypeError\u001b[39m: 'float' object cannot be interpreted as an integer"
     ]
    }
   ],
   "source": [
    "n = 17\n",
    "isprime = True\n",
    "for i in range(2,math.sqrt(n)): \n",
    "    if n % i == 0:\n",
    "        isprime = False"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "id": "43e8e587-56b0-4ca1-8811-add29d932fea",
   "metadata": {},
   "outputs": [],
   "source": [
    "n = 17\n",
    "isprime = True\n",
    "for i in range(2,int(math.sqrt(n))):  # int(...) truncates a float to an int\n",
    "    if n % i == 0:\n",
    "        isprime = False"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "id": "ee24fe90-08fb-4a21-b9c1-e428623017cc",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "execution_count": 24,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "isprime"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "id": "cac44a6a-5029-41b5-9d80-be768192f4ed",
   "metadata": {},
   "outputs": [],
   "source": [
    "n = 25\n",
    "isprime = True\n",
    "for i in range(2,int(math.sqrt(n))):  # int(...) truncates a float to an int\n",
    "    if n % i == 0:\n",
    "        isprime = False"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "id": "88d2edfd-5dbd-4a22-938a-ad2a13587fb6",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "execution_count": 26,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "isprime"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "27166fee-742e-471d-a5ee-3444f696903e",
   "metadata": {},
   "source": [
    "- We have to be careful, because `range(j,m)` stops at `m-1`\n",
    "- The code above wrongly claims `25` is a prime -- the search for factors runs from `2` to `4` rather than `2` to `5`\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "8f3fe955-0793-4796-947f-8d617f7a73d3",
   "metadata": {},
   "source": [
    "- To fix this, modify the upper bound of `range` to `sqrt(n)+1`"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "id": "6554115f-174c-4f14-a7de-f54585d9591c",
   "metadata": {},
   "outputs": [],
   "source": [
    "n = 25\n",
    "isprime = True\n",
    "for i in range(2,int(math.sqrt(n))+1):  # int(...) truncates a float to an int\n",
    "    if n % i == 0:\n",
    "        isprime = False"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "id": "f2fa791c-a4eb-4a93-a561-a094a8d2d748",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "False"
      ]
     },
     "execution_count": 28,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "isprime"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "017694d3-c414-4729-86f8-8575df3c24c3",
   "metadata": {},
   "source": [
    "### Large and small numbers\n",
    "- Python allows us to work with very large (and very small numbers)\n",
    "- The operator `**` is exponentiation"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "id": "f5145544-44de-496b-b9ed-71a3fc843cf5",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(343, 4096)"
      ]
     },
     "execution_count": 29,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "7**3, 2**12"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b93bc50e-08b8-4983-b74a-04dedfeb3214",
   "metadata": {},
   "source": [
    "- What is $2^{2^{12}}$, in other words, $2^{4096}$?"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "id": "23fba15d-fa6a-4562-8c90-62909ed21dbf",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "1044388881413152506691752710716624382579964249047383780384233483283953907971557456848826811934997558340890106714439262837987573438185793607263236087851365277945956976543709998340361590134383718314428070011855946226376318839397712745672334684344586617496807908705803704071284048740118609114467977783598029006686938976881787785946905630190260940599579453432823469303026696443059025015972399867714215541693835559885291486318237914434496734087811872639496475100189041349008417061675093668333850551032972088269550769983616369411933015213796825837188091833656751221318492846368125550225998300412344784862595674492194617023806505913245610825731835380087608622102834270197698202313169017678006675195485079921636419370285375124784014907159135459982790513399611551794271106831134090584272884279791554849782954323534517065223269061394905987693002122963395687782878948440616007412945674919823050571642377154816321380631045902916136926708342856440730447899971901781465763473223850267253059899795996090799469201774624817718449867455659250178329070473119433165550807568221846571746373296884912819520317457002440926616910874148385078411929804522981857338977648103126085903001302413467189726673216491511131602920781738033436090243804708340403154190336"
      ]
     },
     "execution_count": 30,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "2**(2**12)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "id": "3e3cce40-456c-41a3-9dae-4763d6b0a0c6",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "16777216"
      ]
     },
     "execution_count": 31,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "2**24"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 32,
   "id": "6c88573f-8de8-4ba5-a2b1-35ba562604ef",
   "metadata": {},
   "outputs": [
    {
     "ename": "ValueError",
     "evalue": "Exceeds the limit (4300 digits) for integer string conversion; use sys.set_int_max_str_digits() to increase the limit",
     "output_type": "error",
     "traceback": [
      "\u001b[31m---------------------------------------------------------------------------\u001b[39m",
      "\u001b[31mValueError\u001b[39m                                Traceback (most recent call last)",
      "\u001b[31mValueError\u001b[39m: Exceeds the limit (4300 digits) for integer string conversion; use sys.set_int_max_str_digits() to increase the limit"
     ]
    }
   ],
   "source": [
    "2**(2**24)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "63d72e16-5ffd-4904-9840-c37bf7d9508d",
   "metadata": {},
   "source": [
    "- How about $2^{-4096}$?"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 33,
   "id": "ba79c8dc-fb95-42e7-80c9-4cca2e1716c1",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "0.0"
      ]
     },
     "execution_count": 33,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "2**(-(2**12))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 34,
   "id": "cf782cdc-a20f-4f48-b51d-921b7b67cc1d",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "5.562684646268003e-309"
      ]
     },
     "execution_count": 34,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "2**(-(2**10))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e2acb00f-e770-4bf4-b026-d1302683d227",
   "metadata": {},
   "source": [
    "### Computing primes upto `n`\n",
    "- Instead of checking if `n` is a prime, find all primes upto (and including) `n`\n",
    "- Generate the sequence `2,3,...,n`\n",
    "- For each element in this sequence, check if it is a prime\n",
    "- Accumulate all primes found in a list\n",
    "    - Recall that `l1 + l2` concatenates two lists into a single list\n",
    "- Two *nested* loops, use different variables `j` and `i` to iterate"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 35,
   "id": "c93daab0-2e2c-47f5-af4d-e8526e1fa225",
   "metadata": {},
   "outputs": [],
   "source": [
    "n = 50\n",
    "primelist = []\n",
    "for j in range(2,n+1):\n",
    "    isprime = True\n",
    "    for i in range(2,j): # If we had started with 1, we would have a problem here!\n",
    "        if j % i == 0:\n",
    "            isprime = False\n",
    "    if isprime:\n",
    "        primelist = primelist + [j]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 36,
   "id": "7d4b2b1d-2a34-48ea-bc82-ab35456b5751",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47]"
      ]
     },
     "execution_count": 36,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "primelist"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "fcc4d665-d729-4448-ba9f-209413e796bd",
   "metadata": {},
   "source": [
    "### Appending a value to a list\n",
    "- Can also use `l.append(v)` to add an element `v` to a list\n",
    "- Note the distinction between `l + [v]` and `l.append(v)`\n",
    "    - In the first case, we have to make `v` into a singleton list `[v]` to use the operator `+`"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 37,
   "id": "6c1e23d4-1b24-4075-8adb-049868e520d0",
   "metadata": {},
   "outputs": [],
   "source": [
    "n = 100\n",
    "primelist = []\n",
    "for j in range(2,n+1):\n",
    "    isprime = True\n",
    "    for i in range(2,j):\n",
    "        if j % i == 0:\n",
    "            isprime = False\n",
    "    if isprime:\n",
    "        primelist.append(j)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 38,
   "id": "f3abc63c-37cb-4498-8f4d-a16c25d886dc",
   "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]"
      ]
     },
     "execution_count": 38,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "primelist"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "bc941c55-3bb1-4f90-9d6e-4da788778c2e",
   "metadata": {},
   "source": [
    "### Functions\n",
    "- Modularise code into functional units\n",
    "- Instead of embedding code to check if `j` is a prime, call a function that returns `True` if `j` is a prime and `False` otherwise\n",
    "- Function definition starts with `def function_name (argument1, argument2, ...):`\n",
    "- When the function completes, it should report an answer -- return a value through `return(v)`"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 39,
   "id": "53d0e488-9f40-4d9a-a27e-8772667ff80a",
   "metadata": {},
   "outputs": [],
   "source": [
    "def isprime(n):\n",
    "    status = True\n",
    "    for i in range(2,n):\n",
    "        if n % i == 0:\n",
    "            status = False\n",
    "    return(status)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 40,
   "id": "b4ae93dc-eff9-4735-8ef7-712fdf2313a5",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(True, False)"
      ]
     },
     "execution_count": 40,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "isprime(17), isprime(25)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "7453d99c-8e4f-4f08-a9c3-095393014e94",
   "metadata": {},
   "source": [
    "### Exiting a function in between\n",
    "- If we find a factor, we can declare the number to not be a prime without testing more factors\n",
    "- In the original implementation, we needed to exit the loop\n",
    "- `return()` automatically exits, so we can use this optimisation in the function"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 41,
   "id": "cda3b471-d7a4-4710-9dcf-ca5ab3f3bd2e",
   "metadata": {},
   "outputs": [],
   "source": [
    "def isprime2(n): # An equivalent defn, terminates with False at first factor\n",
    "    status = True\n",
    "    for i in range(2,n):\n",
    "        if n % i == 0:\n",
    "            status = False\n",
    "            return(status)\n",
    "    return(status)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 42,
   "id": "42456fdd-0ff7-411c-b979-0576f1b22455",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(True, False)"
      ]
     },
     "execution_count": 42,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "isprime2(47), isprime2(44)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "fe7ec67c-ccfb-4bab-ae03-22568ea08452",
   "metadata": {},
   "source": [
    "- In fact, we don't even need the variable `status`\n",
    "- If we find a factor, `return(False)`\n",
    "- If the search for a factor ends without finding one, `return(True)`"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 43,
   "id": "1789e9e2-1153-4f4f-98b2-609971f411f9",
   "metadata": {},
   "outputs": [],
   "source": [
    "def isprime3(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": 44,
   "id": "85bfd5c6-5e59-4813-a52b-035018dce2a2",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(True, False)"
      ]
     },
     "execution_count": 44,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "isprime3(571), isprime3(573)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e9afff69-2753-4f0b-b213-5980ba090478",
   "metadata": {},
   "source": [
    "### Using functions\n",
    "- We can rewrite our code to search for primes upto `n` to call the function `isprime` for each candidate\n",
    "    - Recall that in our earlier, explicit, code, we had to rename the outer loop variable as `j` to avoid a clash with the loop through potential factors\n",
    "    - If we use a function, the `i` inside the function is different from the `i` outside the function"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 45,
   "id": "983d652d-024c-4725-a0cf-2bdf403e6ec9",
   "metadata": {},
   "outputs": [],
   "source": [
    "n = 100\n",
    "primelist = []\n",
    "for i in range(2,n+1):\n",
    "    if isprime(i):\n",
    "        primelist.append(i)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 46,
   "id": "2bf29cd9-9551-4a20-a123-52537528c43f",
   "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]"
      ]
     },
     "execution_count": 46,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "primelist"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "bf4775ec-3de2-4c84-b485-63d477ff36db",
   "metadata": {},
   "source": [
    "- We can convert this search for primes upto `n` into another function"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 47,
   "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": 48,
   "id": "fe7d305f-282e-4771-91b5-66427b5dda8d",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[2, 3, 5, 7, 11, 13, 17, 19, 23, 29]"
      ]
     },
     "execution_count": 48,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "primesupto(30)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 49,
   "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": 49,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "primesupto(70)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 50,
   "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": 50,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "primesupto(1000)"
   ]
  },
  {
   "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"
   ]
  }
 ],
 "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
}
