{ "cells": [ { "cell_type": "markdown", "id": "885dfde1", "metadata": {}, "source": [ "# Lesson 2: Strings and Lists" ] }, { "cell_type": "markdown", "id": "fce534d7", "metadata": {}, "source": [ "## Objectives \n", "\n", "In this lesson, we'll introduce strings, lists, and None in Python. We'll also learn the principles of documenting code. By the end of this lesson, students will be able to:\n", "\n", "* Evaluate expressions involving strings, string slicing, and lists.\n", "* Apply `str` operations and slicing to compute a new string representing the desired text.\n", "* Apply `list` operations to store, retrieve, and modify values in a list." ] }, { "cell_type": "markdown", "id": "3d7c2558", "metadata": {}, "source": [ "## Strings\n", "\n", "**Strings** are commonly used to represent text. In Python, `str` (pronounced \"stir\") represents a string. We'll refer to **string** and `str` interchangeably since we're focusing on Python programming.\n", "\n", "In Lesson 1, we saw that `str` values are defined by surrounding text in matching quotes: either a `'` or a `\"`." ] }, { "cell_type": "code", "execution_count": null, "id": "e5e7d7a8", "metadata": {}, "outputs": [], "source": [ "s1 = 'hello world'\n", "s2 = \"CSE 163 is fun!\"\n", "\n", "print(s1)\n", "print(s2)" ] }, { "cell_type": "markdown", "id": "0aaa54e1", "metadata": {}, "source": [ "Strings provide lots of ways of accessing and transforming the text data to do almost anything you want! One of the most common things you want to do with strings is to combine them. In the following snippet, we use **string concatenation** to add on one string to the end of another." ] }, { "cell_type": "code", "execution_count": null, "id": "4c57586f", "metadata": {}, "outputs": [], "source": [ "s1 = 'hello world'\n", "s2 = \"CSE 163 is fun!\"\n", "print(s1 + s2)" ] }, { "cell_type": "markdown", "id": "a21cc10b", "metadata": {}, "source": [ "The `+` operator in this context will work with two values of type `str` to create a new `str` that has the characters from the first followed by the second. Importantly, this does not modify either of `s1` or `s2`, but rather creates a *new string* that has the same characters as both of them. In fact, strings are what we call **immutable**, meaning that you can't change the characters of a particular string at all!\n", "\n", "Take a second and think about what the following code snippet should be based on this description of string concatenation before running it... Okay! Let's run it! Did it do what you expected?" ] }, { "cell_type": "code", "execution_count": null, "id": "f5e49e21", "metadata": {}, "outputs": [], "source": [ "s = 'hello world'\n", "n = 163\n", "print(s + n)" ] }, { "cell_type": "markdown", "id": "58387fc1", "metadata": {}, "source": [ "Ah, our first (intentional) error message. Python says that string concatenation is only defined between two values that are both of type `str`. To fix this, you have to explicitly turn the value `163` into a `str`! You could easily just change the code to wrap the value 163 in quotes so it is `'163'`, but that only works under a very narrow set of circumstances. Instead, we will **cast** the number into a `str` using the `str()` function." ] }, { "cell_type": "code", "execution_count": null, "id": "adc76ef2", "metadata": {}, "outputs": [], "source": [ "s = 'hello world'\n", "n = 163\n", "print(s + str(n))" ] }, { "cell_type": "markdown", "id": "8e8148f9", "metadata": {}, "source": [ "Casting works for some other kinds of type conversions as well. Most commonly in this class, you might encounter `int()` or `float()` to turn a value into an integer, or a float, respectively." ] }, { "cell_type": "markdown", "id": "96ca4f2d", "metadata": {}, "source": [ "## String indexing\n", "\n", "When we think of strings, we commonly think of them as a sequence of characters, where each character has an **index** in the string. For example, the string `'hello world'` should really be thought of as a sequence of characters in the image shown below. Each character has its own spot in the sequence, and the spots are ordered starting at index 0 going up to the end of the string.\n", "\n", "| h | e | l | l | o | | w | o | r | l | d |\n", "|---|---|---|---|---|---|---|---|---|---|----|\n", "| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |\n", "\n", "Python lets you access a character at a specific index by using this [] notation to index into the str itself. Consider the following code snippet and think about what it will print before you run it." ] }, { "cell_type": "code", "execution_count": null, "id": "5813d7fd", "metadata": {}, "outputs": [], "source": [ "s = 'hello world'\n", "print(s[0])\n", "print(s[2])\n", "print(s[10])" ] }, { "cell_type": "markdown", "id": "480bb4d4", "metadata": {}, "source": [ "Each of these goes into the string, and grabs and returns the character at the particular index.\n", "\n", "Trying to get the last character is a very common operation, so it would be annoying to have to count by hand how many characters you need to go till the end. Thankfully, Python provides a way to find the number of characters, called the **length**, of the string. If you have a `str` named `s`, then using the built-in function `len` tells you the number of characters in it.\n", "\n", "Let's try to grab that last character using the `len` function in the following snippet:" ] }, { "cell_type": "code", "execution_count": null, "id": "b6e2c365", "metadata": {}, "outputs": [], "source": [ "s = 'hello world'\n", "print('Length of string:', len(s))\n", "print('Last character:', s[len(s)])" ] }, { "cell_type": "markdown", "id": "c69e6884", "metadata": {}, "source": [ "Uh-oh. Another error. The crash this time was because we went \"out of bounds\" of the string. What went wrong? If you look at the first line of output, it actually succeeded in printing out the length. For this string, the length is `11`. So we then tried to access `s[len(s)]` which is the same as `s[11]`. See the problem here?\n", "\n", "The last valid index of this string is *10*. Even though there are 11 characters, the *valid indices go from 0 to 10*. This is precisely because the first index of the string starts at 0. To fix this, we need to ask for one index earlier in our code:" ] }, { "cell_type": "code", "execution_count": null, "id": "86a6992e", "metadata": {}, "outputs": [], "source": [ "s = 'hello world'\n", "print('Length of string:', len(s))\n", "print('Last character:', s[len(s) - 1])" ] }, { "cell_type": "markdown", "id": "5c5730e7", "metadata": {}, "source": [ "One of the cool things about Python is that the language supports **negative indexing**. Pictorally, a string can also look like this:\n", "\n", "| h | e | l | l | o | | w | o | r | l | d |\n", "|---|---|---|---|---|---|---|---|---|---|----|\n", "| -11 | -10 | -9 | -8 | -7 | -6 | -5 | -4 | -3 | -2 | -1 |\n", "\n", "To access the very last index of the string now, we can write:" ] }, { "cell_type": "code", "execution_count": null, "id": "500279b6", "metadata": {}, "outputs": [], "source": [ "s = 'hello world'\n", "print('Last character:', s[-1])" ] }, { "cell_type": "markdown", "id": "5013b2ab", "metadata": {}, "source": [ "**Food for thought:** When might negative indexing be helpful? When might positive indexing be helpful?" ] }, { "cell_type": "markdown", "id": "458338be", "metadata": {}, "source": [ "## String Slicing\n", "\n", "String indexing gets a single character from a string. How do we get multiple characters from a string? Python has a special syntax called **slicing** that enables patterned access to **substrings**: `s[start:end]`. Just like the `range` function, the `start` is inclusive and the `end` is exclusive." ] }, { "cell_type": "code", "execution_count": null, "id": "17399d4d", "metadata": {}, "outputs": [], "source": [ "s = 'hello world!'\n", "print(s[2:7])" ] }, { "cell_type": "markdown", "id": "1e37f0ab", "metadata": {}, "source": [ "The slice shown above means \"all characters starting at index 2 and up to (not including) 7\". If you take this with the picture below, it can clarify why the cell above prints `\"llo w\"`. \n", "\n", "| h | e | l | l | o | | w | o | r | l | d |\n", "|---|---|---|---|---|---|---|---|---|---|----|\n", "| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |\n", "\n", "To slice all the way from the beginning of a string to a specified (exclusive) `end`, don't specify a `start`:" ] }, { "cell_type": "code", "execution_count": null, "id": "7a75a7bd", "metadata": {}, "outputs": [], "source": [ "s = 'hello world!'\n", "print(s[:7])" ] }, { "cell_type": "markdown", "id": "3f3122fc", "metadata": {}, "source": [ "To slice all the way to the end of a string from a specified (inclusive) `start`, don't specify an `end`:" ] }, { "cell_type": "code", "execution_count": null, "id": "c468e8b4", "metadata": {}, "outputs": [], "source": [ "s = 'hello world!'\n", "print(s[2:])" ] }, { "cell_type": "markdown", "id": "41c3ea72", "metadata": {}, "source": [ "Like `range`, you can also add a `step` parameter to string slicing. What do you think will be the output below?" ] }, { "cell_type": "code", "execution_count": null, "id": "f20803e0", "metadata": {}, "outputs": [], "source": [ "s = 'hello world!'\n", "print(s[2:8:2])" ] }, { "cell_type": "markdown", "id": "6ddb7b88", "metadata": {}, "source": [ "## Looping over a String\n", "\n", "There are two ways that we can loop through the characters in a string. The first is by using the `range` function to loop over string **indices**." ] }, { "cell_type": "code", "execution_count": null, "id": "5f1bf532", "metadata": {}, "outputs": [], "source": [ "s = \"hello world\"\n", "for i in range(len(s)):\n", " print(s[i])" ] }, { "cell_type": "markdown", "id": "8cfb7563", "metadata": {}, "source": [ "Note that since `range` gives integer values, those integers are then used to access indices in the given string.\n", "\n", "The other way is looping over the characters directly using a `for` loop. Recall that `for` loops iterate over a **sequence**, and a `str` is a sequence of the characters in that string!" ] }, { "cell_type": "code", "execution_count": null, "id": "e8ef6a65", "metadata": {}, "outputs": [], "source": [ "s = \"hello world\"\n", "for c in s:\n", " print(c)" ] }, { "cell_type": "markdown", "id": "6b4760b0", "metadata": {}, "source": [ "## String Functions\n", "\n", "We have seen a simple function already that allows us to index into the string so it can return the character at that index. You can imagine this indexing as just one special function provided to us by the string (although the syntax looks different than the general notion we will show below).\n", "\n", "For example, there is also a `find` function that you can call on a string `s1`, that returns the index of a given string `s2` inside `s1`. For example, you could write the following:" ] }, { "cell_type": "code", "execution_count": null, "id": "d27c530e", "metadata": {}, "outputs": [], "source": [ "source = 'I really like dogs'\n", "target = 'll'\n", "print(source.find(target))" ] }, { "cell_type": "markdown", "id": "5fab9901", "metadata": {}, "source": [ "In this case, it prints 5 because the first occurrence of the substring `'ll'` in source appears at index `5`. Notice that we call a function on the string `source` by saying `source.(...)` where `...` are the parameters we need to pass to that function. If we were to call `target.find(source)` it would be looking for source inside `target` and would instead return -`1` (as defined in the documentation for `find`). You can try this in the code cell below." ] }, { "cell_type": "code", "execution_count": null, "id": "971b7d82", "metadata": {}, "outputs": [], "source": [ "source = 'I really like dogs'\n", "target = 'll'\n", "print(target.find(source))" ] }, { "cell_type": "markdown", "id": "bb20dd16", "metadata": {}, "source": [ "Here are some useful functions for `str`.\n", "\n", "* `s.lower()` returns a new string that is the lowercase version of `s`\n", "* `s.upper()` returns a new string that is the uppercase version of `s`\n", "* `s.find(t)` returns the index of the first occurrence of `t` in `s`. If not found, returns `-1`.\n", "* `s.strip()` returns a new string that has all the leading and trailing whitespace removed. `lstrip()` and `rstrip()` remove only left whitespace or right whitespace respectively.)\n", "* `s.split(delim)` returns a list consisting of the parts of `s` split up according to the `delim`.\n", "* `s.join(strings)` returns a single string consisting of the given strings with the string `s` inserted between each string.\n", "\n", "Because strings are **immutable**, all string functions that return a `str` return **new** strings, rather than modifying the original string `s`.\n", "\n", "Let's look more closely at the last two functions in this list.\n", "\n", "Suppose we had a string that contained a series of values separated by the `,` character, but we want to print the string out in all upper-case letters separated by `|` characters. We put `print` statements in between to make the sequence of transformations clearer and to provide comments explaining the step." ] }, { "cell_type": "code", "execution_count": null, "id": "1b801b1c", "metadata": {}, "outputs": [], "source": [ "data = 'Mercury,Venus,Earth,Mars'\n", "print('Original:', data)\n", "\n", "# Convert the data to have all upper-case letters\n", "data = data.upper()\n", "print('After upper:', data)\n", "\n", "# Split the data up by a ','. Returns a list of parts.\n", "# We will describe lists later in this reading.\n", "parts = data.split(',')\n", "print('After split:', parts)\n", "\n", "# Put those parts back together separated by a '|'\n", "data = '|'.join(parts)\n", "print('After join:', data)" ] }, { "cell_type": "markdown", "id": "962f5b27", "metadata": {}, "source": [ "Note that the `join` function doesn't add whitespace! If you want spaces between the joined strings, make sure to add it in the original string you join with:" ] }, { "cell_type": "code", "execution_count": null, "id": "4843ab48", "metadata": {}, "outputs": [], "source": [ "parts = 'Mercury,Venus,Earth,Mars'.split()\n", "data2 = ' and '.join(parts)\n", "print('After a different join:', data2)" ] }, { "cell_type": "markdown", "id": "a841f4d6", "metadata": {}, "source": [ "## Lists\n", "\n", "The `s.split(delim)` function defined in the list above introduced another data type called a **list**. Whereas a string is an indexed sequence of characters, a list is an indexed sequence that can store values of *any* type." ] }, { "cell_type": "markdown", "id": "c1026555", "metadata": {}, "source": [ "### List Operations\n", "\n", "The great thing about lists in Python, is that they share a lot of the same *syntax* for operations as strings. The following snippet shows you all of the string syntaxes we learned this lesson also applies to lists." ] }, { "cell_type": "code", "execution_count": null, "id": "3761b98d", "metadata": {}, "outputs": [], "source": [ "l = ['dog', 'says', 'woof']\n", "\n", "# Length\n", "print(len(l)) # 3\n", "\n", "# Indexing\n", "print(l[1]) # 'says'\n", "print(l[len(l) - 1]) # 'woof'\n", "\n", "# Slicing\n", "print(l[1:3]) # ['says', 'woof']\n", "print(l[:1]) # ['dog']\n", "\n", "# Looping\n", "for i in range(len(l)):\n", " print(l[i])\n", "\n", "for word in l:\n", " print(word)" ] }, { "cell_type": "markdown", "id": "7c1b8c23", "metadata": {}, "source": [ "Some key differences/things to point out:\n", "\n", "First, to specify the values of a list, the syntax uses square brackets around a comma-separated list of values (of any type)." ] }, { "cell_type": "code", "execution_count": null, "id": "3eed36ce", "metadata": {}, "outputs": [], "source": [ "l1 = ['I', 'love', 'dogs']\n", "l2 = [7, 8, 9]\n", "l3 = ['I', 3, 'dogs']" ] }, { "cell_type": "markdown", "id": "38195da7", "metadata": {}, "source": [ "Second, because this is now a `list`, not a `str`, the values returned by indexing are different. By indexing into index `0` of `l1`, it returns the value that's in that index (in this case, the str `'I'`). Similarly, when you slice into a list you get a list back (although it's shorter).\n", "\n", "**Food for thought:** How might you access the letter `'s'` from `'dogs'` in `l3`?" ] }, { "cell_type": "markdown", "id": "045db944", "metadata": {}, "source": [ "### List Assignment\n", "\n", "One way lists are able to do a bit more than strings comes from the fact that you are allowed to change the contents of a list by assigning into it. We say that lists are therefore **mutable**. Just like you can use an index to get a value out of a list, you can use an index to set a value at a particular spot." ] }, { "cell_type": "code", "execution_count": null, "id": "f269916d", "metadata": {}, "outputs": [], "source": [ "l1 = ['I', 'love', 'dogs']\n", "\n", "print(l1)\n", "\n", "l1[0] = 'You'\n", "\n", "print(l1)" ] }, { "cell_type": "markdown", "id": "8a625b37", "metadata": {}, "source": [ "## Documentation Matters!\n", "\n", "Documentation for a function communicates information about a program (such as its purpose and how to use it) to other programmers. Reading code can be hard so we want to provide some instructions people can understand. Code without documentation requires anyone trying to use your code to try and recreate what you were thinking.\n", "\n", "You can always use the `#` to leave a note in your code, but we are specifically going to talk about a special notion in Python called a **docstring** (\"doc-string\") that lets you add special documentation for a function. To do this, you use this special triple-quote string (i.e. `\"\"\" documentation \"\"\"`) as the first lines of the function." ] }, { "cell_type": "code", "execution_count": null, "id": "8e3bdf64", "metadata": {}, "outputs": [], "source": [ "def mean(a, b):\n", " \"\"\"\n", " Returns the average of a and b\n", " \"\"\"\n", " return (a + b) / 2" ] }, { "cell_type": "markdown", "id": "5f79d1f5", "metadata": {}, "source": [ "Everything that goes inside these triple-quotes now becomes the documentation for a function.\n", "\n", "Why does it help to specify this special docstring? Well Python has built-in tools to help you view the doc-strings for any function!\n", "\n", "Python provides a `help` function that lets you see the documentation for any function! For long documentation, it brings up a special viewer where you can move up/down with the keys `j/k` and you can quit with the key `q`." ] }, { "cell_type": "code", "execution_count": null, "id": "ebe9976c", "metadata": {}, "outputs": [], "source": [ "help(print)" ] }, { "cell_type": "markdown", "id": "229caa6d", "metadata": {}, "source": [ "To see how this works with code you write, suppose I wrote the function with the following docstring and asked for `help` on it." ] }, { "cell_type": "code", "execution_count": null, "id": "6c261a86", "metadata": {}, "outputs": [], "source": [ "def function_with_good_comment():\n", " \"\"\"\n", " This function does some really cool stuff\n", " \"\"\"\n", " print('Friends of the ABC')\n", "\n", "help(function_with_good_comment)" ] }, { "cell_type": "markdown", "id": "8eb02098", "metadata": {}, "source": [ "**Food for thought:** What would happen if you put everything after a `#` comment instead? Try it and see!" ] }, { "cell_type": "code", "execution_count": null, "id": "6161f163", "metadata": {}, "outputs": [], "source": [ "def function_with_good_comment():\n", " # This function does some really cool stuff\n", " print('Friends of the ABC')\n", "\n", "help(function_with_good_comment)" ] }, { "cell_type": "markdown", "id": "2c745b69", "metadata": {}, "source": [ "Every function you write should include a descriptive docstring comment! The comment should include information for the following:\n", "\n", "* The input type of the function and what the input means\n", "* The return type of the function and what the return means\n", "* The expected behavior of the function\n", "* Any special case (return `None`, empty input, etc.)\n", "\n", "Check out our [Code Quality Guide](https://courses.cs.washington.edu/courses/cse163/26wi/code_quality/) for details!" ] }, { "cell_type": "markdown", "id": "2657683e", "metadata": {}, "source": [ "### `None`\n", "\n", "Python has a special value in the language called `None` to represent the absence of a value. We sometimes use `None` to represent a result of a failed or invalid computation. (The other common way to represent a failed or invalid computation is to crash the program by raising an error.)\n", "\n", "For example, suppose we had the following `increment` function that we decided should only increment positive values. You could write code to throw an error if it was given a negative value, but it's very common in Python to instead return `None`." ] }, { "cell_type": "code", "execution_count": null, "id": "d51d4b74", "metadata": {}, "outputs": [], "source": [ "def increment(x):\n", " \"\"\"\n", " Returns the value of incrementing a non-negative value x by 1. \n", " If x is negative, returns None.\n", " \"\"\"\n", " if x < 0:\n", " return None\n", " else:\n", " return x + 1\n", "\n", "\n", "print(increment(3))\n", "print(increment(-3))" ] }, { "cell_type": "markdown", "id": "8e15dd94", "metadata": {}, "source": [ "`None` should not be confused with the value `0`! `0` is a valid number in Python (i.e. `1 + 0` is well defined to be `1`) while `None` is the absence of a number all together! If you were to run `1 + None` it would cause an error since it doesn't make sense to add 1 to something that is entirely missing!\n", "\n", "A `TypeError` or `AttributeError` can occur when manipulating a `None` value. Try modifying the code snippet to display a `TypeError` by adding a number to `None`.\n" ] }, { "cell_type": "markdown", "id": "f2af6575", "metadata": {}, "source": [ "### Checking for `None`\n", "\n", "A very common task in Python is to check if a particular value is `None` or not. Check for `None` using the `is` operator rather than the `==` operator." ] }, { "cell_type": "code", "execution_count": null, "id": "d41667e6", "metadata": {}, "outputs": [], "source": [ "def increment(x):\n", " \"\"\"\n", " Returns the value of incrementing a non-negative value x by 1. \n", " If x is negative, returns None.\n", " \"\"\"\n", " if x < 0:\n", " return None\n", " else:\n", " return x + 1\n", "\n", "\n", "x = increment(-1)\n", "if x is None: # checking for None\n", " print('Failed')\n", "else:\n", " print(x)" ] }, { "cell_type": "markdown", "id": "f6854302", "metadata": {}, "source": [ "Alternatively," ] }, { "cell_type": "code", "execution_count": null, "id": "08cf4c7d", "metadata": {}, "outputs": [], "source": [ "if x is not None:\n", " print(x)\n", "else:\n", " print('Failed')" ] }, { "cell_type": "markdown", "id": "0057a61b", "metadata": {}, "source": [ "## ⏸️ Pause and 🧠 Think\n", "\n", "Take a moment to review the following concepts and reflect on your own understanding. A good temperature check for your understanding is asking yourself whether you might be able to explain these concepts to a friend outside of this class.\n", "\n", "Here's what we covered in this lesson:\n", "\n", "* `str` indexing\n", "* `str` slicing\n", "* Looping over a `str`\n", "* `len` function\n", "* `str` functions\n", "* `list` functions\n", "* Documenting functions\n", "\n", "Here are some other guiding exercises and questions to help you reflect on what you've seen so far:\n", "\n", "1. In your own words, write a few sentences summarizing what you learned in this lesson.\n", "2. What did you find challenging in this lesson? Come up with some questions you might ask your peers or the course staff to help you better understand that concept.\n", "3. What was familiar about what you saw in this lesson? How might you relate it to things you have learned before?\n", "4. Throughout the lesson, there were a few **Food for thought** questions. Try exploring one or more of them and see what you find." ] }, { "cell_type": "markdown", "id": "2474c2ed", "metadata": {}, "source": [ "## In-Class\n", "\n", "When you come to class, we will work together on evaluating Pythonic expressions, and completing `switch_pairs.py` and `count_votes.py`. Make sure that you have a way of editing and running these files!" ] }, { "cell_type": "markdown", "id": "78990284", "metadata": {}, "source": [ "### Slices\n", "\n", "For all the following questions, assume we are using the string\n", "\n", "```python\n", "s = 'I have eaten the plums that were in the icebox'\n", "```" ] }, { "cell_type": "markdown", "id": "9fbe8d36", "metadata": {}, "source": [ "What are the values of the following slices? (You can add code cells to verify your answers!)\n", "\n", "1. `s[3:10]`\n", "2. `s[s.find('p'):]`\n", "3. `s[:s.find('t'):3]`" ] }, { "cell_type": "code", "execution_count": 1, "id": "a01e074b", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "ave eat\n", "plums that were in the icebox\n", "Ia \n" ] } ], "source": [ "s = 'I have eaten the plums that were in the icebox'\n", "\n", "print(s[3:10])\n", "print(s[s.find('p'):])\n", "print(s[:s.find('t'):3])" ] }, { "cell_type": "markdown", "id": "ff0b0cac", "metadata": {}, "source": [ "### Mystery\n", "\n", "What are the values of the elements in list `a1` after the following code executes?\n", "\n", "```python\n", "def mystery(a1, a2):\n", " for i in range(len(a1)):\n", " a1[i] += a2[len(a2) - i - 1]\n", "\n", "a1 = [1, 3, 5, 7, 9]\n", "a2 = [1, 4, 9, 16, 25]\n", "mystery(a1, a2)\n", "```\n", "\n", "(i.e., what are the values of `a1[0]`, `a1[1]`, `a1[2]`, `a1[3]`, and `a1[4]`?)\n", "\n", "You can add code cells to verify your answer!" ] }, { "cell_type": "code", "execution_count": 3, "id": "8e183607", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[26, 19, 14, 11, 10]" ] }, "execution_count": 3, "metadata": {}, "output_type": "execute_result" } ], "source": [ "def mystery(a1, a2):\n", " for i in range(len(a1)):\n", " a1[i] += a2[len(a2) - i - 1]\n", "\n", "a1 = [1, 3, 5, 7, 9]\n", "a2 = [1, 4, 9, 16, 25]\n", "mystery(a1, a2)\n", "a1" ] }, { "cell_type": "markdown", "id": "1ad37ecc", "metadata": {}, "source": [ "### `switch_pairs`\n", "\n", "For this problem, refer to the starter code in `switch_pairs.py`.\n", "\n", "Write a function named `switch_pairs` that accepts a string as a parameter and returns that string with each pair of neighboring letters reversed. If the string has an odd number of letters, the last letter should not be modified. For example, the call `switch_pairs(\"example\")` should return `\"xemalpe\"` and the call `switch_pairs(\"hello there\")` should return `\"ehll ohtree\"`.\n", "\n", "Note that this function returns a string and does not print anything. You should not make a `list` to solve this problem. You should solve it by building up a `str`." ] }, { "cell_type": "markdown", "id": "5e834109", "metadata": {}, "source": [ "### `count_votes`\n", "\n", "For this problem, refer to the starter code in `count_votes.py`.\n", "\n", "Write a function `count_votes` that takes a `list` of numbers indicating votes for candidates `0`, `1`, or `2` and returns a new list of length 3 showing how many counts each candidate got. For example:\n", "\n", "```python\n", "votes = [1, 0, 1, 1, 2, 0]\n", "result = count_votes(votes)\n", "print(result) # [2, 3, 1]\n", "```\n", "\n", "The returned list has a `2` at index `0` because a `0` appeared twice in the votes." ] }, { "cell_type": "markdown", "id": "680a6bcb", "metadata": {}, "source": [ "## Canvas Quiz\n", "\n", "All done with the lesson? Complete the [Canvas Quiz linked here!](https://canvas.uw.edu/courses/1860345/quizzes/2328974)" ] } ], "metadata": { "kernelspec": { "display_name": "cse163", "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 }