Back to courses

MATH40006 Practice Paper B Questions

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. This material's source date is 2026-08-30; it is later than the recorded activity ending 21 August 2026 and is not evidence of use during that period.

Source SHA-256: 9edd7acf80ae9c8c253a3cfe2c6142f6768698d687ac34eda725d65eee4274d5
Source date: 2026-08-30

Notes — cell 1

# MATH40006 - Introduction to Computation

## Practice Paper Paper B - Candidate question notebook

**REVIEW CANDIDATE - NOT PUBLISHED**

- Practice duration: 90 minutes
- Total: 75 marks; answer all three questions
- Work in this single Jupyter notebook.
- Use code cells for programs, tests, figures and requested output.
- Use Markdown answer cells for explanations, invariants, derivations and comments.
- No external files, network access, `input()` or package installation are required.
- Before submission, restart the kernel and run all cells from top to bottom.

The 90-minute/75-mark structure is a review assumption based on the nearest
alternative-assessment precedent and must be checked against Tony's own notice.

Code — cell 2

%matplotlib inline
import sys
import numpy as np
import matplotlib
import matplotlib.pyplot as plt
import sympy as sp
import pandas as pd
print('Environment ready:', sys.version.split()[0], 'NumPy', np.__version__, 'Matplotlib', matplotlib.__version__)
print('SymPy', sp.__version__, 'pandas', pd.__version__)

Notes — cell 3

## Question 1 (30 marks): Vectorised absorbing random walks

A walk occupies an integer in `{0,1,...,L}`. From an interior point it moves
right with probability `p` and left otherwise, stopping at `0` or `L`. The
valid contract requires positive integer `n_walks,L`, integer `x0` in `[0,L]`,
`p` in `[0,1]`, and non-negative integer `max_steps`.

**(a) [3]** With `np.random.default_rng(seed)`, demonstrate a Boolean array
encoding right/left moves for several walkers.

**(b) [10]** Write
`absorbing_walks(n_walks,L,x0,p=0.5,max_steps=10000,seed=0)`. Vectorise over
walkers and loop only over time. Return Boolean `hit_right` and integer
absorption times. Raise a clear error if active walks remain at `max_steps`.

**(c) [5]** Test shapes, fixed-seed reproducibility, non-negative times,
immediate absorption at `x0=0,L`, and invalid inputs.

**(d) [5]** For 50000 fair walks with `L=20,x0=7,seed=20260829`, estimate the
right-hit probability and mean absorption time. Compare with `x0/L` and
`x0*(L-x0)`.

**(e) [4]** Construct the stated normal-approximation 95% interval. In
Markdown, check whether `7/20` lies inside and interpret cautiously. Random
agreement must not be a pass/fail assertion.

**(f) [3]** Plot an absorption-time histogram. In Markdown, comment on its
shape and explain the `max_steps` safety contract.

Notes — cell 4

### Q1 code answers for parts (a)-(f)

Code — cell 5

# YOUR CODE HERE
raise NotImplementedError()

Notes — cell 6

### Q1 written answers for parts (d)-(f)

**YOUR ANSWER HERE**

Notes — cell 7

## Question 2 (35 marks): Horner evaluation, derivatives and Newton iteration

`[c0,...,cn]` represents `p(x)=c0*x**n+...+cn` in descending powers.

**(a) [6]** Write `horner(coefficients,x)` using `value=value*x+c`. Accept a
real scalar or real NumPy array, reject an empty list and do not mutate input.

**(b) [5]** Test a constant polynomial, vector `x`, repeated/zero coefficients
and agreement with `np.polyval`.

**(c) [4]** In Markdown, give the exact multiplication/addition counts and
Theta time; contrast with rebuilding every power by repeated multiplication.

**(d) [8]** Derive in Markdown and implement
`horner_with_derivative(coefficients,x)`, using the old polynomial accumulator
when updating the derivative.

**(e) [6]** For coefficients `[1,1,-7,-1,6]` and 601 points on `[-3,3]`,
verify `p` with `np.polyval`, verify `p'` with SymPy `diff` and `lambdify`, and
plot both.

**(f) [6]** Write guarded Newton iteration using extended Horner. Stop on a
step below `tol`; reject a near-zero derivative and exhausted `max_iter`.
Starting at `0.8`, verify the root and residual.

Notes — cell 8

### Q2 code answers for parts (a), (b), (d), (e) and (f)

Code — cell 9

# YOUR CODE HERE
raise NotImplementedError()

Notes — cell 10

### Q2 written answers for parts (c) and (d)

**YOUR ANSWER HERE**

Notes — cell 11

## Question 3 (10 marks): A pandas report for a supplied simulation log

Run the non-assessed **GIVEN SETUP** cell below unchanged. It creates a
reproducible synthetic run log, so this question has no external-file or
Question 1 dependency.

**(a) [3]** Build a DataFrame with one row per record and columns `side`
(`'left'/'right'`) and `steps`.

**(b) [4]** With `groupby` and `agg`, report count, mean, median and maximum
duration for each side. Verify counts total `report_n`.

**(c) [3]** Find the 99th percentile of `steps`, use `query` to select records
at or above it, and count by side. In Markdown, explain why this conditional
subset cannot estimate the unconditional right-side probability.

Code — cell 12

import numpy as np
import pandas as pd


# GIVEN SETUP - run this cell unchanged before Question 3.
report_rng = np.random.default_rng(4000603)
report_n = 50000
report_hit_right = report_rng.random(report_n) < 0.35
report_durations = report_rng.geometric(1 / 91.0, size=report_n)

Notes — cell 13

### Q3 code answers for parts (a)-(c)

Code — cell 14

# YOUR CODE HERE
raise NotImplementedError()

Notes — cell 15

### Q3 written answer for part (c)

**YOUR ANSWER HERE**