MATH40006 Practice Paper 3
English review edition prepared on 4 October 2026 from a preserved source copy. It is a later presentation, not the historical study interface. Source checks and difficulty judgements describe the original material author's own process; they do not indicate Imperial College London endorsement.
Source SHA-256: d57867278a2aa68e4fcd3638e8e79e36c7820fdfa4f9d578c1ca1cd820cc36c0Source date: 2026-08-06
Notes — cell 1
# MATH40006 Revised Historical-Coverage Mock 3 **Time allowed:** 60 minutes **Total marks:** 50 **Questions:** 3 (20 + 20 + 10) **Role:** 2023-24 historical ability: prime algorithms, recursion and lexicon data Answer all questions in this Jupyter notebook. Show testing code and outputs. Unless the question explicitly requests an in-place operation, functions should return a value without changing their inputs.
Code — cell 2
import numpy as np
import sympy as sp
import matplotlib.pyplot as plt
import pandas as pd
from time import perf_counter
from copy import copy
import pickle
import ast
import math
sp.init_printing()
def primes_numpy(n):
pos=np.ones(n+1,dtype=bool); pos[:2]=False
for p in range(2,int(np.sqrt(n))+1):
if pos[p]: pos[p*p::p]=False
return np.arange(n+1)[pos]
mini=[{'word':'Alpha','description':'first'}, {'word':'Beta','description':'second'}, {'word':'Delta','description':'change'}, {'word':'Gamma','description':'third'}]
with open('mini_lexicon.dat','w',encoding='utf-8') as f: f.write(repr(mini))
Notes — cell 3
## Question 1 (20 marks) The supplied `primes_numpy` implements the Sieve of Eratosthenes. (a) Test it for a prime upper bound, a composite upper bound and a square of a prime. **[3]** (b) Write in-place `conditional_append(primes,p)`, testing divisors only up to sqrt(p). **[5]** (c) Test both append and no-append branches. **[3]** (d) Write `primes_incremental(n)` starting with `[2]` and testing odd candidates only. **[4]** (e) Check equality with `primes_numpy` for several values. **[2]** (f) Use `perf_counter` for a fair comparison at `n=100000`. **[2]** (g) Give one cautious sentence explaining the observed difference. **[1]**
Code — cell 4
# YOUR CODE HERE raise NotImplementedError()
Notes — cell 5
## Question 2 (20 marks) Define recursively, for positive integers, `s3(n)=n` when `n<3`, and otherwise ` s3(n)=s3(n//3)+(n%3)`. (a) Implement `s3` recursively and return an int. **[4]** (b) Test at least four values including 1, 8 and 2026. **[2]** (c) Produce a point plot for 1 to 500. **[2]** (d) Write `ternary_digits(n)` and `list_crush(lis)`, where the latter replaces each maximal run of equal elements by one copy. **[5]** (e) Verify for 1 to 500 that `s3(n)` equals the sum of the ternary digits, and separately demonstrate `list_crush` on a non-trivial list. **[4]** (f) Give a Theta bound for the recursive running time in terms of n. **[3]**
Code — cell 6
# YOUR CODE HERE raise NotImplementedError()
Notes — cell 7
## Question 3 (10 marks) Execute the setup cell, which creates `mini_lexicon.dat` as text representing a list of dictionaries. (a) Read the file as text and parse it safely with `ast.literal_eval`. **[2]** (b) Build a list of `(word,description)` tuples. **[1]** (c) Write and test a sequential lookup that returns `'failed'` when absent. **[3]** (d) Convert the same data to a dictionary and a pandas Series. **[2]** (e) Verify all three structures agree for a hit and handle a miss. **[2]**
Code — cell 8
# YOUR CODE HERE raise NotImplementedError()