diff --git a/s24/AmFam_Ashwin/16_List_Practice/Lecture Code/Lec_16_List_Practice_Solution.ipynb b/s24/AmFam_Ashwin/16_List_Practice/Lecture Code/Lec_16_List_Practice_Solution.ipynb new file mode 100644 index 0000000000000000000000000000000000000000..591b5912b2f7f16de131e14668dbc27c8825b68c --- /dev/null +++ b/s24/AmFam_Ashwin/16_List_Practice/Lecture Code/Lec_16_List_Practice_Solution.ipynb @@ -0,0 +1,839 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Lists Practice" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Warmup 0: Hotkeys\n", + "\n", + "We move quickly, it's good to know some hotkeys!\n", + "\n", + "#### All-around good-to-knows...\n", + "* `Ctrl`+`A`: Select all the text in a cell.\n", + "* `Ctrl`+`C`: Copy selected text.\n", + "* `Ctrl`+`X`: Cut selected text.\n", + "* `Ctrl`+`V`: Paste text from clipboard.\n", + "* `Ctrl`+`S`: Save.\n", + "\n", + "#### Jupyter-specific good-to-knows...\n", + "* `Ctrl`+`Enter` or `Shift`+`Enter`: Run Cell\n", + "* `Ctrl`+`/`: Comment/uncomment sections of code.\n", + "* `Esc` -> `Shift`+`L`: Toggle line numbers.\n", + "* Select text -> `Tab`: Add extra level of indent.\n", + "* Select text -> `Shift`+`Tab`: Remove level of indent." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Warmup 1: Create an empty list and add elements to it" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[]\n", + "['study', 'hike', 'golf']\n" + ] + } + ], + "source": [ + "weekend_plans = [] # I have no weekend plans :(\n", + "print(weekend_plans)\n", + "\n", + "# TODO add three things to your weekend plans\n", + "weekend_plans.append(\"study\")\n", + "weekend_plans.append(\"hike\")\n", + "weekend_plans.append(\"golf\")\n", + "print(weekend_plans)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Warmup 2: Sets\n", + "\n", + "Like a **list**, a **set** is another collection. However, it is **unordered** and **unique**." + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{'study', 'hike', 'golf'}\n" + ] + } + ], + "source": [ + "my_set_of_weekend_plans = set()\n", + "\n", + "# TODO: add 4 weekend plans, 1 of which is a duplicate.\n", + "my_set_of_weekend_plans.add(\"study\")\n", + "my_set_of_weekend_plans.add(\"study\")\n", + "my_set_of_weekend_plans.add(\"hike\")\n", + "my_set_of_weekend_plans.add(\"golf\")\n", + "\n", + "print(my_set_of_weekend_plans)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### We can `pop` to remove elements, but it will remove a random item.\n", + "See: https://www.w3schools.com/python/trypython.asp?filename=demo_ref_set_pop2" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "study\n", + "{'hike', 'golf'}\n" + ] + } + ], + "source": [ + "what_removed = my_set_of_weekend_plans.pop()\n", + "\n", + "print(what_removed)\n", + "print(my_set_of_weekend_plans)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### We can `discard` a specific item!\n", + "\n", + "Unlike a list's `remove`, this will **not** throw an error if the element does not exist." + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{'golf'}\n" + ] + } + ], + "source": [ + "my_set_of_weekend_plans.discard('hike')\n", + "print(my_set_of_weekend_plans)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Copy/paste the `cell` function from the last lecture" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [], + "source": [ + "import csv\n", + "\n", + "# source: Automate the Boring Stuff with Python Ch 12\n", + "def process_csv(filename):\n", + " exampleFile = open(filename, encoding=\"utf-8\") \n", + " exampleReader = csv.reader(exampleFile) \n", + " exampleData = list(exampleReader) \n", + " exampleFile.close() \n", + " return exampleData" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [], + "source": [ + "cs220_csv = process_csv('cs220_survey_data.csv')\n", + "cs220_header = cs220_csv[0]\n", + "cs220_data = cs220_csv[1:]" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [], + "source": [ + "def cell(row_idx, col_name):\n", + " col_idx = cs220_header.index(col_name)\n", + " val = cs220_data[row_idx][col_idx]\n", + " if val == \"\":\n", + " return None\n", + " elif col_name == \"Age\" or col_name == \"Zip Code\":\n", + " return int(val)\n", + " elif col_name == \"Latitude\" or col_name == \"Longitude\":\n", + " return float(val)\n", + " else:\n", + " return val" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Warmup 4: Does the oldest basil/spinach-loving Business major prefer cats, dogs, or neither?" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "The oldest basil/spinach loving Business major prefers cat\n" + ] + } + ], + "source": [ + "oldest_idx = None\n", + "oldest_age = None\n", + "\n", + "for i in range(len(cs220_data)):\n", + " current_age = cell(i, \"Age\")\n", + " current_pizza = cell(i, \"Pizza topping\")\n", + " current_major = cell(i, \"Primary major\")\n", + " if current_age == None:\n", + " continue\n", + " \n", + " if current_pizza == \"basil/spinach\" and current_major.startswith(\"Business\"):\n", + " if oldest_idx == None or current_age > oldest_age:\n", + " oldest_age = current_age\n", + " oldest_idx = i\n", + " \n", + "print(\"The oldest basil/spinach loving Business major prefers\", cell(oldest_idx, \"Cats or dogs\"))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Warmup 5: Is their city in the United States?\n", + "\n", + "The United States has **latitudes** approximately spanning from `23.101` to `49.632`, and **longitudes** approximately spanning from `-129.306` to `-65.017`." + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "The oldest basil/spinach loving Business major is NOT in the USA\n" + ] + } + ], + "source": [ + "spinach_lat = cell(oldest_idx, \"Latitude\")\n", + "spinach_lon = cell(oldest_idx, \"Longitude\")\n", + "\n", + "if 23.101 <= spinach_lat <= 49.632 and -129.306 <= spinach_lon <= -65.017:\n", + " print('The oldest basil/spinach loving Business major is in the USA')\n", + "else:\n", + " print('The oldest basil/spinach loving Business major is NOT in the USA')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Restaurants" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[['restaurant_id', 'name', 'x_coord', 'y_coord'],\n", + " ['MCD_1', 'McDonalds', '-3', '-3'],\n", + " ['EIN_1', 'Einsteins Bagels', '1', '3'],\n", + " ['STA_1', 'Starbucks', '0', '1'],\n", + " ['MCD_2', 'McDonalds', '2', '0'],\n", + " ['GRE_1', 'Greenbush Donuts', '0', '-3'],\n", + " ['STA_2', 'Starbucks', '-2', '1'],\n", + " ['PAN_1', 'Panda Express', '', '']]" + ] + }, + "execution_count": 10, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "restaurant_csv = process_csv('restaurants.csv')\n", + "\n", + "# TODO: Display restaurant_csv. What do we call this data structure? -> list of lists\n", + "restaurant_csv" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Separate the data into 2 parts: a header row, and a list of data rows" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": {}, + "outputs": [], + "source": [ + "restaurant_header = restaurant_csv[0]\n", + "restaurant_data = restaurant_csv[1:]" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "['restaurant_id', 'name', 'x_coord', 'y_coord']" + ] + }, + "execution_count": 12, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "restaurant_header" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[['MCD_1', 'McDonalds', '-3', '-3'],\n", + " ['EIN_1', 'Einsteins Bagels', '1', '3'],\n", + " ['STA_1', 'Starbucks', '0', '1'],\n", + " ['MCD_2', 'McDonalds', '2', '0'],\n", + " ['GRE_1', 'Greenbush Donuts', '0', '-3'],\n", + " ['STA_2', 'Starbucks', '-2', '1'],\n", + " ['PAN_1', 'Panda Express', '', '']]" + ] + }, + "execution_count": 13, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "restaurant_data" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Example 1: Make a list of just the names from restaurant_data" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "['McDonalds',\n", + " 'Einsteins Bagels',\n", + " 'Starbucks',\n", + " 'McDonalds',\n", + " 'Greenbush Donuts',\n", + " 'Starbucks',\n", + " 'Panda Express']" + ] + }, + "execution_count": 14, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "names = [] # names starts out empty, we will append to it\n", + "for row in restaurant_data:\n", + " names.append(row[restaurant_header.index(\"name\")])\n", + "names" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Example 2: Extract the list of unique restaurant names " + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "['Starbucks', 'Greenbush Donuts', 'Panda Express', 'McDonalds', 'Einsteins Bagels']\n" + ] + } + ], + "source": [ + "names = list(set(names))\n", + "print(names)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Example 3: Sort the list of unique restaurant names" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Sorting Option 1: Print the sorted list without changing it" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "['Einsteins Bagels', 'Greenbush Donuts', 'McDonalds', 'Panda Express', 'Starbucks']\n" + ] + } + ], + "source": [ + "print(sorted(names))" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "['Starbucks', 'Greenbush Donuts', 'Panda Express', 'McDonalds', 'Einsteins Bagels']\n" + ] + } + ], + "source": [ + "print(names) # note that this list is still the same as earlier (i.e., before sorting)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Sorting Option 2: Sort the list and then print it" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "['Einsteins Bagels', 'Greenbush Donuts', 'McDonalds', 'Panda Express', 'Starbucks']\n" + ] + } + ], + "source": [ + "names.sort()\n", + "print(names) # note that this list itself has been modified here" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Example 4: Define a `cell` function to extract the data in `restaurant_data`\n", + "\n", + "Make sure it returns `None` if there is **missing** data. Make sure it **typecasts** appropriately depending on the **column name**." + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "metadata": {}, + "outputs": [], + "source": [ + "def cell(row_idx, col_name):\n", + " col_idx = restaurant_header.index(col_name)\n", + " val = restaurant_data[row_idx][col_idx]\n", + " if val == \"\":\n", + " return None\n", + " elif col_name == \"x_coord\" or col_name == \"y_coord\":\n", + " return int(val)\n", + " else:\n", + " return val" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Example 5: Write a function that is sent x y coordinates and returns back the `restaurant_id` of that restaurant." + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "metadata": {}, + "outputs": [], + "source": [ + "def get_restaurant_at_coordinates(search_x, search_y):\n", + " for i in range(len(restaurant_data)):\n", + " if cell(i, 'x_coord') == search_x and cell(i, 'y_coord') == search_y:\n", + " return cell(i, 'restaurant_id')" + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "EIN_1\n", + "GRE_1\n", + "None\n" + ] + } + ], + "source": [ + "print(get_restaurant_at_coordinates(1, 3)) # should be EIN_1\n", + "print(get_restaurant_at_coordinates(0, -3)) # should be GRE_1\n", + "print(get_restaurant_at_coordinates(2, -3)) # should be None" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Example 6: Write a function that is sent the restaurant ID of a restaurant and returns the x and y coordinates as a string.\n", + "\n", + "This should be **case-insensitive**." + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "metadata": {}, + "outputs": [], + "source": [ + "def get_coordinates(restaurant_id):\n", + " for i in range(len(restaurant_data)):\n", + " x_coord = cell(i, \"x_coord\")\n", + " y_coord = cell(i, \"y_coord\")\n", + " if x_coord == None or y_coord == None:\n", + " continue\n", + " if cell(i, \"restaurant_id\").lower() == restaurant_id.lower():\n", + " return \"(\" + str(x_coord) + \", \" + str(y_coord) + \")\"" + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "(0, -3)\n", + "(2, 0)\n", + "(2, 0)\n", + "None\n", + "None\n" + ] + } + ], + "source": [ + "print(get_coordinates(\"GRE_1\")) # should be (0, -3)\n", + "print(get_coordinates(\"MCD_2\")) # should be (2, 0)\n", + "print(get_coordinates(\"mcd_2\")) # should be (2, 0)\n", + "print(get_coordinates(\"PAN_1\")) # should be None\n", + "print(get_coordinates(\"ZZZ_123\")) # should be None" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Example 7: Define `get_smallest_index` to get the INDEX of the smallest value in `col_name` (such as `'x_coord'`)\n", + "\n", + "If there are ties, use the last value in the dataset." + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "metadata": {}, + "outputs": [], + "source": [ + "def get_smallest_index(col_name):\n", + " smallest = None\n", + " smallest_idx = None\n", + " for i in range(len(restaurant_data)):\n", + " curr_val = cell(i, col_name)\n", + " if curr_val == None:\n", + " continue\n", + " \n", + " if smallest == None or curr_val <= smallest:\n", + " smallest = curr_val\n", + " smallest_idx = i\n", + " return smallest_idx" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### What is the name of the restaurant farthest to the west?" + ] + }, + { + "cell_type": "code", + "execution_count": 25, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'McDonalds'" + ] + }, + "execution_count": 25, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# use `get_smallest_index` to find the answer here\n", + "\n", + "far_west_idx = get_smallest_index(\"x_coord\")\n", + "far_west_restauraunt = cell(far_west_idx, 'name')\n", + "far_west_restauraunt" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### What is the restaurant ID of the restaurant farthest to the south?" + ] + }, + { + "cell_type": "code", + "execution_count": 26, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'GRE_1'" + ] + }, + "execution_count": 26, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# use `get_smallest_index` to find the answer here\n", + "\n", + "far_south_idx = get_smallest_index(\"y_coord\")\n", + "far_south_restaurant = cell(far_south_idx, 'restaurant_id')\n", + "far_south_restaurant" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Example 8: Complete this function that computes the distance between `(x1,y1)` and `(x2,y2)`" + ] + }, + { + "cell_type": "code", + "execution_count": 27, + "metadata": {}, + "outputs": [], + "source": [ + "import math\n", + "def distance(x1, y1, x2, y2):\n", + " return math.sqrt((x1 - x2)**2 + (y1 - y2)**2)" + ] + }, + { + "cell_type": "code", + "execution_count": 28, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "5.0\n", + "1.4142135623730951\n", + "13.0\n" + ] + } + ], + "source": [ + "print(distance(0, 0, 3, 4)) # should be 5.0\n", + "print(distance(1, 2, 2, 3)) # should be square root of 2\n", + "print(distance(-3, 3, 2, -9)) # should be 13.0" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Example 9: Write a function that is sent x and y coordinates and returns the name of the closest restaurant to those coordinates.\n", + "\n", + "Use the `distance` function to calculate the distance." + ] + }, + { + "cell_type": "code", + "execution_count": 29, + "metadata": {}, + "outputs": [], + "source": [ + "def closest_restaurant(source_x, source_y):\n", + " '''return the name of the closest restaurant to the parameters given'''\n", + " closest_index = None # start with no value, to be clear if no result found\n", + " min_dist = None # why does this have to be None, not just 0? -> If closest restaurant is at (source_x, source_y), we do NOT want to skip\n", + " \n", + " for i in range(len(restaurant_data)):\n", + " current_x = cell(i, \"x_coord\")\n", + " current_y = cell(i, \"y_coord\")\n", + " if current_x == None or current_y == None: # check for missing data\n", + " continue\n", + " current_dist = distance(current_x, current_y, source_x, source_y)\n", + " \n", + " if min_dist == None or min_dist >= current_dist:\n", + " closest_index = i\n", + " min_dist = current_dist\n", + " \n", + " return closest_index # Bonus: fix this to make the function more useful -> make the function return the index instead of the name" + ] + }, + { + "cell_type": "code", + "execution_count": 30, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Einsteins Bagels\n", + "Starbucks\n", + "McDonalds\n", + "Greenbush Donuts\n" + ] + } + ], + "source": [ + "print(cell(closest_restaurant(3, 3), \"name\")) # should be Einsteins Bagels\n", + "print(cell(closest_restaurant(0, 0), \"name\")) # should be Starbucks\n", + "print(cell(closest_restaurant(5, -2), \"name\")) # should be McDonalds\n", + "print(cell(closest_restaurant(1, -2), \"name\")) # should be Greenbush Donuts" + ] + } + ], + "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.11.7" + } + }, + "nbformat": 4, + "nbformat_minor": 4 +}