{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "6b4fce18-128e-441d-9040-7d738b1ac1c8",
   "metadata": {},
   "source": [
    "## PDSP 2025, Lecture 09, 4 September 2025"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "90dd963d-bf0a-4fa5-963d-1f79a418243d",
   "metadata": {},
   "outputs": [],
   "source": [
    "matchlist = [\n",
    "    (\"Chennai\",\"RCB\",\"CSK\",\"RCB\",\"CSK\",174),\n",
    "    (\"Mohali\",\"DC\",\"PK\",\"PK\",\"PK\",175),\n",
    "    (\"Kolkata\",\"KKR\",\"SRH\",\"SRH\",\"KKR\",209),\n",
    "    (\"Jaipur\",\"RR\",\"LSG\",\"RR\",\"RR\",194),\n",
    "    (\"Ahmedabad\",\"GT\",\"MI\",\"MI\",\"GT\",169),\n",
    "    (\"Bengaluru\",\"PK\",\"RCB\",\"RCB\",\"RCB\",177),\n",
    "    (\"Chennai\",\"CSK\",\"GT\",\"GT\",\"CSK\",207),\n",
    "    (\"Hyderabad\",\"SRH\",\"MI\",\"MI\",\"SRH\",278),\n",
    "    (\"Jaipur\",\"RR\",\"DC\",\"DC\",\"RR\",186),\n",
    "    (\"Bengaluru\",\"RCB\",\"KKR\",\"KKR\",\"KKR\",183),\n",
    "    (\"Lucknow\",\"LSG\",\"PK\",\"LSG\",\"LSG\",200),\n",
    "    (\"Ahmedabad\",\"SRH\",\"GT\",\"SRH\",\"GT\",163),\n",
    "    (\"Visakhapatnam\",\"DC\",\"CSK\",\"DC\",\"DC\",192),\n",
    "    (\"Mumbai\",\"MI\",\"RR\",\"RR\",\"RR\",126),\n",
    "    (\"Bengaluru\",\"LSG\",\"RCB\",\"RCB\",\"LSG\",182),\n",
    "    (\"Visakhapatnam\",\"KKR\",\"DC\",\"KKR\",\"KKR\",273),\n",
    "    (\"Ahmedabad\",\"GT\",\"PK\",\"PK\",\"PK\",200),\n",
    "    (\"Hyderabad\",\"CSK\",\"SRH\",\"SRH\",\"SRH\",166),\n",
    "    (\"Jaipur\",\"RCB\",\"RR\",\"RR\",\"RR\",184),\n",
    "    (\"Mumbai\",\"MI\",\"DC\",\"DC\",\"MI\",235),\n",
    "    (\"Lucknow\",\"LSG\",\"GT\",\"LSG\",\"LSG\",164),\n",
    "    (\"Chennai\",\"KKR\",\"CSK\",\"CSK\",\"CSK\",138),\n",
    "    (\"Mohali\",\"SRH\",\"PK\",\"PK\",\"SRH\",183),\n",
    "    (\"Jaipur\",\"RR\",\"GT\",\"GT\",\"GT\",197),\n",
    "    (\"Mumbai\",\"RCB\",\"MI\",\"MI\",\"MI\",197),\n",
    "    (\"Lucknow\",\"LSG\",\"DC\",\"LSG\",\"DC\",168),\n",
    "    (\"Mohali\",\"PK\",\"RR\",\"RR\",\"RR\",148),\n",
    "    (\"Kolkata\",\"LSG\",\"KKR\",\"KKR\",\"KKR\",162),\n",
    "    (\"Mumbai\",\"CSK\",\"MI\",\"MI\",\"CSK\",207),\n",
    "    (\"Bengaluru\",\"SRH\",\"RCB\",\"RCB\",\"SRH\",288),\n",
    "    (\"Kolkata\",\"KKR\",\"RR\",\"RR\",\"RR\",224),\n",
    "    (\"Ahmedabad\",\"GT\",\"DC\",\"DC\",\"DC\",90),\n",
    "    (\"Mohali\",\"MI\",\"PK\",\"PK\",\"MI\",193),\n",
    "    (\"Lucknow\",\"CSK\",\"LSG\",\"LSG\",\"LSG\",177),\n",
    "    (\"Delhi\",\"SRH\",\"DC\",\"DC\",\"SRH\",267),\n",
    "    (\"Kolkata\",\"KKR\",\"RCB\",\"RCB\",\"KKR\",223),\n",
    "    (\"Mohali\",\"PK\",\"GT\",\"PK\",\"GT\",143),\n",
    "    (\"Jaipur\",\"MI\",\"RR\",\"MI\",\"RR\",180),\n",
    "    (\"Chennai\",\"CSK\",\"LSG\",\"LSG\",\"LSG\",211),\n",
    "    (\"Delhi\",\"DC\",\"GT\",\"GT\",\"DC\",225),\n",
    "    (\"Hyderabad\",\"RCB\",\"SRH\",\"RCB\",\"RCB\",207),\n",
    "    (\"Kolkata\",\"KKR\",\"PK\",\"PK\",\"PK\",262),\n",
    "    (\"Delhi\",\"DC\",\"MI\",\"MI\",\"DC\",258),\n",
    "    (\"Lucknow\",\"LSG\",\"RR\",\"RR\",\"RR\",197),\n",
    "    (\"Ahmedabad\",\"GT\",\"RCB\",\"RCB\",\"RCB\",201),\n",
    "    (\"Chennai\",\"CSK\",\"SRH\",\"SRH\",\"CSK\",213),\n",
    "    (\"Kolkata\",\"DC\",\"KKR\",\"DC\",\"KKR\",154),\n",
    "    (\"Lucknow\",\"MI\",\"LSG\",\"LSG\",\"LSG\",145),\n",
    "    (\"Chennai\",\"CSK\",\"PK\",\"PK\",\"PK\",163),\n",
    "    (\"Hyderabad\",\"SRH\",\"RR\",\"SRH\",\"SRH\",202),\n",
    "    (\"Mumbai\",\"KKR\",\"MI\",\"MI\",\"KKR\",170),\n",
    "    (\"Bengaluru\",\"GT\",\"RCB\",\"RCB\",\"RCB\",148),\n",
    "    (\"Dharamsala\",\"CSK\",\"PK\",\"PK\",\"CSK\",168),\n",
    "    (\"Lucknow\",\"KKR\",\"LSG\",\"LSG\",\"KKR\",236),\n",
    "    (\"Mumbai\",\"SRH\",\"MI\",\"MI\",\"MI\",174),\n",
    "    (\"Delhi\",\"DC\",\"RR\",\"RR\",\"DC\",222),\n",
    "    (\"Hyderabad\",\"LSG\",\"SRH\",\"LSG\",\"SRH\",166),\n",
    "    (\"Dharamsala\",\"RCB\",\"PK\",\"PK\",\"RCB\",242),\n",
    "    (\"Ahmedabad\",\"GT\",\"CSK\",\"CSK\",\"GT\",232),\n",
    "    (\"Kolkata\",\"KKR\",\"MI\",\"MI\",\"KKR\",158),\n",
    "    (\"Chennai\",\"RR\",\"CSK\",\"RR\",\"CSK\",142),\n",
    "    (\"Bengaluru\",\"RCB\",\"DC\",\"DC\",\"RCB\",188),\n",
    "    (\"Delhi\",\"DC\",\"LSG\",\"LSG\",\"DC\",209),\n",
    "    (\"Guwahati\",\"RR\",\"PK\",\"RR\",\"PK\",145),\n",
    "    (\"Mumbai\",\"LSG\",\"MI\",\"MI\",\"LSG\",215),\n",
    "    (\"Bengaluru\",\"RCB\",\"CSK\",\"CSK\",\"RCB\",219),\n",
    "    (\"Hyderabad\",\"PK\",\"SRH\",\"PK\",\"SRH\",215),\n",
    "    (\"Ahmedabad\",\"SRH\",\"KKR\",\"SRH\",\"KKR\",160),\n",
    "    (\"Ahmedabad\",\"RCB\",\"RR\",\"RR\",\"RR\",173),\n",
    "    (\"Chennai\",\"SRH\",\"RR\",\"RR\",\"SRH\",176),\n",
    "    (\"Chennai\",\"SRH\",\"KKR\",\"SRH\",\"KKR\",114)\n",
    "]"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "15aec21a-795c-4e6a-8d82-bcf549fc5925",
   "metadata": {},
   "source": [
    "- List of teams that played IPL 2024"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "178d9244-2567-4855-b1c2-ab26f3c70bf5",
   "metadata": {},
   "outputs": [],
   "source": [
    "def get_teams(l):\n",
    "    teamdict = {}\n",
    "    for m in l:\n",
    "        team1,team2 = m[1],m[2]\n",
    "        teamdict[team1] = 1\n",
    "        teamdict[team2] = 2\n",
    "    return(sorted(list(teamdict)))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "c2881bd6-f0aa-4220-b8d2-2d17f4e1a299",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "['CSK', 'DC', 'GT', 'KKR', 'LSG', 'MI', 'PK', 'RCB', 'RR', 'SRH']"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "get_teams(matchlist)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "2e82f948-c993-4a3b-a292-e67f42fd4809",
   "metadata": {},
   "source": [
    "### Map\n",
    "- Apply a function $f()$ to each element in a list\n",
    "- Convert $[x_0,x_1,\\ldots,x_{n-1}]$ to $[f(x_0),f(x_1),\\ldots,f(x_{n-1})]$\n",
    "- In Python, `map(f,l)` applies `f` to each element of `l`"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d5bf4f17-5a4c-4b0f-b238-15b51396d1a5",
   "metadata": {},
   "source": [
    "**Example**\n",
    "- List full names of teams that played in IPL 2024\n",
    "- First, a function to map team abbreviations to full names, using a dictionary"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "e3c85b87-4a79-447b-9c1d-7309d5029bb7",
   "metadata": {},
   "outputs": [],
   "source": [
    "def expand(s):\n",
    "    teamdict = {'CSK':'Chennai Super Kings', \n",
    "                'PK':'Punjab Kings', \n",
    "                'SRH':'Sunrisers Hyderabad',\n",
    "                'LSG':'Lucknow Super Giants', \n",
    "                'MI':'Mumbai Indians', \n",
    "                'RCB':'Royal Challengers Bengaluru',\n",
    "                'GT':'Gujarat Titans', \n",
    "                'DC':'Delhi Capitals', \n",
    "                'KKR':'Kolata Knight Riders', \n",
    "                'RR':'Rajasthan Royals'}\n",
    "    if (s in teamdict):\n",
    "        return(teamdict[s])\n",
    "    else:\n",
    "        return('No info')"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d431b780-8661-4154-93ae-6726818c800c",
   "metadata": {},
   "source": [
    "- Now, we can `map` this function to the outcome of our earlier function"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "433010eb-0e51-4f90-ab60-8bbd3db74292",
   "metadata": {},
   "outputs": [],
   "source": [
    "teams = get_teams(matchlist)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "4d4aef75-a130-4fff-b98e-7b32111ccbf9",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "['CSK', 'DC', 'GT', 'KKR', 'LSG', 'MI', 'PK', 'RCB', 'RR', 'SRH']"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "teams"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "bc7ea479-a50b-4917-874d-5e2dd3fac3b9",
   "metadata": {},
   "source": [
    "- Output of `map` is a sequence, but not a list, like `range`"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "6869bb8d-a568-42c1-82b7-9f47c14d20cb",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<map at 0x7f0b226e5ff0>"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "map(expand,teams)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b0bb5bb5-3c14-48ee-88c7-3907d19e5a96",
   "metadata": {},
   "source": [
    "- Explicitly convert it to a list to view the output"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "b13d6001-7687-4ec5-a2ca-23d518449fac",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "['Chennai Super Kings',\n",
       " 'Delhi Capitals',\n",
       " 'Gujarat Titans',\n",
       " 'Kolata Knight Riders',\n",
       " 'Lucknow Super Giants',\n",
       " 'Mumbai Indians',\n",
       " 'Punjab Kings',\n",
       " 'Royal Challengers Bengaluru',\n",
       " 'Rajasthan Royals',\n",
       " 'Sunrisers Hyderabad']"
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "list(map(expand,teams))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "8ef3bdf5-ddb5-4f28-bf31-2c9378f98bb6",
   "metadata": {},
   "source": [
    "- Since `expand` returns `No info` for unknown keys, the following works\n",
    "- Note that keys need not be of uniform type: `7` is merely an unknown key, not an invalid one because it is not a string"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "521b8fa7-f11d-4a1a-9ab9-47cbb6f8b7bf",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "['No info', 'No info', 'No info']"
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "list(map(expand,['xxx','yyy',7]))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "8a878ee4-04c5-4437-bc3c-335c63a83eba",
   "metadata": {},
   "source": [
    "### Filter\n",
    "- Check if each item $x$ in a list satisfies a property $p(x)$\n",
    "- Retain only such elements\n",
    "- Filter out elements that do not satisfy $p()$\n",
    "- In Python, `filter(p,l)`"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "1ac198ce-9306-4816-83cd-783cc6bd17ed",
   "metadata": {},
   "source": [
    "**Example**\n",
    "- List matches where CSK won the toss\n",
    "- First define the filter function -- returns `True` or `False`"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "6ba51b40-1397-411a-87c4-26dbd4c387f7",
   "metadata": {},
   "outputs": [],
   "source": [
    "def csktosswin(t): # t is expected to be one tuple from matchlist\n",
    "    return(t[3] == 'CSK')"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "5e3814e6-078c-4153-9ec8-eb692d224cfb",
   "metadata": {},
   "source": [
    "- Now, filter matchlist using this function"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "89cf026b-2610-4712-8b8d-201ad8c2cb2a",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[('Chennai', 'KKR', 'CSK', 'CSK', 'CSK', 138),\n",
       " ('Ahmedabad', 'GT', 'CSK', 'CSK', 'GT', 232),\n",
       " ('Bengaluru', 'RCB', 'CSK', 'CSK', 'RCB', 219)]"
      ]
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "list(filter(csktosswin,matchlist))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e004e6ba-25fe-42a2-94c9-61995a40d59e",
   "metadata": {},
   "source": [
    "## List comprehension\n",
    "- Combine map and filter to create a list\n",
    "- *Set comprehension*: Squares of positive even integers = $\\{x^2 \\mid x \\in \\mathbb{Z}, x > 0\\}$\n",
    "- In Python: `[ f(x) for x in l if p(x) ]`"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "2c2fbaf9-0caf-4835-b639-6148ca667cf7",
   "metadata": {},
   "source": [
    "**Example**\n",
    "- Full names of all teams in IPL 2024"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "id": "1543189b-0130-48c5-9e09-419ee7aca93a",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "['Chennai Super Kings',\n",
       " 'Delhi Capitals',\n",
       " 'Gujarat Titans',\n",
       " 'Kolata Knight Riders',\n",
       " 'Lucknow Super Giants',\n",
       " 'Mumbai Indians',\n",
       " 'Punjab Kings',\n",
       " 'Royal Challengers Bengaluru',\n",
       " 'Rajasthan Royals',\n",
       " 'Sunrisers Hyderabad']"
      ]
     },
     "execution_count": 12,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "[ expand(t) for t in get_teams(matchlist) ]"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ce7f1347-35c0-4103-b67d-e6cf2cb1d02a",
   "metadata": {},
   "source": [
    "- List both teams in matches where CSK won the toss"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "id": "e257a7ee-39cb-496d-a8fe-a74befb4b058",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[('KKR', 'CSK'), ('GT', 'CSK'), ('RCB', 'CSK')]"
      ]
     },
     "execution_count": 13,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "[ (t[1],t[2]) for t in matchlist if t[3] == \"CSK\" ]"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "4122f5f0-e516-4bb7-b071-365d18d2cebf",
   "metadata": {},
   "source": [
    "- Same, with full names"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "id": "311da493-0877-4c67-adc7-15d4aa71e531",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[('Kolata Knight Riders', 'Chennai Super Kings'),\n",
       " ('Gujarat Titans', 'Chennai Super Kings'),\n",
       " ('Royal Challengers Bengaluru', 'Chennai Super Kings')]"
      ]
     },
     "execution_count": 14,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "[ (expand(t[1]),expand(t[2])) for t in matchlist if t[3] == \"CSK\" ]\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "5e286ff7-4038-4b0f-a5ea-ba3ddb34c8b1",
   "metadata": {},
   "source": [
    "- Similar notation works for dictionaries\n",
    "- Create a dictionary matching team abbreviations to full names for teams in IPL 2024"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "id": "209e78f1-6af5-448b-a756-2acbcf2141ab",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'CSK': 'Chennai Super Kings',\n",
       " 'DC': 'Delhi Capitals',\n",
       " 'GT': 'Gujarat Titans',\n",
       " 'KKR': 'Kolata Knight Riders',\n",
       " 'LSG': 'Lucknow Super Giants',\n",
       " 'MI': 'Mumbai Indians',\n",
       " 'PK': 'Punjab Kings',\n",
       " 'RCB': 'Royal Challengers Bengaluru',\n",
       " 'RR': 'Rajasthan Royals',\n",
       " 'SRH': 'Sunrisers Hyderabad'}"
      ]
     },
     "execution_count": 15,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "{ t:expand(t) for t in get_teams(matchlist) }"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "8de1b8a7-f8f7-43f9-ad41-461099a7b94f",
   "metadata": {},
   "source": [
    "- Recall that `uniqd` created a list of unique items via keys of a dictionary\n",
    "- Here is a short way to do this using list comprehension"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "id": "568af303-0723-4435-bf03-e40261a01666",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "['CSK', 'PK', 'SRH', 'LSG', 'MI', 'RCB', 'GT', 'DC', 'KKR', 'RR']"
      ]
     },
     "execution_count": 16,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "list({ x[2]:1 for x in matchlist})"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e695b662-59dc-40ca-9f62-dd7cf89ee394",
   "metadata": {},
   "source": [
    "- Uses the fact that a dictionary `d` when interpreted as a sequence is implcitly `d.keys()`\n",
    "- `list(d)` looks for a sequence `d`"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "8ce9a439-2df3-4066-b6ba-ac7a6ed8f393",
   "metadata": {},
   "source": [
    "- Can also do the equivalent of relational algebra selection and projection\n",
    "- Project matchlist onto columns `team 1, team 2, target` (columns 1,2,5) where CSK won the toss\n",
    "    - Filter by CSK winning the toss (select)\n",
    "    - Project onto columns 1,2,5"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "id": "a17ab9d4-7ac4-48e4-ac08-75b3fc1c4a55",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[('KKR', 'CSK', 138), ('GT', 'CSK', 232), ('RCB', 'CSK', 219)]"
      ]
     },
     "execution_count": 17,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "[ (t[1],t[2],t[5]) for t in matchlist if t[3] == \"CSK\" ]"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "abc0a457-b352-4ecc-8ee7-6f198d1812d9",
   "metadata": {},
   "source": [
    "- Can have multiple generators\n",
    "- Like nested loops, the left most generator is the outermost loop"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "id": "7471a4a2-697b-4283-945c-c0af252951db",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[(0, 0),\n",
       " (0, 1),\n",
       " (0, 2),\n",
       " (0, 3),\n",
       " (1, 0),\n",
       " (1, 1),\n",
       " (1, 2),\n",
       " (1, 3),\n",
       " (2, 0),\n",
       " (2, 1),\n",
       " (2, 2),\n",
       " (2, 3)]"
      ]
     },
     "execution_count": 18,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "[ (i,j) for i in range(3) for j in range(4) ]"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "1a68d22b-e72b-4446-85b7-aafcb19ab738",
   "metadata": {},
   "source": [
    "- **Example**: \"Small\" Pythagorean triples"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "id": "a467e79d-0a8b-4bc9-a647-daab169956ec",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[(3, 4, 5),\n",
       " (4, 3, 5),\n",
       " (5, 12, 13),\n",
       " (6, 8, 10),\n",
       " (8, 6, 10),\n",
       " (8, 15, 17),\n",
       " (9, 12, 15),\n",
       " (12, 5, 13),\n",
       " (12, 9, 15),\n",
       " (15, 8, 17)]"
      ]
     },
     "execution_count": 19,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "[ (x,y,z) for x in range(1,20) for y in range(1,20) for z in range(1,20) if x*x + y*y == z*z ]"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "3e16c208-990b-41b0-b2d4-4b0240872eea",
   "metadata": {},
   "source": [
    "- Avoid duplicates like `(3,4,5)`, `(4,3,5)` -- ensure that `y > x`\n",
    "- `y in range(x,20)` -- later generator can use value from an earlier one, like in a nested loop"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "id": "8454d461-83a0-4857-9e4c-7f432e168e43",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[(3, 4, 5), (5, 12, 13), (6, 8, 10), (8, 15, 17), (9, 12, 15)]"
      ]
     },
     "execution_count": 20,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "[ (x,y,z) for x in range(1,20) for y in range(x,20) for z in range(x,20) if x*x + y*y == z*z ]"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "30f76c96-a1f7-4394-b502-26644bafd163",
   "metadata": {},
   "source": [
    "- Can report the triples in a different order"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "id": "35f81e0f-6beb-499b-83ba-9eb816595c6a",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[(4, 3, 5), (12, 5, 13), (8, 6, 10), (15, 8, 17), (12, 9, 15)]"
      ]
     },
     "execution_count": 21,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "[ (y,x,z) for x in range(1,20) for y in range(x,20) for z in range(x,20) if x*x + y*y == z*z ]"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "0c8fbf94-4257-4d3b-9fda-693a3294c3fd",
   "metadata": {},
   "source": [
    "### Mutable and immutable values\n",
    "- Lists and dictionaries can be updated in place\n",
    "    - Can reassign `l[i]` or `d[k]`\n",
    "    - These are *mutable* values\n",
    "- Numbers (`int`, `float`), booleans, strings, tuples cannot be updated in place\n",
    "    - Immutable values"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d4373279-e990-4f41-a905-8f7855d12a78",
   "metadata": {},
   "source": [
    "### Mutability and assignment\n",
    "- Assiging a mutable value creates an *alias*\n",
    "- Updating through either the old or the new name indirectly affects the other"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "id": "2f0eb59c-9579-423b-9fdf-c7461f517144",
   "metadata": {},
   "outputs": [],
   "source": [
    "l = [1,2,3]\n",
    "newl = l\n",
    "newl[0] = 4"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "id": "85da70ff-bc70-4fe3-bbfd-3d00db2e1b2e",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "([4, 2, 3], [4, 2, 3])"
      ]
     },
     "execution_count": 23,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "l, newl"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "id": "91c2e176-ef26-4557-9c41-7116bb92968d",
   "metadata": {},
   "outputs": [],
   "source": [
    "l[1] = 5"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "id": "2cb83a9a-166a-4b37-b87c-d1dd9138ea49",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "([4, 5, 3], [4, 5, 3])"
      ]
     },
     "execution_count": 25,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "l, newl"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "7bf2f8f1-fd7b-4248-b517-dd339d800c97",
   "metadata": {},
   "source": [
    "- For immutable values, assignment behaves as we would expect\n",
    "- The two names can be updated without affecting each other\n",
    "    - It is as though assignment copies the value"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "id": "b5ad027b-e553-4404-aab1-e811aa140e41",
   "metadata": {},
   "outputs": [],
   "source": [
    "x = 17\n",
    "y = x\n",
    "y = 19"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "id": "8a51d8a0-b730-4a68-a178-70f3a12594a4",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(17, 19)"
      ]
     },
     "execution_count": 27,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "x, y"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "id": "7307a69e-70e3-40e0-af7a-3bc7f0ca7089",
   "metadata": {},
   "outputs": [],
   "source": [
    "x = 18"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "id": "1b3c3491-0b4a-4248-80f0-e12b68324686",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(18, 19)"
      ]
     },
     "execution_count": 29,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "x, y"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "fc20172e-7d1c-4129-bf82-fbfc290eedfc",
   "metadata": {},
   "source": [
    "### Mutable and immutable values\n",
    "- Lists and dictionaries are mutable\n",
    "- `int`, `float`, `bool`, `str`, tuple are immutable"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "9aa55b47-a957-4021-bd14-35b8cfb9e7b4",
   "metadata": {},
   "source": [
    "- For immutable values, assignment copies the value"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "id": "436ddc14-9f85-4872-bdbe-57d0681542b6",
   "metadata": {},
   "outputs": [],
   "source": [
    "x = 5\n",
    "y = x\n",
    "y = 7  # Does not affect the value of x"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "id": "6202f9a6-248e-4700-91e5-a54c8b502763",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(5, 7)"
      ]
     },
     "execution_count": 31,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "x,y"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "16bc5e68-c08d-496d-a208-872ddd715e05",
   "metadata": {},
   "source": [
    "- For mutable values, assigment *aliases* the new name to point to the same value as the old name\n",
    "- Updating through either name affects both"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 32,
   "id": "e8bd506c-466f-45a0-9f0c-04dac409624e",
   "metadata": {},
   "outputs": [],
   "source": [
    "l1 = [1,2,3]\n",
    "l2 = l1\n",
    "l2[0] = 4"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 33,
   "id": "24d5f326-5efb-4187-a593-e87fd2f697d5",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "([4, 2, 3], [4, 2, 3])"
      ]
     },
     "execution_count": 33,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "l1,l2"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 34,
   "id": "b178d223-0eed-4986-8456-3460ef59ff8c",
   "metadata": {},
   "outputs": [],
   "source": [
    "l1[2] = 6"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 35,
   "id": "2d1f5e33-937e-40f9-96a5-bbee63d6c961",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "([4, 2, 6], [4, 2, 6])"
      ]
     },
     "execution_count": 35,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "l1,l2"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "fe986201-b1e1-4ecc-ac72-86413cf37d76",
   "metadata": {},
   "source": [
    "### Slices and copying lists\n",
    "- A slice creates a new list\n",
    "- `l[0:len(l)]` is a faithful copy of `l`\n",
    "    - Abbreviate as `l[:]`, *full slice*\n",
    "- Assigning a full slice makes a disjoint copy of a list"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 36,
   "id": "a8cf63bb-6232-46e7-b43f-23b206a29047",
   "metadata": {},
   "outputs": [],
   "source": [
    "l1 = [1,2,3]\n",
    "l2 = l1[:]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 37,
   "id": "24d776a8-9c5c-481a-b227-96dee10df3af",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "([1, 2, 3], [1, 2, 3])"
      ]
     },
     "execution_count": 37,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "l1,l2"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 38,
   "id": "5f68ceac-dd43-4a80-9166-41101f1cdc3d",
   "metadata": {},
   "outputs": [],
   "source": [
    "l1[2] = 6\n",
    "l2[0] = 4"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 39,
   "id": "9fce6893-abc2-4ba1-bfba-1f9253796e2f",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "([1, 2, 6], [4, 2, 3])"
      ]
     },
     "execution_count": 39,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "l1, l2"
   ]
  }
 ],
 "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
}
