CS 111
Summer 2 2018

# Problem Set 2

due by 9:00 p.m. on Wednesday, July 04, 2018

## Preliminaries

In your work on this assignment, make sure to abide by the collaboration policies of the course.

If you have questions while working on this assignment, please come to office hours, post them on Piazza, or email `cs111-staff@cs.bu.edu`.

Make sure to submit your work on Apollo, following the procedures found at the end of the assignment.

For each problem in this problem set, we will be writing or evaluating some Python code. In today’s class, we will introduce the Python IDLE development environment.

### Problem 1: Functions with numeric inputs, part I

25 points; pair-optional See the rules for working with a partner on pair-optional problems for details about how this type of collaboration must be structured.

In this problem you will write a collection of simple functions that operate on numeric inputs.

Begin by downloading this file: `ps2pr1.py`. Open it in IDLE, following the procedure outlined in class.

Important guidelines:

• Your functions must have the exact names that we have specified, or we won’t be able to test them. Note in particular that the case of the letters matters (all of them should be lowercase), and that you should use an underscore character (`_`) wherever we have specified one (e.g., in `convert_from_inches`).
• If a function takes more than one input, you must keep the inputs in the order that we have specified.
• Each of your functions should include a docstring that describes what your function does and what its inputs are. See our example function for a model.
• Make sure that your functions return the specified value, rather than printing it. None of these functions should use a `print` statement.
• You should not use any Python features that we have not discussed in lecture or read about in the textbook.
• Your functions do not need to handle bad inputs – inputs with a type or value that doesn’t correspond to the description of the inputs provided in the problem.
• Test each function after you write it. Here are two ways to do so:
• Run your `ps2pr1.py` file after you finish a given function. Doing so will bring you to the Shell, where you can call the function using different inputs and check to see that you obtain the correct outputs.
• Add test calls to the bottom of your `ps2pr1.py` file. These will be called every time that you run the file, which will save you from having to enter the tests yourself. We have given you an example of one such test in the starter file.

Here are the descriptions of the functions:

1. (example) Write a function `opposite(x)` that takes a number `x` as its input and returns the opposite of its input. We have given you this example function in the starter file.

2. Write a function `cube(x)` that takes a number `x` as its input and returns the cube of its input (i.e., `x` raised to the power of 3). For example:

```>>> cube(2)
8
>>> print(cube(-5))
-125
```

Warning

Make sure that your function returns the correct value rather than printing it. If your function is printing the return value, you will see the word `None` as part of the output for the second test above. If you are seeing `None` in your output, you must fix your function so that it uses a `return` statement rather than a `print` statement. This same warning applies to all of the functions that you will write for this assignment.

Note: You should leave one or two blank lines between functions to make things more readable, and make sure to include a docstring like the one in our example function.

Warning

Make sure that you use the correct amount of indentation. In particular, your docstrings should be indented by 4 spaces as shown in our code for `opposite`, so that they line up with the code inside the function.

3. Write a function `slope(x1, y1, x2, y2)` that takes four numeric inputs that specify the coordinates of two points `(x1, y1)` and `(x2, y2)` in the Cartesian plane, and that returns the slope of the line formed by those two points. Recall that slope is given by the following formula:

```         y2 - y1
slope = ---------
x2 - x1
```

If `x1` and `x2` are the same (meaning the line is vertical, and thus the slope is undefined), the function should execute the following line:

```return float('nan')
```

This line will cause the function to return a special value called `nan` to indicate that the result is not a number (which is what `nan` stands for!).

Examples:

```>>> slope(2, 3, 4, 7)     # line between (2,3) and (4,7)
2.0
>>> slope(7, 2, 3, 4)     # line between (7,2) and (3,4)
-0.5
>>> print(slope(2, 3, 5, 3))
0.0
>>> slope(2, 5, 2, -3)    # vertical line (both x values are 2)
nan
```

Note: In Python, if you divide `0` by a negative number using the `/` operator, the result is `-0.0`. You don’t need to worry if your `slope` function returns `-0.0` for cases in which the slope is 0.

4. Write a function `make_change(cents)` that takes a nonnegative integer `cents` that represents an amount of money in cents and returns a list of four integers in which that amount has been broken up into quarters, dimes, nickels, and pennies. Although there are many ways to make change for a given number of cents, the values returned by the function should minimize the total number of coins. For example:

```>>> make_change(347)         # 347 cents = 13 quarters, 2 dimes, 0 nickels, 2 pennies
[13, 2, 0, 2]
>>> print(make_change(84))   # 84 cents = 3 quarters, 0 dimes, 1 nickel, 4 pennies
[3, 0, 1, 4]
```

Here’s the beginning of one possible template that you could use:

```def make_change(cents):
"""
quarters =                  # number of quarters
cents =                     # leftover number of cents
dimes =                     # number of dimes
cents =                     # leftover number of cents
return [quarters, dimes, nickels, pennies]
```

Hint: The integer division (`//`) and modulus (`%`) operators will come in handy for this problem.

Don’t forget to test your functions using the approaches mentioned at the start of the problem.

You may also find it helpful to use the Python Tutor Visualizer to trace through the execution of your functions – either to verify that they’re working as expected, or to determine why they’re not working! Paste your function definition into the Visualizer’s code box, and follow the definition with code that calls the function. Then click the Visualize Execution button below the code box to begin the visualization. For example, to test the `circle_area` function that we discussed in lecture, you could paste the following into the Visualizer:

```def circle_area(diam):
return area

test = circle_area(10)
print('test is', test)
```

### Problem 2: Tracing program execution

10 points; individual-only

Try to do this part before class!

Create a new text file called `ps2pr2.txt`, and save your work in this program into that file.

1. Consider the following Python program:

```x = 11
y = 5
x = x + 6
z = y + x
x = x // 7
y = z % 3
```

Copy the table shown below into your text file for this problem, and fill in the missing values to illustrate how the values of the variables change over the course of the program. We’ve given you the values of the variables after the first two lines of code. You should complete the remaining rows of the table.

```line of code   | x  | y  | z  |
--------------------------------
x = 11         | 11 |    |    |
y = 5          | 11 | 5  |    |
x = x + 6      |    |    |    |
z = y + x      |    |    |    |
x = x // 7     |    |    |    |
y = z % 3      |    |    |    |
```
2. Consider the following Python program:

```def foo(a, b):
b = b - 2
a = a - b
print('foo', a, b)
return a

a = 7
b = 4
a = foo(a, b)
print(a, b)
foo(b, a)
print(a, b)
```

• a table for the variables in the global scope that illustrates how their values change over time. You can begin it as follows:

```  a  |  b
-----------
7  |  4
```
• one or more separate tables that illustrate the changes in the local variables that belong to the function `foo`; you can either use a different table for each function call, or one table for the function as a whole

• a separate section that specifies the output of the program (i.e., the values that are printed).

### Problem 3: Tracing function calls

10 points; individual-only

Try to do this part before class!

Put your answers for this problem in a plain-text file named `ps2pr3.txt`.

1. Consider the following Python program:

```def decide(a, b, c):
if a <= c:
if b > c:
a = a * 3
else:
b = b + 4
elif b >= c:
if b == a:
c = c + 2
else:
a = a + 3
b = b * 5
print('decide', a, b, c)
return b

a = 1
b = 3
c = 2
decide(a, b, c)
print(a, b, c)
c = decide(b, a, a)
print(a, b, c)
```

• a table for the variables in the global scope that illustrates how their values change over time. You can begin it as follows:

```  a  |  b  |  c
-----------------
1  |  3  |  2
```
• one or more separate tables that illustrate the changes in the local variables that belong to the function; you can either use a different table for each function call, or one table for the function as a whole

• a separate section that specifies the output of the program (i.e., the values that are printed).

2. Consider the following Python program:

```def foo(a):
b = bar(a) + bar(a - 2)
print('foo:', a, b)
return b

def bar(b):
a = b * 2
print('bar:', a, b)
return a

a = 3
b = 2
bar(b)
print(a, b)
a = foo(a)
print(a, b)
```

Trace the execution of this program. Your answer should include the same components specified above for the first part of the problem. Make sure to include separate tables for each function.

### Problem 4: Functions with numeric inputs, part II

5 points; pair-optional
See the rules for working with a partner on pair-optional problems for details about how this type of collaboration must be structured.

This problem involves more practice in writing functions.

In IDLE, use the File -> New Window menu option to open a new editor window for your program, and save it using the the name `ps2pr4.py`. Make sure to specify the `.py` extension.

1. Write a function `compare(num1, num2)` that takes two numeric inputs `num1` and `num2` and returns a value that is based on how the numbers compare. More specifically, it should:

• return `1` if `num1` is greater than `num2`

• return `-1` if `num1` is less than `num2`

• return `0` if `num1` is equal to `num2`

Here are some examples of how it should work:

```>>> compare(5, 2)
1
>>> compare(2, 5)
-1
>>> print(compare(2, 2))
0
```

### Problem 5: Functions on strings and lists, part I

25 points; individual-only

This problem involves more practice in writing functions.

In IDLE, use the File -> New Window menu option to open a new editor window for your program, and save it using the the name `ps2pr5.py`. Make sure to specify the `.py` extension.

Include comments at the top of the file that are similar to the ones that we gave you at the top of `ps2pr1.py`.

Follow the same guidelines that we gave you for problem set 1.

1. Write a function `front3(s)` that takes an input string `s` and follows the specifications given in the problem of that name on the CodingBat website. Here is a screenshot of the problem:

Write this function in your `ps2pr5.py` file. In addition, we encourage you to try entering your function into the CodingBat website, because it will test your function for you. (Note: You may need to remove your docstring when testing the function on CodingBat.)

In general, CodingBat is a great way to reinforce what you have learned. If you would like some additional practice on the material that we’ve covered thus far, you can find some (entirely optional!) additional problems here.

2. Write a function `reverse(values)` that takes a list `values` and returns a new list in which the elements from `values` have been reversed. Here are some examples:

```>>> reverse([1, 2, 3, 4])
[4, 3, 2, 1]
>>> reverse(['hello', 'world'])
['world', 'hello']
>>> print(reverse([0, 5, 10]))
[10, 5, 0]
```

Hint: Use skip-slicing!

Warning

Remember that your functions should return the correct value rather than printing it. If your function is printing the return value, you will see the word `None` as part of the output for the last test above. If you are seeing `None` in your output, you must fix your function so that it uses a `return` statement rather than a `print` statement. This same warning applies to all of the functions that you will write for this assignment.

Remember that you should not use Python features that we have not discussed in lecture. In particular, you should not use the built-in Python `reverse` method!

3. Write a function `ends_with(word, suffix)` that takes as inputs two string values `word` and `suffix`, and that returns `True` if the string `word` ends with the string `suffix`, and `False` otherwise. For example:

```>>> ends_with('computer', 'ter')
True
>>> ends_with('computer', 'tar')
False
>>> ends_with('begin', 'in')
True
>>> print(ends_with('begin', 'on'))
False
```

Warning

Your function should return a boolean value – either `True` or `False`, without any quotes around them.

Remember that you should not use Python features that we have not discussed in lecture. In particular, you should not use the built-in Python `endswith` method!

Hint: Begin by computing the length of `suffix` and storing it in an appropriately named variable. Then use that variable as part of a test to determine if `word` ends with `suffix`.

4. Write a function `has_vowel(s)` that takes as input a string `s` and returns `True` if `s` contains at least one vowel (`a`, `e`, `i`, `o`, or `u`), and `False` otherwise. For example:

```>>> has_vowel('computer')
True
>>> print(has_vowel('wxyz'))
False
```

You may assume that `s` contains only lower-case letters, which means that you do not need to worry about upper-case vowels like `A` or `E`.

Hint: Use the `in` operator, which allows you to test for the presence of one string in another. For example:

```>>> word = 'python'
>>> 't' in word          # 'python' does have a 't'
True
>>> 'b' in word          # 'python' does not have a 'b'
False
```

Don’t forget to test your functions using the approaches mentioned at the start of Problem 3. You may also find it helpful to use the Python Tutor visualizer to trace through the execution of your functions, as described at the end of Problem 3.

### Problem 6: Functions on strings and lists, part II

25 points; individual-only

This problem involves more practice in writing functions.

In IDLE, use the File -> New Window menu option to open a new editor window for your program, and save it using the the name `ps2pr6.py`. Make sure to specify the `.py` extension.

Follow the same guidelines that we gave you for problem 5.

1. Write a function `mirror(s)` that takes as input a string `s` and returns a mirrored version of `s` that is twice the length of the original string. For example:

```>>> mirror('bacon')
'baconnocab'
>>> print(mirror('XYZ'))
XYZZYX
```

Hint: Use skip-slicing!

2. Write a function `front_back(values)` that takes a list `values` as input and returns a new list in which the first and last elements of the original list have been exchanged. For example:

```>>> front_back([0, 2, 4, 6, 8])
[8, 2, 4, 6, 0]
>>> print(front_back(['a', 'b', 'c', 'd']))
['d', 'b', 'c', 'a']
```

Note that you will need a special case for lists with fewer than two elements, since those lists should be left unchanged:

```>>> front_back([1])
[1]
```
3. Write a function `replace_prefix(word, n, prefix)` that takes as inputs a string `word`, an integer `n`, and a string `prefix`, and that returns a string in which the first `n` characters of `word` have been replaced by `prefix`. For example:

```>>> replace_prefix('undo', 2, 're')
'redo'
```

In the above example, the second input is `2`, so we replace the first 2 characters of `'undo'` with `'re'`. Note, however, that the number of characters in the new `prefix` does not need to be the same as the number of characters being replaced:

```>>> replace_prefix('protagonist', 3, 'an')
'antagonist'
>>> print(replace_prefix('autocrat', 4, 'techno'))
technocrat
```

Special case: If `n` (the second input) is larger than the length of `word` (the first input), then the function should simply return the original `word` without changing it:

```>>> replace_prefix('undo', 5, 're')    # 5 > len('undo')
'undo'
```

Warning

Remember that you should not use Python features that we have not discussed in lecture. In particular, you should not use the built-in Python `replace` method!

4. Write a function `swap_halves(s)` that takes a string input `s` and returns a string whose first half is `s`‘s second half and whose second half is `s`‘s first half. If `len(s)` (the length of `s`) is odd, the first half of the input string should have one fewer character than the second half, and thus the second half of the output string will be one character shorter in such cases. For example:

```>>> swap_halves('homework')
'workhome'
>>> print(swap_halves('carpets'))
petscar
```

Hint: We strongly recommend computing `len(s)//2` (using the integer-division operator `//`) and storing the result in an appropriately named variable. You will need to use that value twice in your function, and using the variable in both places with save you from recomputing it.

Don’t forget to test your functions using the approaches mentioned at the start of Problem 2. You may also find it helpful to use the Python Tutor Visualizer to trace through the execution of your functions, as described at the end of Problem 2.

You should use Apollo to submit the following files:

• your modified `ps2pr1.py` file containing your solutions for Problem 1 if you worked with a partner, make sure that you each submit a copy of your joint work, and that you include comments at the top of the file specifying the name and email of your partner
• your `ps2pr2.txt` file containing your solutions for Problem 2
• your `ps2pr3.txt` file containing your solutions for Problem 3
• your `ps2pr4.py` file containing your solutions for Problem 4
• your `ps2pr5.py` file containing your solutions for Problem 5
• your `ps2pr6.py` file containing your solutions for Problem 6

Warnings

• Make sure to use these exact file names, or Apollo will not accept your files. If Apollo reports that a file does not have the correct name, you should rename the file using the name listed in the assignment or on the Apollo upload page.

• If you make any last-minute changes to one of your Python files (e.g., adding additional comments), you should run the file in IDLE after you make the changes to ensure that it still runs correctly. Even seemingly minor changes can cause your code to become unrunnable.

• If you submit an unrunnable file, Apollo will accept your file, but it will print a warning message. If time permits, you are strongly encouraged to fix your file and resubmit. Otherwise, your code will fail most if not all of our tests.

Here are the steps:

Note: If you encounter problems with Apollo, close your browser and try again. If possible, you may also want to wait an hour or two before retrying. If you are unable to submit and it is close to the deadline, email your homework before the deadline to `cs111-staff@cs.bu.edu`.