Before you turn this problem in, make sure everything runs as expected. This is a combination of **restarting the kernel** and then **running all cells** (in the menubar, select Kernel$\rightarrow$Restart And Run All).

Make sure you fill in any place that says `YOUR CODE HERE`

or "YOUR ANSWER HERE".

In [ ]:

```
import os
import os.path
import io
import sys
import string
import math
from contextlib import redirect_stdout
datadir = "publicdata"
```

The following set of questions involve the `sorted()`

built-in Python function and the list of tuples:

```
students = [('bob', 'B', 19), ('chris', 'B', 18),
('chris', 'A', 18), ('alice', 'A', 19)]
```

Documentation for `sorted()`

may be found at

In [ ]:

```
students = [('bob', 'B', 19), ('chris', 'B', 18), ('chris', 'A', 18), ('alice', 'A', 19)]
```

**Q1** What is returned when `sorted()`

is invoked on the `students`

list? In this case, we are sorting a list whose elements are tuples. Describe how the algorithm used by `sorted()`

works in the case that two elements are equal in their first element.

YOUR ANSWER HERE

**Q2** Look at the documentation for `sorted()`

. If we wanted to sort the `students`

list based on the second element of the tuple (the grade), we want a function that is used to extract the "key" from a list element (tuple) to retrieve that second element. Write a function

```
getGrade(record)
```

that, given a student record that consists of a 3-tuple, accesses and returns the middle element of the record/tuple. You are welcome to define `getGrade`

as a lambda function. With this `getGrade`

function object passed as the `key`

parameter, call `sorted()`

and assign the result to the variable `gradeSorted`

.

In [ ]:

```
# Solution cell
# YOUR CODE HERE
raise NotImplementedError()
print(gradeSorted)
```

In [ ]:

```
# Testing cell
assert getGrade(('alice', 'A', 18)) == 'A'
assert getGrade(('chris', 'B', 18)) == 'B'
assert isinstance(gradeSorted, list)
assert gradeSorted[0] == ('chris', 'A', 18)
```

**Q3** Consider your result: when there are ties in the "key", do you get the elements involved in the tie in the same order as in the original list, or in different orders?

YOUR ANSWER HERE

**Q4** Write a function

```
whichIsBigger(f1,f2,n)
```

which computes `f1(n)`

and `f2(n)`

, and returns whichever function (`f1`

or `f2`

) results in the larger value when an integer `n`

is passed as a parameter. In case of a tie, return `f1`

. Test with `f1(x)`

defined as $x^3$ and `f2(x)`

defined as $5x^2+4$ and using $n=2$. Test again with $n=100$.

In [ ]:

```
# Solution cell
def whichIsBigger(f1,f2,n):
# YOUR CODE HERE
raise NotImplementedError()
def f1(x):
return x**3
def f2(x):
return 5*x*x + 4
print(whichIsBigger(f1,f2,2))
print(whichIsBigger(f1,f2,100))
```

In [ ]:

```
# Testing cell
def f1(x):
return x**3 - 7
def f2(x):
return 5*x*x + 4*x + 2
assert whichIsBigger(f1,f2,0) == f2
assert whichIsBigger(f1,f2,-10) == f2
assert whichIsBigger(f1,f2,2) == f2
assert whichIsBigger(f1,f2,50) == f1
```

**Q5** Write a lambda expression and assign it to the variable `evensquared`

such that it squares the value of its single argument if the argument is even, and *cubes* the argument if it is odd.

Afterward, for example, expression `evensquared(5)`

should yield `125`

, while `evensquared(4)`

should yield `16`

.

Hint: We need an *expression* to handle an `if`

type condition

In [ ]:

```
# Solution cell
# YOUR CODE HERE
raise NotImplementedError()
```

In [ ]:

```
# Testing cell
assert(evensquared(1)==1)
assert(evensquared(2)==4)
assert(evensquared(3)==27)
assert(evensquared(4)==16)
assert(evensquared(0)==0)
```

**Q6** Write a lambda function that takes three parameters and multiplies them together. Assign the lambda function expression to `mult3`

.

In [ ]:

```
# Solution cell
# YOUR CODE HERE
raise NotImplementedError()
mult3(10,12, 9)
```

In [ ]:

```
assert mult3(10, 12, 9) == 1080
```

**Q7** The formula for the volume of a barrel is as follows:

Where $h$=height, $D$=middle radius, and $d$=top or bottom radius.

Write a lambda expression assigned to `vol`

so that the resulting function, `vol(h,D,d)`

computes the volume of a barrel. Use `math.pi`

in your computations, not a hard-coded value for $\pi$. Be careful that your Python precedence follows the precedence of the mathematical formula.

In [ ]:

```
# Solution cell
import math
# YOUR CODE HERE
raise NotImplementedError()
```

In [ ]:

```
# Testing cell
assert(238.5<vol(8,7,4)<239)
assert(2285.4<vol(10,18,15)<2285.6)
assert(785.3<vol(10,10,10)<785.5)
assert(9691.8<vol(15,28,30)<9691.9)
```

**Mapping Functions**

Python has a built-in function `map()`

whose parameters are a function object followed by one or more iterables. If there are only two arguments, the provided first argument function (which should take a single argument) is invoked over the elements of the second argument. This gives us a built-in way to apply a unary function element-wise over a list or other sequence.

If we pass, as arguments to `map()`

, a function followed by *two* iterables, then the function is expected to have *two* parameters, and the function is called for each pair of elements coming from the first and second iterable. This gives us a built-in way to apply a binary function element-wise over two lists/vectors/sequences.

Note that, for efficiency reasons, `map()`

actually returns an *iterator* that, like `range()`

, can be used as the sequence in a `for`

statement, and waits to compute elements until needed. If we want a *list* instead of an iterator, we must pass the iterator as the argument to the `list()`

function.

**Q8** Write a function

```
incrementAge(record)
```

that, given a 3-tuple, `record`

, of a student, composed of a name, a grade, and an age, increments the age component and returns a tuple with the same name and age and the incremented age. Implement this function as a lambda function

In [ ]:

```
# Solution cell
# YOUR CODE HERE
raise NotImplementedError()
```

In [ ]:

```
# Testing cell
assert incrementAge(('chris', 'A', 18)) == ('chris', 'A', 19)
```

**Q9** Use `map()`

to apply the `incrementAge()`

function to the `students`

list, and create a list assigned to variable `students2`

.

In [ ]:

```
# Solution cell
# YOUR CODE HERE
raise NotImplementedError()
```

In [ ]:

```
# Testing cell
assert isinstance(students2, list)
assert len(students2) == 4
assert students2[-1] == ('alice', 'A', 20)
```

**Q10** Write a function

```
vector_mult(L1, L2)
```

that performs element-wise multiplication between the elements in `L1`

and `L2`

. You may assume that `L1`

and `L2`

are the same length. You *must* use `map()`

in the `vector_mult`

function, although you may write a helper function. Use lambda functions where you can (i.e. where the function can be formed as an expression).

In [ ]:

```
# Solution cell
# YOUR CODE HERE
raise NotImplementedError()
```

In [ ]:

```
# Testing cell
A = [5, 3, 1, 2]
B = [2, 1, 4, 3]
assert vector_mult(A, B) == [10, 3, 4, 6]
```