= [[ 22.50, 18.62, 22.04 ],
data 20.27, 19.86, 20.03 ],
[ 20.26, 17.33, 18.60 ],
[ 21.75, 15.02, 21.26 ],
[ 21.05, 13.86, 23.08 ],
[ 23.47, 11.43, 23.98 ],
[ 22.84, 9.98, 25.45 ],
[ 21.38, 9.19, 25.90 ],
[ 20.03, 11.92, 27.57 ],
[ 19.71, 10.89, 29.30 ],
[ 19.14, 11.56, 26.94 ],
[ 19.83, 11.62, 26.78 ],
[ 18.24, 12.27, 24.45 ],
[ 20.35, 14.32, 25.18 ],
[ 18.86, 16.99, 23.81 ],
[ 17.06, 19.86, 24.62 ],
[ 16.02, 19.77, 27.13 ],
[ 14.68, 19.27, 28.45 ],
[ 16.71, 17.77, 28.51 ],
[ 16.98, 20.60, 26.17 ],
[ 15.93, 19.96, 24.31 ],
[ 14.14, 19.94, 24.95 ],
[ 14.33, 21.40, 23.07 ],
[ 16.60, 21.27, 23.35 ]] [
Appendix L — Final Exam Questions
Notes:
- A PDF copy of this page can be found on the LEARN Website, attached to the “Final” Dropbox.
- This file can also be found on the course website under the Appendices section.
- A template file (
'final.py'
) can be found on the LEARN website attached to the “Final” Dropbox. This file contains empty function definitions which you should complete. - The functions MUST be named
Q1
,Q2
, …,Q12
.
- The total marks for all the questions add up to 30. The number of marks associated with each question are roughly representative of the difficulty of the question. Start with the easy ones to warm up.
- Please remove any extra code that you may have added like test calls to functions and so on.
- You are allowed to use the internet to search for help and read documentation, but you are NOT allowed to ask for help directly from a person or AI coding assistant.
- The terminals in the labs are to be used for coding, not personal laptops. These terminals have anti-cheating mechanisms in place.
When Numpy computes something for us, and the result is an ndarray
it will look like this when displayed in the interactive terminal: array([1, 2, 3])
. When the result is a scalar, however, it will look something like this: np.int64(99)
. This is the same as saying 99
, but Numpy has overwritten the __repr__
dunder method, which controls the representation of the value in the terminal. If you do print(np.int64(99))
it will give 99
which looks like a normal int
. The point is that 99
is the crucial part of the result and np.int64
is just there to remind us about the type. So in the examples below, when it says a function should return 99
, this means both 99
and np.int64(99)
are equivalent.
L.1 Question 1 (3 marks)
Write a function which accepts a string
then finds the product of all the numerical characters in the string
. The function should have an option to ignore 0’s, and if the string has no numerical values it should return None
.
def Q1(___): # Replace the ___ with your own argument(s)
r"""
Computes the product of all numerical characters in a string.
Parameters
----------
string : str
A string containing assorted characters.
ignore_zeros : bool
If this flag is True (the default) then 0's will not be included
when computing the product. If False, they are included, meaning
the product will be 0.
Returns
-------
prod : int or None
The product of multiplying all numerical characters. If the
string contains no numerical values then None is returned.
"""
# Your code here
return prod
Some examples:
'a1b2c3') # Should return 6
Q1('abcde') # Should return None
Q1('01234') # Should return 24
Q1('0a1b2', False) # Should return 0
Q1('0a1b2', True) # Should return 2 Q1(
L.2 Question 2 (2 marks)
Write a function which merges two dictionaries. In the event that both dicts
have keys in common, the function should prevent overwriting of duplicates by appending '_dupe'
to the key.
def Q2(___): # Replace the ___ with your own argument(s)
r"""
Merges two dictionaries into one, without overwriting duplicates.
Parameters
----------
a, b : dict
The two dicts to be merged.
Returns
-------
d : dict
A new dict containing all the key-value pairs from both a and b.
Note that '_dupe' will be appended to any keys in b which were
already present in a.
"""
# Your code here
return d
Here are some examples:
= {'bob': 2, 'dave': [1]}
a = {'dave': [2], 'fred': 'abc'}
b # Should return {'bob': 2, 'dave': [1], 'dave_dupe': [2], 'fred': 'abc'} Q2(a, b)
L.3 Question 3 (2 marks)
Python does not include any built-in keyword or function for determining the “exclusive or” condition. Write a function which accepts 2 boolean
values, computes the “exclusive or” and returns True
or False
accordingly. (Hint: You may need to lookup what “exclusive or” means.)
def Q3(___): # Replace the ___ with your own argument(s)
r"""
Computes the "exclusive or" between a pair of Boolean values.
Parameters
----------
a, b : bool
The two boolean values which are to be compared.
Returns
-------
xor : bool
The "exclusive or" condition for the given values.
"""
# Your code here
return xor
Creating example cases to test your logic is part of this question, so no examples are provided.
L.4 Question 4 (3 marks)
Write a function which flattens a list
containing sub-lists into a single 1D list
. The sub-lists can be of any length, and they may contain arbitrary data values (i.e. numbers, characters, etc.), but not any additional sub-lists.
def Q4(___): # Replace the ___ with your own argument(s)
r"""
Converts a list containing sub-lists into a single flattened, 1D list.
Parameters
----------
lil : list of lists
The list containing other lists.
Returns
-------
flattened : list
The flattened list.
"""
# Your code here
return flattened
Here are some examples:
1, 2, 3]]) # Should return [1, 2, 3]
Q4([[1, 2, 3], [1, 2], [1]]) # Should return [1, 2, 3, 1, 2, 1] Q4([[
L.5 Question 5 (2 marks)
Write a function that converts a list
of numerical values into a Numpy ndarray
. Assume that all the values in the list are of the same type, and ensure that the ndarray
is of that dtype
.
def Q5(___): # Replace the ___ with your own argument(s)
r"""
Converts a list to a Numpy ndarray of a corresponding shape and
suitable dtype.
Parameters
----------
vals : list
A list to be converted to an ndarray.
Returns
-------
arr : ndarray
A Numpy ndarray containing the values in vals, with a dtype that
is compatible.
"""
# Your code here
return arr
Here are some examples:
= [1+1j, 2+2j, 3+3j]
vals # Returns array([1.+1.j, 2.+2.j, 3.+3.j])
Q5(vals)
= [1, 2, 3, 4, 5, 6]
vals # Returns array([1, 2, 3, 4, 5, 6]) Q5(vals)
L.6 Question 6 (3 marks)
A chemical storage tank with a height of 7.5 m has a level sensor which outputs the height of the fluid in the tank in 1 hour intervals. The data is stored in a text file with one value on each line and no other information (not even a header row). Write a function which accepts the name of the file, then returns the number of times the level exceeded 7.0 m, which is considered dangerously close to overflowing.
def Q6(___): # Replace the ___ with your own argument(s)
r"""
Counts the number of times the values in a text file exceed a given
threshold.
Parameters
----------
filename : str
The name of the file containing the values to be checked.
threshold : float
The value above which should be counted. The default is 7.0
Returns
-------
count : int
The number of times the values in the specified text file exceeded
the given threshold limit.
"""
# Your code here
return count
The text file containing level data would look like this:
6.85
7.33
7.12
7.00
6.06
5.67
And here is an example, assuming the above data is stored in a file called data.txt
:
'data.txt', 7.0) # Should return 2 Q6(
L.7 Question 7 (2 marks)
Write a function which accepts a Numpy ndarray
filled with numerical values, and an upper and lower limit, then counts the number of values that lie on or between the limits. (Hint: True + True == 2
)
def Q7(___): # Replace the ___ with your own argument(s)
r"""
Finds the number of occurrences in arr which lie between hi and lo.
Parameters
----------
arr : ndarray
A Numpy ndarray containing values to be checked. This array can be
any shape and have any number of dimensions.
lo, hi : float
The lower and upper limits between which values in arr are counted.
Values equal to lo and hi are considered within the limits.
Results
-------
count : int
The number of values in arr that lie between lo and hi.
"""
# Your code here
return count
Some examples:
= np.array([[2, 3, 2],
arr 4, 3, 2],
[6, 4, 5]])
[3, 5) # Should return 5 Q7(arr,
L.8 Question 8 (3 marks)
Write a function which accepts an arbitrary number of Numpy ndarrays
, and plots their histograms in an “N-by-N” grid of subplots, where “N” is determined to give a square grid. It is possible that the last row is not filled. (Hint: The *args
notation collects all positional arguments received by a function and packages them into a tuple
called args
.)
def Q8(___): # Replace the ___ with your own argument(s)
r"""
Generates a Matplotlib figure containing histograms in a square
grid arrangement.
Parameters
----------
*args : ndarrays
An arbitrary of number of Numpy arrays passed as positional
arguments that are to be plotted as histograms.
Returns
-------
fig, ax
Matplotlib figure and axis handles are returned as created by
plt.subplots().
"""
# Your code here
return fig, ax
L.9 Question 9 (2 marks)
Write a function which accepts 2 Numpy ndarrays
of equal size and shape, performs matrix multiplication on them, then computes the trace of the result. Use Numpy’s linear algebra functions as needed.
def Q9(___): # Replace the ___ with your own argument(s)
r"""
Computes the trace of the matrix product of the given arrays.
Parameters
----------
a, b : ndarray
Numpy ndarrays of equal size and shape
Returns
-------
c : float
The trace of the matrix product of a and b.
"""
# Your code here
return c
Some examples:
= np.array([[1, 2, 3],
a 4, 5, 6],
[7, 8, 9]])
[= np.ones_like(a)*2
b # Should return 90 Q9(a, b)
L.10 Question 10 (2 marks)
Write a function which computes the value of a polynomial for a set of x
values given the coefficients in a tuple
arranged from low to high order terms. In other words, coeffs = (a0, a1, a2, a3)
would correspond to the following polynomial:
\[ y = a_0 + a_1x + a_2x^2 + a_3x^3 \]
def Q10(___): # Replace the ___ with your own argument(s)
r"""
Computes the y-values of a polynomial given x-values and a set of
coefficients.
Parameters
----------
x : scalar or array_like
The x-value(s) at which the polynomial should be evaluated.
coeffs : tuple of floats
A tuple containing the coefficients to use, ordered from lowest to
highest power terms. I.e., if "y = a0 + a1*x", then
"coeffs = (a0, a1)".
Returns
-------
y : scalar or array_like
The y-value(s) corresponding to the given x after applying an N-th
order polynomial.
"""
# Your code here
return y
Some examples:
= [0, 1, 2]
x = [1, 2]
coeffs # Should return array([1, 3, 5]) Q10(x, coeffs)
L.11 Question 11 (2 marks)
Write a wrapper or helper function for Numpy’s polyfit
function which accepts a Pandas DataFrame
containing columns with 'x'
and 'y'
data and the desired order of the fit, and returns a tuple
containing the fitted coefficients stored in increasing order of the term to which they belong, as defined by the following:
\[ y = a_0 + a_1x + a_2x^2 + a_3x^3 + ... \]
def Q11(___): # Replace the ___ with your own argument(s)
r"""
A wrapper function for Numpy's polyfit function that accepts data
in the form of a Pandas DataFrame
Parameters
----------
df : Pandas DataFrame
A DataFrame containing columns labelled 'x' and 'y' containing
the data to be fit. All other columns will be ignored.
order : int
The desired order of the fit. If not provided a value of 1 is
assumed.
Returns
-------
coeffs : tuple
A tuple containing each of the coefficients sorted by increasing
order of the term they belong to.
"""
# Your code
return coeffs
Some examples:
= [0, 1, 2]
x = [1, 3, 5]
y = ... # You need to figure out how to put x and y into a DataFrame
df 1) # Should return array([1., 2.]) Q11(df,
L.12 Question 12 (4 marks)
You have a 2D Numpy array where each row is the temperature taken hourly, starting at midnight and ending at 11pm, and each column is data from a new day. Write a function that finds the largest jump in hourly temperature for the entire time period. You can use Numpy’s diff
function, but be sure that you include the change between 11pm and 12am the following day. (Hint: It might be helpful to reshape the data
array, but you need to pay attention to how Numpy does the reshaping. This might require reading the documentation and experimenting in the Python terminal for a few minutes.)
def Q12(___): # Replace the ___ with your own argument(s)
r"""
Finds the absolute maximum temperature difference between adjacent
hours.
Parameters
----------
temperatures : ndarray
A 2D ndarray with rows containing hourly temperature measurements,
and columns containing measurements for a given day.
Returns
-------
maxdiff : float
The absolute maximum difference in temperatures experienced
between two adjacent hours.
"""
# Your code
return maxdiff
An example:
= np.array([[1, 10],
data 2, 11],
[3, 12],
[6, 13]])
[# Should return 4 Q12(data)