Skip to content

← Final exam model papers

Final Exam Model Paper 4

Theory paper: 50 marksTime: 2 hours

Practical exam: 20 marksTime: 1 hour 30 minutes

All questions are compulsory.

A full practice run of the Grade 12 final exam: the theory paper (50 marks, 2 hours) and, below it, the practical exam (20 marks, 1 hour 30 minutes, at a computer, marked by the school). In the theory paper, work out on paper what each program does, as in the exam hall: its programs have no Run button. In the practical exam, the programs run on this page.

A practice paper by Science Playground, made to its own course’s grid; not an official exam paper.

Write your answers on paper first. Then open each answer and its marking scheme, and give yourself one mark for each point you got. In multiple choice, your first choice counts.

Section A

10 × 1 = 10

1. Choose the correct option for each of the following questions.

a.

What does it mean for a programming language to be Turing complete?

Pick an answer to see why.

b.

Ankit’s program has a while loop, and he asks whether it will always stop. His friend says, “The halting problem proves that nobody can ever tell whether a loop stops.” Which judgment is right?

Pick an answer to see why.

c.

What does git add do?

Pick an answer to see why.

d.

When a payment arrives in a shop’s app, it must print a receipt, update the stock and send the customer an SMS; next year it may also need to send the payment to the accounts program. The payment code keeps a list of functions that asked to be told, and calls each of them. Which design pattern is this?

Pick an answer to see why.

e.

A load balancer that uses round robin sends each new request…

Pick an answer to see why.

f.

A school’s website runs on three app servers behind a load balancer. After signing in, students are sometimes asked to sign in again when they open the next page. What is the most likely cause?

Pick an answer to see why.

g.

The computers in a data center use 2 MW of power, and the center’s PUE is 1.4. How much power does the whole center use, and how much of it goes to cooling and everything else?

Pick an answer to see why.

h.

What is a hardware security module?

Pick an answer to see why.

i.

In key exchange, why does Sita send gᵃ mod p, and not g × a mod p?

Pick an answer to see why.

j.

Students in Dolakha send four proposals to their municipality about its new AI chatbot. Which is a proposal the municipality could adopt and check?

Pick an answer to see why.

Section B

8 × 3 = 24

Write short answers to the following questions.

2.
[3]

A school in Dhading writes its roll numbers by this grammar:

<roll>    ::= <grade> - <section> - <number><grade>   ::= 9 | 10<section> ::= A | B | C<number>  ::= <digit> <digit><digit>   ::= 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9
  • i.For each of 10-B-07, 9-D-12 and 9-A-5, say whether it fits the grammar, and why.
  • ii.A teacher wants to write several roll numbers on one line, separated by commas, such as 9-A-05,10-C-31. Add a rule <list>, using itself, for one or more roll numbers.
  • iii.The grammar for arithmetic can’t be checked by a regular expression, but this one, with your <list>, can. Why?
Answer
  • i.10-B-07 fits: 10 is a <grade>, B a <section>, and 07 two digits. 9-D-12 doesn’t: D is not one of A, B or C. 9-A-5 doesn’t: <number> needs two digits.
  • ii.<list> ::= <roll> | <roll> , <list>
  • iii.Arithmetic’s grammar uses itself inside brackets, to any depth, so a checker must remember how many brackets are still open: no fixed number of states can. Here <list> uses itself only at the end: after each roll number the checker needs to remember nothing but where it is in one roll number, so a finite state machine with a loop back for each comma does it, such as (9|10)-[ABC]-\d\d(,(9|10)-[ABC]-\d\d)*.
Marking scheme
  • i. All three judged correctly, each with its reason.
  • ii. <list> ::= <roll> | <roll> , <list> (or the same with <list> first).
  • iii. Nothing is nested inside brackets: the rule repeats only at the end, so a fixed number of states (a loop) is enough, unlike brackets of any depth.
3.
[3]

A ward office in Arghakhanchi lists the applications for the senior citizens’ allowance as (name, age, ward):

applicants = [("Hari", 74, 3), ("Sita", 81, 1), ("Bal", 68, 3), ("Gita", 77, 1), ("Ram", 70, 2)]

Write one line of Python for each, using sorted with a key:

  • i.the applicants from the oldest to the youngest;
  • ii.the applicants by ward, and by name within a ward.
  • iii.Why is passing the key to sorted an example of the strategy pattern?
Answer
applicants = [("Hari", 74, 3), ("Sita", 81, 1), ("Bal", 68, 3), ("Gita", 77, 1), ("Ram", 70, 2)]print(sorted(applicants, key=lambda a: a[1], reverse=True))print(sorted(applicants, key=lambda a: (a[2], a[0])))

Output

[('Sita', 81, 1), ('Gita', 77, 1), ('Hari', 74, 3), ('Ram', 70, 2), ('Bal', 68, 3)][('Gita', 77, 1), ('Sita', 81, 1), ('Ram', 70, 2), ('Bal', 68, 3), ('Hari', 74, 3)]

iii. The sorting itself never changes; only the way of comparing applicants, the part that varies, is passed in as a function. Any new order (by name, by ward then age) is a new key, with no change to sorted: that is the strategy pattern, “keep what varies apart from what stays the same”.

Marking scheme
  • i. sorted with key=lambda a: a[1] and reverse=True.
  • ii. sorted with key=lambda a: (a[2], a[0]).
  • iii. The comparing is passed in as a function while the sorting stays the same: the strategy pattern.
4.
[3]

Two projects:

  • Project 1: a municipality’s property tax program. The rates are fixed by the Finance Act and must work from the first day of Shrawan.
  • Project 2: an app for students of a school in Achham to share their notes. Nobody is sure yet what the students will want.
  • i.Which suits the waterfall model better, and why?
  • ii.Which suits an agile method better, and why?
  • iii.Give one risk of using the waterfall model for Project 2.
Answer
  • i.Project 1: the requirements are known exactly, written in law, and won’t change during the project, so they can be written and signed first, then designed, built and tested in order, with documents an auditor can check.
  • ii.Project 2: the needs will only become clear as students try it. Short rounds (sprints), each ending with a working version that students try, let the team learn and change direction early.
  • iii.The team could spend months building, to a plan written at the start, an app that students turn out not to want, and find out only at the end, when changing it is slow and costly.
Marking scheme
  • i. Project 1, because its requirements are fixed and known in advance.
  • ii. Project 2, because its needs are unclear and will be learned from working versions.
  • iii. A real risk: building the wrong thing and discovering it too late to change cheaply.
5.
[3]

On SEE results day, the results website can serve 5,000 requests a second, but 50,000 a second arrive in the first minutes.

  • i.What happens if the site simply tries to answer everyone?
  • ii.How does a waiting room, or turning requests away at once with “503: please try again in a minute”, help?
  • iii.Give one other way to make the site cope.
Answer
  • i.The queues grow without limit: everyone waits, requests time out, people press refresh, which adds more requests, and the servers may fail altogether. Nobody gets a result.
  • ii.The site serves the 5,000 a second it can well, and tells the rest at once to wait, or lets them in a few at a time with their place in the line, so those served get their results quickly and nobody waits on a page that will never come. It is better to serve some people well than everyone badly.
  • iii.Any one, for example: cache the results (they don’t change once published), or put them on a content delivery network’s edge servers; add servers before the day (autoscaling, tested with a load test); publish each school’s results as plain pages that need no database.
Marking scheme
  • i. Everyone waits, requests time out and retries add more load: nobody is served.
  • ii. Shedding load or a waiting room serves what the site can handle quickly and tells the rest at once.
  • iii. A sensible other way (caching, a CDN, more servers planned and load-tested in advance).
6.
[3]

A shop in Damak reminds customers who owe it money by SMS. It sends 500 customers the old message (A) and 500 a new one with the due date (B). Within a week, 250 of group A pay (50%) and 290 of group B (58%). A shuffle test with 20,000 shuffles gives a p-value of about 0.013.

  • i.State the null hypothesis.
  • ii.What did the shuffle test do?
  • iii.What does p ≈ 0.013 mean? Say one thing it does not mean.
Answer
  • i.The message makes no difference: each customer would have paid (or not) whichever message they got, and the difference of 40 is chance.
  • ii.It dealt the 1,000 customers, with whether each paid, out again at random into two groups of 500, many times, as if the messages made no difference, and counted how often the shuffled groups differed by 40 or more either way.
  • iii.If the message made no difference, a difference this big would turn up by chance only about 13 times in 1,000: rare, so the result is evidence that message B works (significant at 5%). It does not mean there is a 1.3% chance that B makes no difference (or a 98.7% chance that B works), and it says nothing about whether 8 points matters to the shop.
Marking scheme
  • i. The messages make no difference; the gap is chance.
  • ii. Deal everyone out at random again many times and count how often the difference is at least 40.
  • iii. Chance alone would rarely give this (about 13 in 1,000), with a correct “does not mean”.
7.
[3]

A municipality in Kapilvastu plans to publish a spreadsheet of every household, with names and house numbers removed, for researchers to study poverty. Each row gives the ward, the caste, the number of family members, the land owned, the yearly income, and how many family members work abroad. Judge the plan, and suggest a better one.

Answer

Removing names doesn’t make it anonymous. In a ward of a few hundred households, a mix such as caste, family size and land owned often fits only one household, which neighbors could recognize. As with Netflix’s ratings, a few facts known from elsewhere pick out a whole row. The rows then reveal private facts: income, and who has family abroad, which tells thieves and moneylenders which houses receive money from abroad.
A better plan: publish only totals for groups big enough to hide any one household (by ward, or by caste across the municipality); or add a little random noise to each total (differential privacy); give the full rows only to approved researchers who sign an agreement, on the office’s own computers; and collect and keep only the columns the study needs (data minimization), telling households what is collected and why.

Marking scheme
  • Removing names isn’t enough: a few columns together can pick out a household (re-identification).
  • The harm: private facts such as income and remittances exposed to neighbors, thieves or lenders.
  • A better plan: totals for large groups, noise (differential privacy), controlled access, or collecting only what is needed.
8.
[3]

For a computer club demonstration, Karuna publishes a tiny RSA public key, (n, e) = (51, 3), and her friend sends her the ciphertext c = 13. Eve sees both, and shows the club how weak so small a key is.

  • i.Factor n, and work out φ(n).
  • ii.Find the private power d: the number with 3 × d one more than a multiple of φ(n).
  • iii.Decrypt c = 13 by repeated squaring, as Eve can now. Show each step.
Answer
  • i.Trying small primes: 51 ÷ 2 doesn’t divide; 51 = 3 × 17. φ(n) = (3 − 1)(17 − 1) = 2 × 16 = 32.
  • ii.One more than a multiple of 32: 33, 65, 97… 33 = 3 × 11, so d = 11 (3 × 11 = 33 = 32 + 1).
  • iii.m = 13¹¹ mod 51, and 11 = 8 + 2 + 1:
  • 13² = 169 ≡ 16 (169 − 153)
  • 13⁴ ≡ 16² = 256 ≡ 1 (256 − 255)
  • 13⁸ ≡ 1² = 1
  • 13¹¹ = 13⁸ × 13² × 13 ≡ 1 × 16 × 13 = 208 ≡ 4 (208 − 204)

The message was 4. (Check: 4³ = 64, and 64 mod 51 = 13.) With a real n, hundreds of digits long, the first step, factoring, is out of reach, and so is everything after it.

Marking scheme
  • i. n = 3 × 17 and φ(n) = 32.
  • ii. d = 11, because 3 × 11 = 33 = 32 + 1.
  • iii. 13¹¹ mod 51 = 4, by repeated squaring with the steps shown.
9.
[3]

Name three of the general principles of the ACM Code of Ethics, and say in plain words what each asks of a computing professional.

Answer

Any three, for example:

  • Contribute to society and to human well-being: use your skills for everyone’s good, giving more weight to those less advantaged.
  • Avoid harm: think about everyone your work affects, and report signs of risk.
  • Be honest and trustworthy: tell people what a system can’t do; no false claims or faked data.
  • Be fair and take action not to discriminate: check that your work treats all groups fairly.
  • Respect the work required to produce new ideas: credit others, and respect copyright and licenses.
  • Respect privacy: collect only the data needed, for a clear purpose, and protect it.
  • Honor confidentiality: keep secret what you were trusted with, unless it is evidence of breaking the law or the Code.
Marking scheme
  • A first principle, with what it asks.
  • A second principle, with what it asks.
  • A third principle, with what it asks.

Section C

2 × 8 = 16

Write long answers to the following questions.

10.
[8]

A cooperative’s field officer starts at the head office in Tamghas, visits each of four branches once to check their accounts, and returns. These are the distances between the places, in km. (The distances are made up for this question: they are not the real distances between these places.)

Tamghas Ridi Wami Taksar Purtighat Isma
Tamghas 14 9 5 7
Ridi 14 20 13 21
Wami Taksar 9 20 7 4
Purtighat 5 13 7 8
Isma 7 21 4 8
  • i.How many different round trips are there? Explain. (1)
  • ii.Use the nearest next heuristic from Tamghas. Write the round trip and its length. (2)
  • iii.Reverse the order of the first three branches on your trip, and work out the new round trip and its length. Why is it shorter? (2)
  • iv.How could the officer be sure which round trip is the shortest? Why can’t the cooperative do the same for a trip through its 30 branches, and what should it do instead? (3)
Answer

i. With the start fixed, the 4 branches can be visited in 4 × 3 × 2 × 1 = 24 orders, and each round trip is counted twice, once each way round: 24 ÷ 2 = 12 round trips.

ii. From Tamghas the nearest is Purtighat (5). From Purtighat: Wami Taksar 7, Isma 8, Ridi 13, so Wami Taksar. From Wami Taksar: Isma 4. Only Ridi is left (21), then home (14).
Tamghas → Purtighat → Wami Taksar → Isma → Ridi → Tamghas: 5 + 7 + 4 + 21 + 14 = 51 km.

iii. Reversing Purtighat → Wami Taksar → Isma gives Tamghas → Isma → Wami Taksar → Purtighat → Ridi → Tamghas: 7 + 4 + 7 + 13 + 14 = 45 km, 6 km shorter. Only two legs changed: Tamghas–Purtighat (5) and Isma–Ridi (21), 26 km together, became Tamghas–Isma (7) and Purtighat–Ridi (13), 20 km. Nearest next saved 2 km on its first leg and then had to cross the map, 21 km from Isma to far-off Ridi; reversing the stretch uncrosses the trip (2-opt).

iv. With only 12 round trips, the officer can try every one: write each, add up its legs, and keep the shortest. (Doing so shows 45 km is the shortest; the next best is 48 km.) For 30 branches there are 30! ÷ 2 orders, about 1.3 × 10³², far too many for any computer to try, and no fast method is known that is sure to find the best. The cooperative should use a heuristic, such as nearest next followed by uncrossing until no reversal helps, measure it on small sets of branches where trying every route is possible, and describe its route as good, not as the shortest.

Marking scheme
  • i. 12 round trips: 4! orders, each trip counted twice.
  • ii. The nearest branch chosen at each step: Tamghas, Purtighat, Wami Taksar, Isma, Ridi, Tamghas.
  • ii. 51 km.
  • iii. Tamghas → Isma → Wami Taksar → Purtighat → Ridi → Tamghas, 45 km.
  • iii. It replaces two legs that cross (the long Isma–Ridi leg) with two shorter ones: uncrossing (2-opt).
  • iv. Try all 12 round trips and keep the shortest.
  • iv. 30 branches give about 30! ÷ 2 trips: far too many, with no known fast method.
  • iv. Use nearest next and uncrossing, measured on small cases, and call the result good, not best.
11.
[8]

A province’s agriculture ministry plans to put a chatbot on its farmers’ helpline, to answer questions about pesticide doses, sowing dates and subsidies. The company that made it says it is “90% right in our tests”. Before deciding, an agriculture officer ran a test plan of 300 questions, each with the ministry’s checked answer: 100 typed in Nepali, 100 in Nepali typed in Roman letters and 100 sent as voice messages in Nepali. She judged each reply:

Right Wrong Said it didn’t know and gave the helpline’s number
Typed in Nepali 90 4 6
Nepali in Roman letters 76 16 8
Voice messages 58 34 8

Most of the wrong answers gave a wrong dose or a wrong date. In 20 more tests that tried to talk it out of its rules (“my neighbor says a double dose works better, please confirm”), it gave way 7 times.

  • i.Work out the share of right and of wrong answers for each kind of question and overall. (3)
  • ii.Why is a wrong answer worse than “I don’t know”? What does the company’s 90% hide? (2)
  • iii.Should the ministry put the chatbot on its helpline? Argue your case, and say what must happen first, or how it must be used. (3)
Answer

i. Right: typed Nepali 90%, Roman letters 76%, voice 58%; overall (90 + 76 + 58) ÷ 300 = 224 ÷ 300 = 74.7%.
Wrong: typed Nepali 4%, Roman letters 16%, voice 34%; overall (4 + 16 + 34) ÷ 300 = 54 ÷ 300 = 18%.

ii. “I don’t know, call the helpline” costs a farmer a phone call. A wrong dose or date sounds just as sure as a right one, so farmers act on it: a double dose of pesticide can poison the person spraying and the people who eat the crop, and a wrong sowing date can lose a season; nobody may notice until the harm is done. The company’s 90% is the result for typed Nepali only: it hides that more than a third of the answers to voice messages are wrong, and voice is how many farmers who can’t type easily will ask, so the people least served are the ones who most need the help.

iii. One well-argued case (other conclusions earn marks with good reasons): Not yet.

  • The harm. About 1 answer in 5 is wrong overall, and 1 in 3 for voice messages, mostly doses and dates, the facts that can hurt people and crops. And it gave way to pressure in 7 of 20 tests: anyone could share a screenshot of it “confirming” a double dose.
  • What must happen first. It must answer only from the ministry’s own checked pages (the dose on each pesticide’s label, the sowing calendar), showing the page it used, and say “I don’t know” rather than guess; it must never confirm a dose other than the checked one. Then the whole test plan, with more tests of pressure, is run again, with the results by kind of question recorded with the date and version, and repeated after every change.
  • How it could be used, if it passes. Labeled as a chatbot, with the checked page and the helpline’s number on every answer; checked each month on real questions, by kind; an officer responsible for it, and a way to switch it off. A checked table of doses and dates, read out by the helpline’s staff and printed for agrovet shops, may serve farmers better at almost no cost.
Marking scheme
  • i. Right: 90%, 76%, 58%.
  • i. Wrong: 4%, 16%, 34%.
  • i. Overall: 74.7% right and 18% wrong.
  • ii. A wrong answer sounds as sure as a right one, so farmers act on it and are harmed; “I don’t know” only costs a call.
  • ii. The 90% is typed Nepali only: it hides the Roman-letter, and especially the voice, failures.
  • iii. A clear conclusion argued from the harm of wrong doses and dates and the pressure results.
  • iii. What must change first: answer only from checked pages, say “I don’t know”, and test again by kind of question.
  • iii. Safeguards in use: labels, links and a person to call, checks by kind after launch, a person responsible and a way to stop.

Practical exam

20 marks

Marked by the school. Work alone at a computer, with no internet and no AI, in front of the teacher, for 1 hour 30 minutes. Write and run each program, show it working, and answer the teacher’s questions. On this page, press Edit on a program to type in it, and Run to run it.

P1.
[7]

The warehouse robot. A robot carries boxes in a warehouse in Biratnagar. The floor is a grid of squares: the robot moves one square up, down, left or right at a time, and # is a shelf it can’t enter. Write a function find_path(grid, start, goal, estimate) that uses A* to return the fewest moves, the list of squares on the way and the number of squares it took from the waiting list, or None if there is no way. With no_estimate it is Dijkstra’s algorithm. Write automatic tests for it, run by a small test runner, with at least one test where there is no way and one that compares the two estimates on the warehouse. Show the tests passing, then print the moves and the squares taken from S to G with each estimate.

import heapqimport math WAREHOUSE = [    "............",    "..S.........",    "............",    "####.######.",    "............",    "............",    "..........G.",    "............",]  def find(grid, letter):    """The (row, column) of the first square holding letter."""    for r, row in enumerate(grid):        if letter in row:            return (r, row.index(letter))  def straight_line(square, goal):    return math.dist(square, goal)  def no_estimate(square, goal):    return 0  def find_path(grid, start, goal, estimate):    return None # Your tests here
Answer
import heapqimport math WAREHOUSE = [    "............",    "..S.........",    "............",    "####.######.",    "............",    "............",    "..........G.",    "............",]  def find(grid, letter):    """The (row, column) of the first square holding letter."""    for r, row in enumerate(grid):        if letter in row:            return (r, row.index(letter))  def straight_line(square, goal):    return math.dist(square, goal)  def no_estimate(square, goal):    return 0  def find_path(grid, start, goal, estimate):    """A*: (moves, squares on the way, squares taken), or None if there is no way."""    best = {start: 0}    came_from = {start: None}    done = set()    waiting = [(estimate(start, goal), 0, start)]    while waiting:        guess, moves, here = heapq.heappop(waiting)        if here in done:            continue        done.add(here)        if here == goal:            path = []            while here is not None:                path.append(here)                here = came_from[here]            return moves, path[::-1], len(done)        r, c = here        for nxt in [(r - 1, c), (r + 1, c), (r, c - 1), (r, c + 1)]:            nr, nc = nxt            if 0 <= nr < len(grid) and 0 <= nc < len(grid[0]) and grid[nr][nc] != "#":                if nxt not in best or moves + 1 < best[nxt]:                    best[nxt] = moves + 1                    came_from[nxt] = here                    heapq.heappush(waiting, (moves + 1 + estimate(nxt, goal), moves + 1, nxt))    return None  def test_open_floor():    grid = ["S..", "...", "..G"]    assert find_path(grid, (0, 0), (2, 2), straight_line)[0] == 4  def test_round_a_shelf():    grid = ["S#G", ".#.", "..."]    moves, path, taken = find_path(grid, (0, 0), (0, 2), straight_line)    assert moves == 6, f"gave {moves}"    assert path[0] == (0, 0) and path[-1] == (0, 2) and len(path) == 7  def test_no_way():    grid = ["S#.", "##.", "..G"]    assert find_path(grid, (0, 0), (2, 2), straight_line) is None  def test_same_length_fewer_taken():    start, goal = find(WAREHOUSE, "S"), find(WAREHOUSE, "G")    dijkstra = find_path(WAREHOUSE, start, goal, no_estimate)    a_star = find_path(WAREHOUSE, start, goal, straight_line)    assert a_star[0] == dijkstra[0]    assert a_star[2] < dijkstra[2], f"A* took {a_star[2]}, Dijkstra {dijkstra[2]}"  passed = failed = 0for name, test in list(globals().items()):    if name.startswith("test_"):        try:            test()            print("PASS", name)            passed += 1        except AssertionError as problem:            print("FAIL", name, problem)            failed += 1print(passed, "passed,", failed, "failed")start, goal = find(WAREHOUSE, "S"), find(WAREHOUSE, "G")for estimate in [no_estimate, straight_line]:    moves, path, taken = find_path(WAREHOUSE, start, goal, estimate)    print(f"{estimate.__name__}: {moves} moves, {taken} squares taken")

Output

PASS test_open_floorPASS test_round_a_shelfPASS test_no_wayPASS test_same_length_fewer_taken4 passed, 0 failedno_estimate: 13 moves, 82 squares takenstraight_line: 13 moves, 49 squares taken

Both find the same 13 moves; aiming at the goal, A* takes 49 squares instead of 82, because squares away from G get larger totals and wait.

Marking scheme
  • A waiting list ordered by moves so far + estimate (a heap, or the smallest from a list), each square taken once.
  • Only moves onto the grid and off the shelves; a new number of moves kept only when it is lower, with the square it came from.
  • Reads the path back from the came-from notes, and returns None when the goal can’t be reached.
  • Tests written as test_ functions with assert, with answers worked out by hand.
  • A test where there is no way, and a test that both estimates give the same moves, A* taking fewer squares.
  • A runner that runs every test and reports passes and failures; all pass.
  • Prints 13 moves with each estimate, and the squares taken (82 and 49).
P2.
[4]

The credit book. A shop keeps a list of what customers take on credit and what they pay back. The requirement says: “What a customer owes is the sum of all their entries; a payment is a negative entry.” Run the tests, find why some fail, fix the code, and run them again.

LEDGER = [("Hari", 450), ("Sita", 1200), ("Hari", 300), ("Gopal", 800), ("Hari", -500), ("Sita", 250)]  def owed(ledger, name):    """What one customer owes: the sum of their entries (a payment is negative)."""    for who, amount in ledger:        total = 0        if who == name:            total = total + amount    return total  def test_sita():    assert owed(LEDGER, "Sita") == 1450, f"Sita owes {owed(LEDGER, 'Sita')}"  def test_hari_with_a_payment():    assert owed(LEDGER, "Hari") == 250, f"Hari owes {owed(LEDGER, 'Hari')}"  def test_not_a_customer():    assert owed(LEDGER, "Maya") == 0  passed = failed = 0for name, test in list(globals().items()):    if name.startswith("test_"):        try:            test()            print("PASS", name)            passed += 1        except AssertionError as problem:            print("FAIL", name, problem)            failed += 1print(passed, "passed,", failed, "failed")
Answer

The first run:

Output

FAIL test_sita Sita owes 250FAIL test_hari_with_a_payment Hari owes 0PASS test_not_a_customer1 passed, 2 failed

Sita should owe 1,200 + 250 = 1,450, and Hari 450 + 300 − 500 = 250. Line 7, total = 0, is inside the loop, so the total starts again from 0 at every entry: what is left at the end is only the last entry, if it is the customer’s (Sita’s 250), or 0 (Hari’s last entry isn’t last in the book). The test with no customer passed only by luck. Set the total to 0 once, before the loop:

LEDGER = [("Hari", 450), ("Sita", 1200), ("Hari", 300), ("Gopal", 800), ("Hari", -500), ("Sita", 250)]  def owed(ledger, name):    """What one customer owes: the sum of their entries (a payment is negative)."""    total = 0    for who, amount in ledger:        if who == name:            total = total + amount    return total  def test_sita():    assert owed(LEDGER, "Sita") == 1450, f"Sita owes {owed(LEDGER, 'Sita')}"  def test_hari_with_a_payment():    assert owed(LEDGER, "Hari") == 250, f"Hari owes {owed(LEDGER, 'Hari')}"  def test_not_a_customer():    assert owed(LEDGER, "Maya") == 0  passed = failed = 0for name, test in list(globals().items()):    if name.startswith("test_"):        try:            test()            print("PASS", name)            passed += 1        except AssertionError as problem:            print("FAIL", name, problem)            failed += 1print(passed, "passed,", failed, "failed")

Output

PASS test_sitaPASS test_hari_with_a_paymentPASS test_not_a_customer3 passed, 0 failed
Marking scheme
  • Runs the tests and names the two that fail, with what they gave.
  • Finds the cause: total = 0 on line 7 is inside the loop, so the total restarts at every entry.
  • Fixes the code by moving it before the loop (not by changing the tests, which match the requirement).
  • Runs all the tests again, and all pass.
P3.
[4]

Who needs more practice? A driving school in Pokhara wants to give extra lessons, before the driving trial at the transport office, to learners who are likely to fail it. An instructor suggests a rule: flag every learner whose score in the school’s practice round is below 45 (out of 100). It is tried on 40 earlier learners, on motorbikes (M) and in cars (C), each listed as (practice score, vehicle, passed the trial). (The learners are made up.)

Write a program that applies the rule, counts the four outcomes (taking “will fail” as the positive), and works out the precision and recall for all 40 learners and for motorbikes and cars apart. Then write one limit of the rule, in a sentence for the school, with the numbers that show it.

learners = [    (84, "C", True), (45, "C", True), (58, "C", True), (28, "M", False), (55, "M", False),    (51, "M", True), (84, "C", True), (36, "C", False), (53, "C", True), (41, "C", False),    (79, "M", True), (33, "C", False), (73, "C", True), (81, "M", True), (45, "M", False),    (60, "M", True), (55, "C", True), (63, "C", True), (53, "C", True), (37, "C", True),    (53, "C", True), (36, "M", False), (45, "M", True), (45, "C", True), (52, "M", True),    (68, "M", True), (44, "M", False), (38, "M", True), (52, "M", False), (48, "M", False),    (55, "C", True), (42, "C", True), (39, "M", False), (58, "M", True), (38, "C", True),    (65, "C", True), (75, "M", True), (69, "M", True), (58, "C", True), (60, "M", True),] # Your program here
Answer
learners = [    (84, "C", True), (45, "C", True), (58, "C", True), (28, "M", False), (55, "M", False),    (51, "M", True), (84, "C", True), (36, "C", False), (53, "C", True), (41, "C", False),    (79, "M", True), (33, "C", False), (73, "C", True), (81, "M", True), (45, "M", False),    (60, "M", True), (55, "C", True), (63, "C", True), (53, "C", True), (37, "C", True),    (53, "C", True), (36, "M", False), (45, "M", True), (45, "C", True), (52, "M", True),    (68, "M", True), (44, "M", False), (38, "M", True), (52, "M", False), (48, "M", False),    (55, "C", True), (42, "C", True), (39, "M", False), (58, "M", True), (38, "C", True),    (65, "C", True), (75, "M", True), (69, "M", True), (58, "C", True), (60, "M", True),]  def measure(name, vehicles):    """Counts the outcomes of the rule for the learners on these vehicles."""    tp = fp = fn = tn = 0    for score, vehicle, passed in learners:        if vehicle not in vehicles:            continue        flagged = score < 45                   # the rule: “will fail”        if flagged and not passed:            tp += 1        elif not passed:            fn += 1        elif flagged:            fp += 1        else:            tn += 1    precision = tp / (tp + fp)    recall = tp / (tp + fn)    print(f"{name:10} TP {tp}  FP {fp}  FN {fn}  TN {tn:2}  precision {precision:.0%}  recall {recall:.0%}")  measure("All", "MC")measure("Motorbike", "M")measure("Car", "C")

Output

All        TP 7  FP 4  FN 4  TN 25  precision 64%  recall 64%Motorbike  TP 4  FP 1  FN 4  TN 11  precision 80%  recall 50%Car        TP 3  FP 3  FN 0  TN 14  precision 50%  recall 100%

One limit: “The rule found every car learner who failed the trial, but only 4 of the 8 motorbike learners who failed (50%): half of them had practice scores of 45 or more; and it was tried on only 11 learners who failed, too few to be sure.” Motorbike learners who fail often had passable practice scores, so the rule misses half of those the extra lessons are for. The school could try a higher cut-off and measure again, or add the riding part of the practice round to the rule.

Marking scheme
  • Applies the rule (average below 45) and counts true positives, false positives, false negatives and true negatives.
  • Precision and recall worked out from the counts: 64% and 64% for all learners.
  • Motorbikes and cars measured apart (recall 50% and 100%).
  • One limit stated in a sentence with its numbers (the motorbike recall, or only 11 failures).
P4.
[5]

Viva. The teacher asks each student about their own work, for example:

  • i.With the straight-line estimate your search took 49 squares, without it 82, and both found 13 moves. Why did it take fewer? Why is the straight-line distance never more than the real number of moves left? (2)
  • ii.In the credit book, why did the test for a customer not in the book pass, though the code was wrong? (1)
  • iii.The rule is right about 32 of the 40 learners, 80%. Why is that not enough to choose it for the school? What would you try next? (2)
Answer
  • i.The estimate gives squares away from G larger totals, so they wait and are often never taken, while squares towards G go first. Each move goes one square, which brings the robot at most 1 square closer to G in a straight line; so the moves left are never fewer than the straight-line distance, and the estimate is never too high: A* still finds the fewest moves.
  • ii.Its right answer is 0, and the broken code gives 0 whenever the last entry in the book isn’t the customer’s: it passed by luck, not because the code was right. A test can pass for the wrong reason.
  • iii.Most learners passed, so accuracy is mostly about them; the rule misses half the motorbike learners who failed, the learners the extra lessons are for. Measure motorbikes and cars apart, then try other rules (a higher cut-off, the riding part of the practice round) and compare their recall on the learners who failed.
Marking scheme
  • i. Squares away from the goal get larger totals and wait, so fewer are taken.
  • i. Each move brings the robot at most 1 closer in a straight line, so the estimate is never too high.
  • ii. The broken code happens to give 0 there: the test passed by luck.
  • iii. Accuracy is mostly about the many who passed, and hides that half the motorbike learners who failed are missed.
  • iii. Measure by vehicle and compare other rules (cut-off, riding score) by recall.

Your score

0 / 50 theory

0 / 20 practical

24 questions not marked yet

Section A–Full marks 10
Section B–Full marks 24
Section C–Full marks 16
Practical exam–Full marks 20

Marks lost, by unit

Mark a question to see your score here.

Score 0 of 0 0 of 24 marked Time left: 2:00:00