{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "73703282",
   "metadata": {},
   "source": [
    "## Lecture 16, 09 October 2025"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "5a8115d2",
   "metadata": {},
   "source": [
    "### Linked lists"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "1dc03300-c25c-4d9b-9e0b-56293ad5cac4",
   "metadata": {},
   "source": [
    "- Our current definition, with iterative `append()`"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "02ec7e61-dfb0-4e56-8944-1c7367a256ab",
   "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):\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": "f8df0586-8da7-4f78-bf75-6be3ee12a8fe",
   "metadata": {},
   "source": [
    "- Add recursive `append()`\n",
    "    - `appendi()`, iterative\n",
    "    - `appendr()`, recursive\n",
    "    - Dummy `append()` that calls either `appendi()` or `appendr()`\n",
    "        - To avoid problems with `__init__`, `__str__`"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "85ae6403-46d8-4969-b3d6-ef836167a73c",
   "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 appendi(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 appendr(self,v):   # append, recursive\n",
    "        if self.isempty():\n",
    "            self.value = v\n",
    "        elif self.next == None:\n",
    "            self.next = List()\n",
    "            self.next.value = v\n",
    "        else:\n",
    "            self.next.appendr(v)\n",
    "        return\n",
    "\n",
    "    def append(self,v): # Could point to appendi or appendr\n",
    "        self.appendr(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": 3,
   "id": "f7675182-80cc-439d-973a-551b5936df56",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1]\n"
     ]
    }
   ],
   "source": [
    "l = List()\n",
    "for i in range(20,0,-1):\n",
    "    l.appendr(i)\n",
    "print(l)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a33fef25-8dd0-43d1-ae9a-c25914054aad",
   "metadata": {},
   "source": [
    "- Some performance measurements"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "70b38185-0128-42e2-ba65-0aefe5b22dda",
   "metadata": {},
   "outputs": [],
   "source": [
    "import time"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "aba5d2fe-98b8-412f-9410-3a01bd848960",
   "metadata": {},
   "source": [
    "- Iterative append, quadratic complexity"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "1fe19866",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1000 0.037408503994811326\n",
      "2000 0.13884098699782044\n",
      "3000 0.25658054200175684\n",
      "4000 0.41125536999606993\n"
     ]
    }
   ],
   "source": [
    "for i in range(1,5):\n",
    "    unit = 1000\n",
    "    l1 = List()\n",
    "    start = time.perf_counter()\n",
    "    for j in range(i*unit):\n",
    "        l1.appendi(j)\n",
    "    elapsed = time.perf_counter() - start\n",
    "    print(i*unit,elapsed)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "9c322128-77ce-4e6c-bcc8-86e69770f842",
   "metadata": {},
   "source": [
    "- Recursive append, also quadratic, but 5x overhead due to recursive calls"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "8275bbb5-8b08-4544-b165-dcfe064e8a8d",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1000 0.15295926301041618\n",
      "2000 0.5776570989983156\n"
     ]
    },
    {
     "ename": "RecursionError",
     "evalue": "maximum recursion depth exceeded",
     "output_type": "error",
     "traceback": [
      "\u001b[31m---------------------------------------------------------------------------\u001b[39m",
      "\u001b[31mRecursionError\u001b[39m                            Traceback (most recent call last)",
      "\u001b[36mCell\u001b[39m\u001b[36m \u001b[39m\u001b[32mIn[6]\u001b[39m\u001b[32m, line 6\u001b[39m\n\u001b[32m      4\u001b[39m start = time.perf_counter()\n\u001b[32m      5\u001b[39m \u001b[38;5;28;01mfor\u001b[39;00m j \u001b[38;5;129;01min\u001b[39;00m \u001b[38;5;28mrange\u001b[39m(i*unit):\n\u001b[32m----> \u001b[39m\u001b[32m6\u001b[39m     \u001b[43ml1\u001b[49m\u001b[43m.\u001b[49m\u001b[43mappendr\u001b[49m\u001b[43m(\u001b[49m\u001b[43mj\u001b[49m\u001b[43m)\u001b[49m\n\u001b[32m      7\u001b[39m elapsed = time.perf_counter() - start\n\u001b[32m      8\u001b[39m \u001b[38;5;28mprint\u001b[39m(i*unit,elapsed)\n",
      "\u001b[36mCell\u001b[39m\u001b[36m \u001b[39m\u001b[32mIn[2]\u001b[39m\u001b[32m, line 32\u001b[39m, in \u001b[36mList.appendr\u001b[39m\u001b[34m(self, v)\u001b[39m\n\u001b[32m     30\u001b[39m     \u001b[38;5;28mself\u001b[39m.next.value = v\n\u001b[32m     31\u001b[39m \u001b[38;5;28;01melse\u001b[39;00m:\n\u001b[32m---> \u001b[39m\u001b[32m32\u001b[39m     \u001b[38;5;28;43mself\u001b[39;49m\u001b[43m.\u001b[49m\u001b[43mnext\u001b[49m\u001b[43m.\u001b[49m\u001b[43mappendr\u001b[49m\u001b[43m(\u001b[49m\u001b[43mv\u001b[49m\u001b[43m)\u001b[49m\n\u001b[32m     33\u001b[39m \u001b[38;5;28;01mreturn\u001b[39;00m\n",
      "\u001b[36mCell\u001b[39m\u001b[36m \u001b[39m\u001b[32mIn[2]\u001b[39m\u001b[32m, line 32\u001b[39m, in \u001b[36mList.appendr\u001b[39m\u001b[34m(self, v)\u001b[39m\n\u001b[32m     30\u001b[39m     \u001b[38;5;28mself\u001b[39m.next.value = v\n\u001b[32m     31\u001b[39m \u001b[38;5;28;01melse\u001b[39;00m:\n\u001b[32m---> \u001b[39m\u001b[32m32\u001b[39m     \u001b[38;5;28;43mself\u001b[39;49m\u001b[43m.\u001b[49m\u001b[43mnext\u001b[49m\u001b[43m.\u001b[49m\u001b[43mappendr\u001b[49m\u001b[43m(\u001b[49m\u001b[43mv\u001b[49m\u001b[43m)\u001b[49m\n\u001b[32m     33\u001b[39m \u001b[38;5;28;01mreturn\u001b[39;00m\n",
      "    \u001b[31m[... skipping similar frames: List.appendr at line 32 (2973 times)]\u001b[39m\n",
      "\u001b[36mCell\u001b[39m\u001b[36m \u001b[39m\u001b[32mIn[2]\u001b[39m\u001b[32m, line 32\u001b[39m, in \u001b[36mList.appendr\u001b[39m\u001b[34m(self, v)\u001b[39m\n\u001b[32m     30\u001b[39m     \u001b[38;5;28mself\u001b[39m.next.value = v\n\u001b[32m     31\u001b[39m \u001b[38;5;28;01melse\u001b[39;00m:\n\u001b[32m---> \u001b[39m\u001b[32m32\u001b[39m     \u001b[38;5;28;43mself\u001b[39;49m\u001b[43m.\u001b[49m\u001b[43mnext\u001b[49m\u001b[43m.\u001b[49m\u001b[43mappendr\u001b[49m\u001b[43m(\u001b[49m\u001b[43mv\u001b[49m\u001b[43m)\u001b[49m\n\u001b[32m     33\u001b[39m \u001b[38;5;28;01mreturn\u001b[39;00m\n",
      "\u001b[36mCell\u001b[39m\u001b[36m \u001b[39m\u001b[32mIn[2]\u001b[39m\u001b[32m, line 26\u001b[39m, in \u001b[36mList.appendr\u001b[39m\u001b[34m(self, v)\u001b[39m\n\u001b[32m     25\u001b[39m \u001b[38;5;28;01mdef\u001b[39;00m\u001b[38;5;250m \u001b[39m\u001b[34mappendr\u001b[39m(\u001b[38;5;28mself\u001b[39m,v):   \u001b[38;5;66;03m# append, recursive\u001b[39;00m\n\u001b[32m---> \u001b[39m\u001b[32m26\u001b[39m     \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28;43mself\u001b[39;49m\u001b[43m.\u001b[49m\u001b[43misempty\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m:\n\u001b[32m     27\u001b[39m         \u001b[38;5;28mself\u001b[39m.value = v\n\u001b[32m     28\u001b[39m     \u001b[38;5;28;01melif\u001b[39;00m \u001b[38;5;28mself\u001b[39m.next == \u001b[38;5;28;01mNone\u001b[39;00m:\n",
      "\u001b[31mRecursionError\u001b[39m: maximum recursion depth exceeded"
     ]
    }
   ],
   "source": [
    "for i in range(1,5):\n",
    "    unit = 1000\n",
    "    l1 = List()\n",
    "    start = time.perf_counter()\n",
    "    for j in range(i*unit):\n",
    "        l1.appendr(j)\n",
    "    elapsed = time.perf_counter() - start\n",
    "    print(i*unit,elapsed)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c6e80c8b-ceb1-4373-a7ac-1cafe921d0e4",
   "metadata": {},
   "source": [
    "- Enhance recursion limit\n",
    "    - $2^{31}-1$ is maximum allowed"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "958b087f-76fc-43d5-baad-6e3d87b33162",
   "metadata": {},
   "outputs": [],
   "source": [
    "import sys\n",
    "sys.setrecursionlimit(2**31-1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "f937d90c-598a-44ff-9769-2cce07715cc0",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1000 0.1520825240004342\n",
      "2000 0.59965024900157\n",
      "3000 1.326439897005912\n",
      "4000 2.4543402420094935\n"
     ]
    }
   ],
   "source": [
    "for i in range(1,5):\n",
    "    unit = 1000\n",
    "    l1 = List()\n",
    "    start = time.perf_counter()\n",
    "    for j in range(i*unit):\n",
    "        l1.appendr(j)\n",
    "    elapsed = time.perf_counter() - start\n",
    "    print(i*unit,elapsed)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a1828ac0-29f5-4b11-ab99-612e3e4c9b87",
   "metadata": {},
   "source": [
    "\n",
    "\n",
    "\n",
    "\n",
    "\n",
    "\n",
    "\n",
    "\n",
    "\n",
    "\n",
    "\n",
    "\n",
    "\n",
    "\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "eb79f4ef-fdce-4457-a89e-09e8e5075bac",
   "metadata": {},
   "source": [
    "- Add `delete()`"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "86621218-ae0a-4f70-8176-bfc6dea51eda",
   "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 appendi(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 appendr(self,v):   # append, recursive\n",
    "        if self.isempty():\n",
    "            self.value = v\n",
    "        elif self.next == None:\n",
    "            self.next = List([v])\n",
    "        else:\n",
    "            self.next.appendr(v)\n",
    "        return\n",
    "\n",
    "    def append(self,v):\n",
    "        self.appendr(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",
    "    def delete(self,v):   # delete, recursive\n",
    "        if self.isempty():\n",
    "            return\n",
    "\n",
    "        if self.value == v:\n",
    "            if self.next != None:\n",
    "                self.value = self.next.value\n",
    "                self.next = self.next.next\n",
    "            else:\n",
    "                self.value = None\n",
    "            return\n",
    "        else:\n",
    "            if self.next != None:\n",
    "                self.next.delete(v)\n",
    "                # Ensure that there is no empty node at the end of the list\n",
    "                if self.next.value == None:\n",
    "                    self.next = None\n",
    "        return\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": 10,
   "id": "7cef336f-2692-43f2-86c5-e2dbebc3b103",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99]\n"
     ]
    }
   ],
   "source": [
    "l = List(list(range(100)))\n",
    "print(l)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "050e6b1b-8062-44f6-9d46-a96356f26a36",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99]\n"
     ]
    }
   ],
   "source": [
    "l.delete(1)\n",
    "print(l)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "id": "b95f6f92-0698-4b0d-b899-8f17c3037cef",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99]\n"
     ]
    }
   ],
   "source": [
    "l.delete(0)\n",
    "print(l)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "id": "81db57d7-a77b-45ca-ba5f-fc6e0bc1f1d1",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98]\n"
     ]
    }
   ],
   "source": [
    "l.delete(99)\n",
    "print(l)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "bea293f4-1fbf-4aa7-b938-4804202ab573",
   "metadata": {},
   "source": [
    "### Exception handling"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "3af91f18-45fc-4880-857c-16c069f14cdf",
   "metadata": {},
   "source": [
    "- Example with `input()`\n",
    "- Python statement `pass` is a do-nothing placeholder. Cannot omit `except:` block, nor can you have an empty block."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a5d3ea09-a024-44b7-8cd8-a06ec77ea7e7",
   "metadata": {},
   "source": [
    "\n",
    "\n",
    "\n",
    "\n",
    "\n",
    "\n",
    "\n",
    "\n",
    "\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "id": "834ef1e9-fe01-45c6-b023-1983f455372d",
   "metadata": {},
   "outputs": [
    {
     "name": "stdin",
     "output_type": "stream",
     "text": [
      "Enter a number:  asdf\n",
      "Enter a number:  7.3\n",
      "Enter a number:  -99\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "-99\n"
     ]
    }
   ],
   "source": [
    "invalid = True\n",
    "while (invalid):\n",
    "    try:\n",
    "        xstr = input(\"Enter a number: \")\n",
    "        xint = int(xstr)\n",
    "        invalid = False\n",
    "    except:\n",
    "        pass\n",
    "print(xint)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "id": "a1cdf5c3-8698-4e79-95da-15c191112333",
   "metadata": {},
   "outputs": [
    {
     "name": "stdin",
     "output_type": "stream",
     "text": [
      "Enter a number:  asdf\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Try again:\n"
     ]
    },
    {
     "name": "stdin",
     "output_type": "stream",
     "text": [
      "Enter a number:  7.3\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Try again:\n"
     ]
    },
    {
     "name": "stdin",
     "output_type": "stream",
     "text": [
      "Enter a number:  -919\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "-919\n"
     ]
    }
   ],
   "source": [
    "invalid = True\n",
    "tryagain = False\n",
    "while (invalid):\n",
    "    try:\n",
    "        if tryagain:\n",
    "            print(\"Try again:\")\n",
    "        xstr = input(\"Enter a number: \")\n",
    "        xint = int(xstr)\n",
    "        invalid = False\n",
    "    except:\n",
    "        tryagain = True\n",
    "print(xint)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a073f234-181a-47b9-8f39-43a0c259f7a5",
   "metadata": {},
   "source": [
    "- Catch a specific type of exception"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "id": "9a1a0f36-ff84-4533-9e0a-5312cb68a072",
   "metadata": {},
   "outputs": [
    {
     "ename": "ValueError",
     "evalue": "invalid literal for int() with base 10: 'abc'",
     "output_type": "error",
     "traceback": [
      "\u001b[31m---------------------------------------------------------------------------\u001b[39m",
      "\u001b[31mValueError\u001b[39m                                Traceback (most recent call last)",
      "\u001b[36mCell\u001b[39m\u001b[36m \u001b[39m\u001b[32mIn[16]\u001b[39m\u001b[32m, line 1\u001b[39m\n\u001b[32m----> \u001b[39m\u001b[32m1\u001b[39m \u001b[38;5;28;43mint\u001b[39;49m\u001b[43m(\u001b[49m\u001b[33;43m\"\u001b[39;49m\u001b[33;43mabc\u001b[39;49m\u001b[33;43m\"\u001b[39;49m\u001b[43m)\u001b[49m\n",
      "\u001b[31mValueError\u001b[39m: invalid literal for int() with base 10: 'abc'"
     ]
    }
   ],
   "source": [
    "int(\"abc\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "id": "fdaa4a37-5c54-4153-9983-2bd118dd9186",
   "metadata": {},
   "outputs": [
    {
     "name": "stdin",
     "output_type": "stream",
     "text": [
      "Enter a number:  xyz\n",
      "Enter a number:  748\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "748\n"
     ]
    }
   ],
   "source": [
    "invalid = True\n",
    "while (invalid):\n",
    "    try:\n",
    "        xstr = input(\"Enter a number: \")\n",
    "        xint = int(xstr)\n",
    "        invalid = False\n",
    "    except ValueError:\n",
    "        pass\n",
    "print(xint)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "9e9e387d-9c2b-44b3-8c32-21a307db12de",
   "metadata": {},
   "source": [
    "- Raising an exception in `List()`\n",
    "- Inserting a negative value raises `ValueError`\n",
    "- Add negative value to error message"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "id": "3f7a6da5-1fdd-4553-9d7d-5818d77aef25",
   "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 appendi(self,v):   # append, iterative\n",
    "        if v < 0:\n",
    "            raise ValueError(\"Negative input: \" + str(v))\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 appendr(self,v):   # append, recursive\n",
    "        if v < 0:\n",
    "            raise ValueError(\"Negative input: \" + str(v))\n",
    "        if self.isempty():\n",
    "            self.value = v\n",
    "        elif self.next == None:\n",
    "            self.next = List([v])\n",
    "        else:\n",
    "            self.next.appendr(v)\n",
    "        return\n",
    "\n",
    "    def append(self,v):\n",
    "        self.appendr(v)\n",
    "        return\n",
    "\n",
    "    def insert(self,v):\n",
    "        if v < 0:\n",
    "            raise ValueError(\"Negative input: \" + str(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",
    "    def delete(self,v):   # delete, recursive\n",
    "        if self.isempty():\n",
    "            return\n",
    "\n",
    "        if self.value == v:\n",
    "            self.value = None\n",
    "            if self.next != None:\n",
    "                self.value = self.next.value\n",
    "                self.next = self.next.next\n",
    "            return\n",
    "        else:\n",
    "            if self.next != None:\n",
    "                self.next.delete(v)\n",
    "                if self.next.value == None:\n",
    "                    self.next = None\n",
    "        return\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": 19,
   "id": "064e26ad-9096-48fe-a714-f5396d68a931",
   "metadata": {},
   "outputs": [
    {
     "ename": "ValueError",
     "evalue": "Negative input: -2",
     "output_type": "error",
     "traceback": [
      "\u001b[31m---------------------------------------------------------------------------\u001b[39m",
      "\u001b[31mValueError\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 l = \u001b[43mList\u001b[49m\u001b[43m(\u001b[49m\u001b[43m[\u001b[49m\u001b[32;43m1\u001b[39;49m\u001b[43m,\u001b[49m\u001b[43m-\u001b[49m\u001b[32;43m2\u001b[39;49m\u001b[43m,\u001b[49m\u001b[32;43m3\u001b[39;49m\u001b[43m]\u001b[49m\u001b[43m)\u001b[49m\n\u001b[32m      2\u001b[39m \u001b[38;5;28mprint\u001b[39m(l)\n",
      "\u001b[36mCell\u001b[39m\u001b[36m \u001b[39m\u001b[32mIn[18]\u001b[39m\u001b[32m, line 6\u001b[39m, in \u001b[36mList.__init__\u001b[39m\u001b[34m(self, initlist)\u001b[39m\n\u001b[32m      4\u001b[39m \u001b[38;5;28mself\u001b[39m.next = \u001b[38;5;28;01mNone\u001b[39;00m\n\u001b[32m      5\u001b[39m \u001b[38;5;28;01mfor\u001b[39;00m x \u001b[38;5;129;01min\u001b[39;00m initlist:\n\u001b[32m----> \u001b[39m\u001b[32m6\u001b[39m     \u001b[38;5;28;43mself\u001b[39;49m\u001b[43m.\u001b[49m\u001b[43mappend\u001b[49m\u001b[43m(\u001b[49m\u001b[43mx\u001b[49m\u001b[43m)\u001b[49m\n\u001b[32m      7\u001b[39m \u001b[38;5;28;01mreturn\u001b[39;00m\n",
      "\u001b[36mCell\u001b[39m\u001b[36m \u001b[39m\u001b[32mIn[18]\u001b[39m\u001b[32m, line 39\u001b[39m, in \u001b[36mList.append\u001b[39m\u001b[34m(self, v)\u001b[39m\n\u001b[32m     38\u001b[39m \u001b[38;5;28;01mdef\u001b[39;00m\u001b[38;5;250m \u001b[39m\u001b[34mappend\u001b[39m(\u001b[38;5;28mself\u001b[39m,v):\n\u001b[32m---> \u001b[39m\u001b[32m39\u001b[39m     \u001b[38;5;28;43mself\u001b[39;49m\u001b[43m.\u001b[49m\u001b[43mappendr\u001b[49m\u001b[43m(\u001b[49m\u001b[43mv\u001b[49m\u001b[43m)\u001b[49m\n\u001b[32m     40\u001b[39m     \u001b[38;5;28;01mreturn\u001b[39;00m\n",
      "\u001b[36mCell\u001b[39m\u001b[36m \u001b[39m\u001b[32mIn[18]\u001b[39m\u001b[32m, line 29\u001b[39m, in \u001b[36mList.appendr\u001b[39m\u001b[34m(self, v)\u001b[39m\n\u001b[32m     27\u001b[39m \u001b[38;5;28;01mdef\u001b[39;00m\u001b[38;5;250m \u001b[39m\u001b[34mappendr\u001b[39m(\u001b[38;5;28mself\u001b[39m,v):   \u001b[38;5;66;03m# append, recursive\u001b[39;00m\n\u001b[32m     28\u001b[39m     \u001b[38;5;28;01mif\u001b[39;00m v < \u001b[32m0\u001b[39m:\n\u001b[32m---> \u001b[39m\u001b[32m29\u001b[39m         \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;167;01mValueError\u001b[39;00m(\u001b[33m\"\u001b[39m\u001b[33mNegative input: \u001b[39m\u001b[33m\"\u001b[39m + \u001b[38;5;28mstr\u001b[39m(v))\n\u001b[32m     30\u001b[39m     \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28mself\u001b[39m.isempty():\n\u001b[32m     31\u001b[39m         \u001b[38;5;28mself\u001b[39m.value = v\n",
      "\u001b[31mValueError\u001b[39m: Negative input: -2"
     ]
    }
   ],
   "source": [
    "l = List([1,-2,3])\n",
    "print(l)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "id": "52e5eaee-4e79-4131-969a-08dae15cb361",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "oops\n"
     ]
    }
   ],
   "source": [
    "try:\n",
    "    l = List([1,-2,3])\n",
    "except ValueError:\n",
    "    print(\"oops\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "id": "c4144ec9-e7d5-430c-b9ca-5571d50095a3",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Negative input: -2\n"
     ]
    }
   ],
   "source": [
    "try:\n",
    "    l = List([1,-2,3])\n",
    "except ValueError as errormsg:  # Saves error value in errormsg\n",
    "    print(errormsg)"
   ]
  }
 ],
 "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
}
