{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "5841d5c6-8ade-4e90-9134-a56f0b1faace",
   "metadata": {},
   "source": [
    "## Lecture 15, 25 September 2025"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e7ae0e73-8848-44e1-846e-7281f728eee9",
   "metadata": {},
   "source": [
    "### Class `Point` using $(x,y)$ coordinates"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "635b033d-f33e-40f5-96ff-fa038b8d565d",
   "metadata": {},
   "outputs": [],
   "source": [
    "class Point:\n",
    "  def __init__(self,a=0,b=0):\n",
    "    self.x = a\n",
    "    self.y = b\n",
    "\n",
    "  def translate(self,deltax,deltay):\n",
    "    self.x += deltax\n",
    "    self.y += deltay\n",
    "\n",
    "  def odistance(self):\n",
    "    import math\n",
    "    d = math.sqrt(self.x*self.x +\n",
    "                  self.y*self.y)\n",
    "    return(d)\n",
    "\n",
    "  def __str__(self):\n",
    "    return('('+str(self.x)+','\n",
    "            +str(self.y)+')')\n",
    "\n",
    "  def __add__(self,p):\n",
    "    return(Point(self.x + p.x, \n",
    "                 self.y + p.y))\n",
    "\n",
    "  def __lt__(self,p):\n",
    "    return(self.x < p.x and self.y < p.y)\n",
    "\n",
    "  def __le__(self,p):\n",
    "    return(self.x <= p.x and self.y <= p.y)\n",
    "      \n",
    "  def __eq__(self,p):\n",
    "    return(self.x == p.x and self.y == p.y)\n",
    "\n",
    "  def __ne__(self,p):\n",
    "    return(not(self == p))\n",
    "\n",
    "  def __gt__(self,p):\n",
    "    return(self.x > p.x and self.y > p.y)\n",
    "\n",
    "  def __ge__(self,p):\n",
    "    return(self.x >= p.x and self.y >= p.y)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "31246f50-4e57-4847-917a-054b2b268856",
   "metadata": {},
   "outputs": [],
   "source": [
    "p = Point(3,4)\n",
    "q = Point(7,10)\n",
    "r = Point(3,4)\n",
    "s = Point(7,11)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "959babbf-d1d6-4e2c-ba1b-1beaa8e47eb7",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(True, False, False, True, True, True, True, True)"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "p < q, q < p, p == q, p == r, p <= p, q <= s, s >= q, q > p"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ba743337-4afe-4c6d-b612-c0ae5d524cec",
   "metadata": {},
   "source": [
    "### Changing the implementation\n",
    "- Change the definition of Point to use polar representation, $(r,\\theta)$"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "d72b8d18-48fc-41c8-b0f8-c4ce3de9187c",
   "metadata": {},
   "outputs": [],
   "source": [
    "import math\n",
    "class Point:\n",
    "  def __init__(self,a=0,b=0):\n",
    "    self.r = math.sqrt(a*a + b*b)\n",
    "    if a == 0:\n",
    "      if b >= 0:\n",
    "        self.theta = math.pi/2\n",
    "      else:\n",
    "        self.theta = 3*math.pi/2\n",
    "    else:\n",
    "      self.theta = math.atan(b/a)\n",
    "\n",
    "  def translate(self,deltax,deltay):    \n",
    "    x = self.r*math.cos(self.theta)\n",
    "    y = self.r*math.sin(self.theta)\n",
    "    x += deltax\n",
    "    y += deltay\n",
    "    self.r = math.sqrt(x*x + y*y)\n",
    "    if x == 0:\n",
    "      if y >= 0:\n",
    "        self.theta = math.pi/2\n",
    "      else:\n",
    "        self.theta = 3*math.pi/2\n",
    "    else:\n",
    "      self.theta = math.atan(y/x)\n",
    "\n",
    "  def odistance(self):\n",
    "    return(self.r)\n",
    "\n",
    "  def __str__(self):\n",
    "    x = self.r*math.cos(self.theta)\n",
    "    y = self.r*math.sin(self.theta)\n",
    "    return('('+str(x)+','+str(y)+')')\n",
    "\n",
    "  def __add__(self,p):\n",
    "    sx = self.r*math.cos(self.theta)\n",
    "    sy = self.r*math.sin(self.theta)\n",
    "    px = p.r*math.cos(p.theta)\n",
    "    py = p.r*math.sin(p.theta)\n",
    "    return(Point(sx + px,sy+py))\n",
    "\n",
    "  def __lt__(self,p):\n",
    "    sx = self.r*math.cos(self.theta)\n",
    "    sy = self.r*math.sin(self.theta)\n",
    "    px = p.r*math.cos(p.theta)\n",
    "    py = p.r*math.sin(p.theta)\n",
    "    return(sx < px and sy < py)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "45bb3fed-5f3c-4a02-beac-7390a9679cc0",
   "metadata": {},
   "source": [
    "- The interface still assumes $(x,y)$ representation\n",
    "- When constructing a point, convert $(x,y)$ to $(r,\\theta)$\n",
    "    - Be careful about the case where $x = 0$\n",
    "- To translate a point, convert $(r,\\theta)$ back to $(x,y)$, translate, then convert back to $(r,\\theta)$\n",
    "- Similar conversion for `__str__()`, `__add__()`, `__lt__()`\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e0e6c208-6c89-4bc5-9a67-21696f2d37a6",
   "metadata": {},
   "source": [
    "### Repeat the examples above\n",
    "* Observe that nothing changes for the user of the class"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "15ff17ab-229a-4720-9393-0b2f0b4ebecb",
   "metadata": {},
   "outputs": [],
   "source": [
    "p = Point(3,4)\n",
    "q = Point(7,10)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "1587da6e-0f62-4fef-a4ad-c578a3669df1",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(5.0, 12.206555615733702)"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "p.odistance(), q.odistance()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "ca919c89-b46e-4e3d-ba10-06f3e4bdeedb",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "10.0"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "p.translate(3,4)\n",
    "p.odistance()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "858bffa2-1008-491b-bc6d-89a48c692ca5",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(6.000000000000001,7.999999999999999)\n"
     ]
    }
   ],
   "source": [
    "print(p) # Note some lack of precision going from (x,y) to (r,theta) and back"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "7ea9c512-dfb8-494f-b847-41a4b5e616b8",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'(6.000000000000001,7.999999999999999)'"
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "str(p)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "5b8a1a6c-07de-4c97-ad24-0748ae8366f5",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(13.000000000000002,18.0)\n"
     ]
    }
   ],
   "source": [
    "print(p+q)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "766be397-6409-4ff5-bf7e-da21c40c2f48",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(6.000000000000001,7.999999999999999) (6.999999999999999,10.0)\n"
     ]
    }
   ],
   "source": [
    "print(p,q)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "id": "10c63d92-1862-4f5e-8bd3-7a28df6acb7c",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(True, False)"
      ]
     },
     "execution_count": 12,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "p < q, q < p"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a8d5a98d-5fcf-4d65-81f3-2b3e9dbbd048",
   "metadata": {},
   "source": [
    "#### A note about variables inside classes\n",
    "- Without the prefix `self`, variables are internal to a function\n",
    "- Variables with prefix `self` persist within the object"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "id": "adc1c4e7-680a-4235-a295-97f0dba9e047",
   "metadata": {},
   "outputs": [],
   "source": [
    "class Experiment:\n",
    "    def __init__(self,a):\n",
    "        x = a\n",
    "        \n",
    "    def __str__(self):\n",
    "        return(str(x))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "id": "caaff9b8-6e2c-4c98-a232-49735f29bbf7",
   "metadata": {},
   "outputs": [],
   "source": [
    "z = Experiment(5)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "id": "f222462c-57b1-49a4-8bbf-bf077fb8270e",
   "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[15]\u001b[39m\u001b[32m, line 1\u001b[39m\n\u001b[32m----> \u001b[39m\u001b[32m1\u001b[39m \u001b[38;5;28;43mstr\u001b[39;49m\u001b[43m(\u001b[49m\u001b[43mz\u001b[49m\u001b[43m)\u001b[49m\n",
      "\u001b[36mCell\u001b[39m\u001b[36m \u001b[39m\u001b[32mIn[13]\u001b[39m\u001b[32m, line 6\u001b[39m, in \u001b[36mExperiment.__str__\u001b[39m\u001b[34m(self)\u001b[39m\n\u001b[32m      5\u001b[39m \u001b[38;5;28;01mdef\u001b[39;00m\u001b[38;5;250m \u001b[39m\u001b[34m__str__\u001b[39m(\u001b[38;5;28mself\u001b[39m):\n\u001b[32m----> \u001b[39m\u001b[32m6\u001b[39m     \u001b[38;5;28;01mreturn\u001b[39;00m(\u001b[38;5;28mstr\u001b[39m(\u001b[43mx\u001b[49m))\n",
      "\u001b[31mNameError\u001b[39m: name 'x' is not defined"
     ]
    }
   ],
   "source": [
    "str(z)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "id": "0c6bde24-5014-4dcb-ac3d-a8e186b3ccc9",
   "metadata": {},
   "outputs": [],
   "source": [
    "class Experiment2:\n",
    "    def __init__(self,a):\n",
    "        self.x = a\n",
    "        \n",
    "    def __str__(self):\n",
    "        return(str(self.x))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "id": "22ebcb7e-34d3-4cff-a612-92638cacfc10",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'7'"
      ]
     },
     "execution_count": 17,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "y = Experiment2(7)\n",
    "str(y)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e3e80b95-cfd9-402e-a293-0843eb1fe3b6",
   "metadata": {},
   "source": [
    "- The name `self` for the current object (first parameter) is only a convention\n",
    "- Can use any other name"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "id": "5506a2a1-425e-4365-bd18-1671f26c347e",
   "metadata": {},
   "outputs": [],
   "source": [
    "class Experiment3:\n",
    "    def __init__(self,a):\n",
    "        self.x = a\n",
    "        \n",
    "    def __str__(this):\n",
    "        return(str(this.x))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "id": "7f50d6f0-f689-4830-824c-d413c3e92052",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "17\n"
     ]
    }
   ],
   "source": [
    "x = Experiment3(17)\n",
    "print(x)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "5a600a37-8aed-43c0-be29-173ec9acb27f",
   "metadata": {},
   "source": [
    "- Classes and objects were grafted onto Python as an afterthought\n",
    "- If we have a class `C`, and object `O` and a function `f(self,x,y,z)` inside `C`, we can replace `o.f(a,b,c)` by `C.f(o,a,b,c)`.\n",
    "- In other words, `self` is actually a reference to the object on which `f` is being invoked."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "id": "6c586c29-3b6b-435d-beb1-ce7fb5a7292f",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "8.602325267042627"
      ]
     },
     "execution_count": 20,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "pnew = Point(5,7)\n",
    "pnew.odistance()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "id": "0c962b28-7a1b-4306-8a9c-e6d9cb395e29",
   "metadata": {},
   "outputs": [],
   "source": [
    "Point.translate(pnew,4,7)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "id": "a9d2b1f0-182d-4415-9525-52da153ca668",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(9.0,14.0)\n"
     ]
    }
   ],
   "source": [
    "print(pnew)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "720f971f-feb3-4420-a152-fce4ef626787",
   "metadata": {},
   "source": [
    "- This is also true for built in datatypes like `list`"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "id": "276ded1e-2a04-478c-b295-047bb3a7849f",
   "metadata": {},
   "outputs": [],
   "source": [
    "l = [1,2,3]\n",
    "l.append(4)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "id": "d682aced-3129-4424-92b4-9de1622c8911",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[1, 2, 3, 4]"
      ]
     },
     "execution_count": 24,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "l"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "id": "7c9217d3-ca7a-45be-b547-c5ce41694705",
   "metadata": {},
   "outputs": [],
   "source": [
    "list.append(l,5)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "id": "56589860-5782-4690-802f-4de9f88b6536",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[1, 2, 3, 4, 5]"
      ]
     },
     "execution_count": 26,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "l"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "4b7a1cc1-153b-47b5-996f-de4a6b3979b5",
   "metadata": {},
   "source": [
    "- Python also has no mechanism to ensure privacy of implementation\n",
    "- We cannot prevent code outside the class from accessing internal fields `p.x` and `p.y` for a `Point` `p`\n",
    "- In fact, we can even add new internal fields!"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "id": "6f5ac3e8-a9b4-432c-9391-1777a2413474",
   "metadata": {},
   "outputs": [],
   "source": [
    "pnew.z = 7"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "5a8115d2",
   "metadata": {},
   "source": [
    "### Linked lists"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "9a7bdc56-97fd-4689-8462-d0382254c1df",
   "metadata": {},
   "source": [
    "- An implementation using classes and objects; compare with our earlier implementation using nested dictionaries\n",
    "- An empty list has a single node with `value` and `next` both `None`\n",
    "- Last node in the list has `next` set to `None`"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "id": "1fe19866",
   "metadata": {},
   "outputs": [],
   "source": [
    "class List:\n",
    "    def __init__(self):\n",
    "        self.value = None\n",
    "        self.next = None\n",
    "        return\n",
    "\n",
    "    def isempty(self):\n",
    "        return(self.value == None)\n",
    "    \n",
    "    def append(self,v):   # append, iterative\n",
    "        if self.isempty():\n",
    "            self.value = v\n",
    "            return\n",
    "        \n",
    "        temp = self\n",
    "        while temp.next != None:\n",
    "            temp = temp.next\n",
    "\n",
    "        temp.next = List()\n",
    "        temp.next.value = v \n",
    "        return   \n",
    "\n",
    "    def insert(self,v):\n",
    "        if self.isempty():\n",
    "            self.value = v\n",
    "            return\n",
    "\n",
    "        newnode = List()\n",
    "        newnode.value = v\n",
    "        \n",
    "        # Exchange values in self and newnode\n",
    "        (self.value, newnode.value) = (newnode.value, self.value)\n",
    "\n",
    "        # Switch links\n",
    "        (self.next, newnode.next) = (newnode, self.next)\n",
    "\n",
    "        return\n",
    "\n",
    "\n",
    "    def __str__(self):\n",
    "        # Iteratively create a Python list from linked list\n",
    "        # and convert that to a string\n",
    "        selflist = []\n",
    "        if self.isempty():\n",
    "            return(str(selflist))\n",
    "\n",
    "        temp = self\n",
    "        selflist.append(temp.value)\n",
    "        \n",
    "        while temp.next != None:\n",
    "          temp = temp.next\n",
    "          selflist.append(temp.value)\n",
    "\n",
    "        return(str(selflist))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "id": "c6acd177",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[5]\n"
     ]
    }
   ],
   "source": [
    "l = List()\n",
    "l.append(5)\n",
    "print(l)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "id": "2d5152a0",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[5, 7]\n"
     ]
    }
   ],
   "source": [
    "l.append(7)\n",
    "print(l)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "id": "d3c9417b",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[5, 7, 9]\n"
     ]
    }
   ],
   "source": [
    "l.append(9)\n",
    "print(l)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 32,
   "id": "aebb4c56-404c-4739-aa69-e6629846c043",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[4, 5, 7, 9]\n"
     ]
    }
   ],
   "source": [
    "l.insert(4)\n",
    "print(l)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "48ed68bb-b7a6-4557-89c7-8f3ab954ce34",
   "metadata": {},
   "source": [
    "- Change the constructor\n",
    "- Can create a non-empty list to start with\n",
    "- Default is to create an empty list"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 33,
   "id": "d8792265-71e9-4973-b16b-7b145749902e",
   "metadata": {},
   "outputs": [],
   "source": [
    "class List:\n",
    "    def __init__(self,initlist = []):\n",
    "        self.value = None\n",
    "        self.next = None\n",
    "        for x in initlist:\n",
    "            self.append(x)\n",
    "        return\n",
    "\n",
    "    def isempty(self):\n",
    "        return(self.value == None)\n",
    "    \n",
    "    def append(self,v):   # append, iterative\n",
    "        if self.isempty():\n",
    "            self.value = v\n",
    "            return\n",
    "        \n",
    "        temp = self\n",
    "        while temp.next != None:\n",
    "            temp = temp.next\n",
    "\n",
    "        temp.next = List()\n",
    "        temp.next.value = v \n",
    "        return   \n",
    "\n",
    "    def insert(self,v):\n",
    "        if self.isempty():\n",
    "            self.value = v\n",
    "            return\n",
    "\n",
    "        newnode = List()\n",
    "        newnode.value = v\n",
    "        \n",
    "        # Exchange values in self and newnode\n",
    "        (self.value, newnode.value) = (newnode.value, self.value)\n",
    "\n",
    "        # Switch links\n",
    "        (self.next, newnode.next) = (newnode, self.next)\n",
    "\n",
    "        return\n",
    "\n",
    "\n",
    "    def __str__(self):\n",
    "        # Iteratively create a Python list from linked list\n",
    "        # and convert that to a string\n",
    "        selflist = []\n",
    "        if self.isempty():\n",
    "            return(str(selflist))\n",
    "\n",
    "        temp = self\n",
    "        selflist.append(temp.value)\n",
    "        \n",
    "        while temp.next != None:\n",
    "          temp = temp.next\n",
    "          selflist.append(temp.value)\n",
    "\n",
    "        return(str(selflist))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c27544fd",
   "metadata": {},
   "source": [
    "### Some performance measurements"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 34,
   "id": "9521033a-1d1c-4028-8362-b148c013468f",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[11, 12, 13]\n"
     ]
    }
   ],
   "source": [
    "l = List([11,12,13])\n",
    "print(l)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 35,
   "id": "a7724fb4-b735-4ada-830b-82cec2f8dd32",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[11, 12, 13, 14]\n"
     ]
    }
   ],
   "source": [
    "l.append(14)\n",
    "print(l)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 36,
   "id": "82fcd7db-f074-42c0-b351-03c131426e43",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[10, 11, 12, 13, 14]\n"
     ]
    }
   ],
   "source": [
    "l.insert(10)\n",
    "print(l)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 37,
   "id": "0985e5b9",
   "metadata": {},
   "outputs": [],
   "source": [
    "import time"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "9c13bb8f",
   "metadata": {},
   "source": [
    "- Insert items at the start of a linked list, multiples of $10^5$, linear blowup"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 38,
   "id": "5aa6b735",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "100000 0.03644516799977282\n",
      "200000 0.08824444399942877\n",
      "300000 0.12094478699873434\n",
      "400000 0.1904817329996149\n"
     ]
    }
   ],
   "source": [
    "for i in range(1,5):\n",
    "    l1 = List()\n",
    "    start = time.perf_counter()\n",
    "    for j in range(i*100000):\n",
    "        l1.insert(j)\n",
    "    elapsed = time.perf_counter() - start\n",
    "    print(i*100000,elapsed)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "4c15f41e",
   "metadata": {},
   "source": [
    "- Insert items at the start of a Python list, multiples of $5 \\times 10^4$, quadratic blowup"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 39,
   "id": "68c1ba2c",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "50000 0.17767955300223548\n",
      "100000 0.7180923010018887\n",
      "150000 1.6151041690027341\n",
      "200000 2.9811208480023197\n"
     ]
    }
   ],
   "source": [
    "for i in range(1,5):\n",
    "    l2 = []\n",
    "    start = time.perf_counter()\n",
    "    for j in range(i*50000):\n",
    "        l2.insert(0,j)\n",
    "    elapsed = time.perf_counter() - start\n",
    "    print(i*50000,elapsed)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "831e5d48-3481-4c09-a66a-a8a59ee5706e",
   "metadata": {},
   "source": [
    "- Append items at the end of a linked list, multiples of $10^4$, quadratic blowup"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 40,
   "id": "a69ffecb-af99-40ee-8bf6-67d749266584",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "100000 1.0824261469970224\n",
      "200000 4.68311660499603\n",
      "300000 10.58243091499753\n",
      "400000 17.945564321998972\n"
     ]
    }
   ],
   "source": [
    "for i in range(1,5):\n",
    "    l1 = List()\n",
    "    start = time.perf_counter()\n",
    "    for j in range(i*10000):\n",
    "        l1.append(j)\n",
    "    elapsed = time.perf_counter() - start\n",
    "    print(i*100000,elapsed)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "96050777-4f71-4e15-b1a4-b52528aec18a",
   "metadata": {},
   "source": [
    "- Append items at the end of a Python list, multiples of $10^6$, linear blowup"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 41,
   "id": "d9d961a5-0523-42a8-af33-e52c6ad2d0b8",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "50000 0.042161138997471426\n",
      "100000 0.08379059300204972\n",
      "150000 0.12394860199856339\n",
      "200000 0.15941382599703502\n"
     ]
    }
   ],
   "source": [
    "for i in range(1,5):\n",
    "    l2 = []\n",
    "    start = time.perf_counter()\n",
    "    for j in range(i*1000000):\n",
    "        l2.append(j)\n",
    "    elapsed = time.perf_counter() - start\n",
    "    print(i*50000,elapsed)"
   ]
  }
 ],
 "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
}
