Skip to content

← Final exam model papers

Final Exam Model Paper 2

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.

In a grammar written in BNF, what is a non-terminal, such as <digit>?

Pick an answer to see why.

b.

Bibek writes his own sorting function, which is O(n²), for a mobile wallet company’s app. On a test with 100 customers it sorts faster than Python’s sorted, which is O(n log n). He says, “Mine is faster, so we will use it for all 10 lakh customers.” Which judgment is right?

Pick an answer to see why.

c.

In testing, what is a stub?

Pick an answer to see why.

d.

A test that passed 300 commits ago now fails, and nobody knows which commit broke it. About how many commits will git bisect need to test to find it?

Pick an answer to see why.

e.

What is a shard?

Pick an answer to see why.

f.

Pratima pays her college fee in the college’s app, and it says “Paid”. When she opens her fee statement a moment later, the fee still shows as due. A minute later it shows as paid. What is the most likely reason?

Pick an answer to see why.

g.

On results day, each page of a results website needs answers from 20 servers, and waits for the slowest. Each server is slow on 2% of requests, independently of the others. About what share of pages are slow?

Pick an answer to see why.

h.

What is forward secrecy?

Pick an answer to see why.

i.

Dipika signs in to her bank with a passkey. A lookalike website, set up by a scammer, copies the bank’s sign-in page exactly. Why can’t it collect anything it can use to sign in as her?

Pick an answer to see why.

j.

Pasang, a developer at a cooperative in Kailali, is told to make the loan app show “Interest 9%” in large letters, and to put the rise to 16% after six months only on the terms page, in small gray text. Which judgment best follows the ACM Code?

Pick an answer to see why.

Section B

8 × 3 = 24

Write short answers to the following questions.

2.
[3]

A campus library in Khotang gives each member a card number such as KH-204 or KH-17/A: the letters KH, a hyphen, one or more digits, and perhaps /A at the end (for a second card).

  • i.Write a regular expression that re.fullmatch would use to accept exactly these card numbers.
  • ii.Write the finite state machine for it as a transition table, and mark the accepting states.
  • iii.Using your machine, say whether KH-/A and KH-17/A are accepted, and the state each ends in.
Answer

i. KH-\d+(/A)?
ii.

State K H - a digit / A
S (start) 1
1 2
2 3
3 4
4 (accepting) 4 5
5 6
6 (accepting)

An empty square means no arrow: the text is rejected at once.
iii. KH-/A: S → 1 → 2 → 3, then / has no arrow from state 3 (a digit must come first): rejected. KH-17/A: S → 1 → 2 → 3 → 4 → 4 → 5 → 6, and 6 is accepting: accepted.

Marking scheme
  • i. A correct pattern, such as KH-\d+(/A)?.
  • ii. A correct table (or diagram) with a loop on digits and the two accepting states, after the digits and after /A.
  • iii. KH-/A rejected (no arrow for / before a digit) and KH-17/A accepted, ending in an accepting state.
3.
[3]

The school library’s rule: “A book may be kept for 14 days. After that, the fine is Rs 5 for each extra day, but never more than Rs 100. A negative number of days is a mistake, and must be refused with a ValueError.” Pragya is writing fine(days). Before she writes it, write tests for it as test_ functions with assert:

  • i.one test with normal data;
  • ii.a test with boundary data, at both edges of the rule;
  • iii.a test with erroneous data.
Answer

One good set of tests (with a fine that meets the rule, so they can be run):

def fine(days):    if days < 0:        raise ValueError(f"days can't be negative: {days}")    return min(max(days - 14, 0) * 5, 100)  def test_normal():    assert fine(17) == 15              # 3 days late  def test_boundary():    assert fine(14) == 0               # the last free day    assert fine(15) == 5               # the first day late    assert fine(34) == 100             # 20 days late: exactly the most    assert fine(35) == 100             # one more day: still 100  def test_erroneous():    try:        fine(-1)    except ValueError:        return                         # refused, as it should be    raise AssertionError("-1 was accepted")  for test in [test_normal, test_boundary, test_erroneous]:    test()    print("PASS", test.__name__)

Output

PASS test_normalPASS test_boundaryPASS test_erroneous
Marking scheme
  • i. A normal value well inside the rule, with the fine worked out by hand (17 days, Rs 15).
  • ii. Values on both sides of the 14-day line (14 → 0, 15 → 5) and at the Rs 100 cap (34 and 35 → 100).
  • iii. A negative number of days, with the test passing only if a ValueError is raised.
4.
[3]

A rural municipality in Dadeldhura is building an app for birth registration. It has three parts: a form that checks what the ward secretary types, a database that stores each record, and a part that sends the family an SMS when the certificate is ready.

  • i.Give an example of a unit test for this app.
  • ii.Give an example of an integration test, and say why it is needed even when every unit test passes.
  • iii.Who would do the acceptance testing, and against what?
Answer
  • i.Test one part alone: for example, the form refuses a date of birth in the future, or a name left empty (with a stub in place of the database).
  • ii.Test two parts together where they hand data to each other: for example, a record saved by the form is found in the database with the same date, and the SMS part sends the certificate number the database gave it. Each part can pass its own tests and still disagree with the next, such as one writing dates in Bikram Sambat and the other reading them as AD.
  • iii.The customer: the municipality’s officials (the ward secretaries and the registration officer), who check the finished app against the requirements they agreed, and decide whether to accept it.
Marking scheme
  • i. A test of one part alone, with a suitable example.
  • ii. A test of parts together, and why: parts can each be right and still disagree where they meet.
  • iii. Done by the customer (the municipality’s officials) against the agreed requirements.
5.
[3]

A flood-warning website shows the latest water level of the Karnali at Chisapani on its home page, read from its database. To save work, it keeps a copy of the page in a cache for 10 minutes (its time to live). On an ordinary day, about 6,000 people open the home page each hour.

  • i.How many times an hour does the home page now need the database, and why?
  • ii.The river rises fast at 14:02, and a new reading reaches the database. What can go wrong, and how could the site prevent it?
  • iii.During a flood, 60,000 people an hour open the page. How many times an hour does the page need the database then? What does this show about a cache?
Answer
  • i.About 6 times, once every 10 minutes. The first request after the copy runs out is a miss: the page is built from the database and kept. The other requests in those 10 minutes are hits, served from the copy.
  • ii.The copy is stale: for up to 10 minutes people see the old, lower level, while the river is rising, which is exactly when the number matters most. The site can remove (or rebuild) the copy as soon as a new reading arrives, or keep it for a shorter time.
  • iii.Still about 6. However many people come, the database is read only when the copy runs out: the cache makes the database’s work independent of the number of visitors, which is why it helps most on the busiest day.
Marking scheme
  • i. About 6 times an hour: one miss each time the copy runs out, then hits.
  • ii. A stale level shown for up to 10 minutes while the river rises; prevented by removing the copy when a new reading comes (or a shorter time to live).
  • iii. Still about 6 an hour: the database’s work doesn’t grow with the visitors.
6.
[3]

A survey of 600 farmers in Chitwan finds that farmers who use a farming-advice app on their phones get bigger rice harvests per kattha. An official says, “Let’s get every farmer to use the app, and harvests will go up.”

  • i.Name a possible confounder, and explain how it could cause both.
  • ii.Explain how the cause could run the other way.
  • iii.How could the official find out whether the app really raises harvests?
Answer
  • i.For example, money and land: better-off farmers can afford a smartphone with data, and also irrigation, better seed and fertilizer, which raise their harvests. (Others: schooling; being younger; living near a town and its market.)
  • ii.Reverse cause: farmers who already get good harvests earn more, so they can buy smartphones and data; the harvests could be causing the app use.
  • iii.A randomized trial: choose at random which farmers (or villages) get a phone with the app and training and which don’t, then compare their harvests after a season. Random choice makes the groups alike in everything else, confounders included, so a difference can be put down to the app.
Marking scheme
  • i. A sensible confounder that could raise both app use and harvests.
  • ii. Good harvests (more money) leading to app use.
  • iii. Groups chosen at random, then compared.
7.
[3]

Two savings and credit cooperatives report how many of last year’s loans were repaid on time:

Small business loans Housing loans All loans
Bhojpur cooperative 150 of 200 (75%) 46 of 50 (92%) 196 of 250 (78.4%)
Dhankuta cooperative 35 of 50 (70%) 176 of 200 (88%) 211 of 250 (84.4%)

A newspaper writes: “Dhankuta’s cooperative is better at choosing borrowers; Bhojpur’s should copy its methods.” Judge this claim.

Answer

The claim is not supported. For each kind of loan, Bhojpur’s cooperative has the better record (75% against 70%, and 92% against 88%). Dhankuta looks better overall only because most of its loans are housing loans, which are repaid more often everywhere, while most of Bhojpur’s are small business loans, which are repaid less often. A total that reverses the comparison inside every group is Simpson’s paradox: the mix of loans, not the choosing, makes the difference. If anything, Dhankuta could learn from Bhojpur. A fair report compares like with like, kind of loan by kind of loan.

Marking scheme
  • Bhojpur is better within each kind of loan (75% vs 70%, 92% vs 88%).
  • Dhankuta is ahead overall only because of its mix of loans (mostly housing, repaid more often).
  • Names Simpson’s paradox (or explains it) and concludes the claim is wrong: compare within groups.
8.
[3]

Aayush and Bina agree on a key over an open line, using key exchange with the public numbers p = 29 and g = 2. Aayush’s secret is a = 5 and Bina’s is b = 9.

  • i.What number does Aayush send?
  • ii.What number does Bina send?
  • iii.Work out the shared key on each side, and show they are the same.
Answer
  • i.A = 2⁵ mod 29 = 32 mod 29 = 3.
  • ii.B = 2⁹ mod 29 = 512 mod 29. 17 × 29 = 493, so B = 19.
  • iii.Aayush works out Bᵃ = 19⁵ mod 29: 19² = 361 ≡ 13 (361 − 348); 19⁴ ≡ 13² = 169 ≡ 24 (169 − 145); 19⁵ ≡ 24 × 19 = 456 ≡ 21 (456 − 435).

Bina works out Aᵇ = 3⁹ mod 29: 3³ = 27; 3⁶ = 27² = 729 ≡ 4 (729 − 725); 3⁹ ≡ 4 × 27 = 108 ≡ 21 (108 − 87).
Both get 21, without ever sending it. (Eve sees only 29, 2, 3 and 19.)

Marking scheme
  • i. A = 3.
  • ii. B = 19.
  • iii. 19⁵ mod 29 and 3⁹ mod 29 both worked out as 21.
9.
[3]

A government has many tools for a new technology such as AI, from a light touch to a heavy hand. Name three of them, from the lightest to the heaviest, with an example from AI for each.

Answer

Any three, in order, for example:

  • Information and funding (light): a grant for an AI research center, or courses in AI for teachers.
  • Disclosure: a label on every AI-made video or picture.
  • Impact assessment: questions a government office must answer before using an AI system to decide about people, which set the safeguards it needs.
  • Licensing: only approved companies may sell AI systems for grading exams.
  • A ban (heaviest): no AI system may score people’s social behavior.

(Guidelines and standards also lie between the light and heavy ends.)

Marking scheme
  • A first tool with a suitable AI example.
  • A second tool with a suitable AI example.
  • A third tool with a suitable AI example, the three in order from lightest to heaviest.

Section C

2 × 8 = 16

Write long answers to the following questions.

10.
[8]

A. A ward office’s online form asks for the applicant’s home district. When someone types a name that isn’t a district, the form suggests the district at the smallest edit distance. Rabin types JUMAL.

  • i.Fill in the edit-distance table between JUMAL (rows) and JUMLA (columns). (3)
  • ii.Write the distance, and the edits it stands for. (1)

B. The ward hall can hold one event at a time. These requests have come in for Saturday. An event may start the moment another ends.

Request Time
Mothers’ group 7:00–12:00
Youth club 8:00–9:00
Ward committee meeting 9:00–11:00
Senior citizens’ bhajan 11:00–14:00
Children’s drawing contest 12:00–13:00
Women’s savings group 13:00–15:00
  • iii.Use the greedy method of taking the request that finishes earliest, then the next that starts after it and finishes earliest, and so on. Which events get the hall? (2)
  • iv.The ward secretary suggests taking the request that starts earliest each time instead. Which events would get the hall then? (1)
  • v.Why can no choice of first event fit more events than the one that finishes earliest? (1)
Answer

i. Each cell is the smallest of: the cell above + 1, the cell to the left + 1, and the cell diagonally above-left + 0 (same letters) or + 1 (different).

J U M L A
0 1 2 3 4 5
J 1 0 1 2 3 4
U 2 1 0 1 2 3
M 3 2 1 0 1 2
A 4 3 2 1 1 1
L 5 4 3 2 1 2

ii. 2. J, U and M are kept; then A and L are in the wrong order, which costs two edits: change A to L and L to A (or delete the A, keep the L, and insert an A at the end). Swapping two letters counts as two edits in this measure.

iii. Finishing earliest is the youth club (9:00). Of those starting at 9:00 or later, the ward committee meeting finishes first (11:00). Of those starting at 11:00 or later, the drawing contest finishes first (13:00); then the savings group (13:00–15:00). Four events: youth club, ward committee meeting, drawing contest, women’s savings group.

iv. Starting earliest is the mothers’ group (7:00–12:00). Then, starting at 12:00 or later, the drawing contest (12:00–13:00), then the savings group (13:00–15:00). Only three events. The long first event blocks four others.

v. The event that finishes earliest leaves the hall free from the earliest possible moment. Whatever event another plan puts first finishes at the same time or later, so swapping it for the earliest-finishing one never makes the rest fit worse; repeating the argument at each step shows the greedy plan fits as many events as any plan can.

Marking scheme
  • i. The first row and column 0 to 5, and every cell from its three neighbors.
  • i. The rows for J, U and M correct (the diagonal of zeros).
  • i. The rows for A and L correct (1, 1, 1 and 1, 2).
  • ii. Distance 2, with the edits it stands for.
  • iii. Requests taken in order of finishing time, each starting after the last one ends.
  • iii. Four events: youth club, ward committee, drawing contest, savings group.
  • iv. Three events (mothers’ group, drawing contest, savings group): starting earliest is worse.
  • v. Finishing earliest leaves the most time for the rest, so it can always replace the first event of any other plan.
11.
[8]

A college in Pokhara plans to check every Grade 12 project report with a model that says whether the writing was done by AI, and to give zero to every report the model flags. The builders tested it on 500 reports whose truth was known, 50 of them written by AI.

Flagged Not flagged
Written by AI 32 18
The student’s own 44 406

Split by the school the student studied at before Grade 11:

AI, flagged AI, not flagged Own, flagged Own, not flagged
English-medium schools (300 reports) 21 9 18 252
Nepali-medium schools (200 reports) 11 9 26 154
  • i.Taking “written by AI” as the positive, work out the model’s accuracy, precision and recall over all 500 reports. (3)
  • ii.For each group, work out the share of the students’ own reports that were flagged, and the precision. What do the numbers mean for students from Nepali-medium schools? (2)
  • iii.Should the college give zero to flagged reports automatically? Argue your case, and say how the model could be used, if at all. (3)
Answer

i. TP = 32, FN = 18, FP = 44, TN = 406.

  • Accuracy = (32 + 406) ÷ 500 = 438 ÷ 500 = 87.6%
  • Precision = 32 ÷ (32 + 44) = 32 ÷ 76 = 42%: fewer than half of the flagged reports were really written by AI.
  • Recall = 32 ÷ (32 + 18) = 32 ÷ 50 = 64%

ii. English-medium: 18 of the 270 own reports were flagged, 6.7%; precision 21 ÷ (21 + 18) = 21 ÷ 39 = 54%. Nepali-medium: 26 of 180, 14.4%; precision 11 ÷ (11 + 26) = 11 ÷ 37 = 30%. A student from a Nepali-medium school who wrote her own report is more than twice as likely to be flagged, and 7 in 10 of the flagged reports from these students are their own work. Under the plan, they would get zero, and be thought cheats, for nothing they did. The likely cause is the data: the model learned what a person’s writing looks like mostly from fluent English writers, so the plainer English of students writing in their second language looks to it like a machine’s.

iii. One well-argued case (other conclusions earn marks with good reasons): No: not as an automatic zero.

  • The cost of each mistake. Here a flag is a punishment: a zero, and an accusation of cheating. So a false alarm is costly, and precision matters: at 42% overall and 30% for Nepali-medium students, most zeros would go to students who did their own work. The 87.6% accuracy hides this, because most reports are the students’ own anyway.
  • Fairness. The zeros would fall most on students writing in their second language, who did nothing different. The cure is at the cause: test the model on, and retrain it with, much more writing by students like them, and measure it by group again. A different threshold for them would only move the line on poor scores.
  • How it could be used. Only as a reason to talk: a flag means the teacher asks the student, in the viva, to explain the report, its choices and its drafts; the teacher decides, the student is told why and can appeal; nobody gets zero from the model alone. Its results are checked each year by group. Better still, the college can mark the work AI can’t do for the student: the drafts, the viva, and the work done in class.
Marking scheme
  • i. Accuracy 87.6%.
  • i. Precision 42%.
  • i. Recall 64%.
  • ii. Own reports flagged: 6.7% (English-medium) and 14.4% (Nepali-medium); precision 54% and 30%.
  • ii. Students from Nepali-medium schools who did their own work are flagged about twice as often, and most of their flags are wrong.
  • iii. A clear conclusion argued from the cost of a false alarm when a flag means zero (precision matters most).
  • iii. The gap dealt with at its cause (testing and retraining with second-language writing, measured by group), not just a different threshold.
  • iii. Safeguards: the teacher decides after a viva, the student is told and can appeal, checks by group, no zero from the model alone.

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]

Cheapest transfer. A cooperative moves members’ money between its branches, and each link between two branches has a fee (the fees below are made up). Money may pass through other branches on the way. Write a function cheapest(fees, start, goal) that returns the lowest total fee and the list of branches on the way, or None if there is no way, and automatic tests for it, run by a small test runner, with at least one test where the direct link is not the cheapest. Show the tests passing, then print the cheapest way from Khotang to Jhapa.

FEES = {    "Khotang": {"Bhojpur": 40, "Dhankuta": 90},    "Bhojpur": {"Khotang": 40, "Dhankuta": 35, "Ilam": 120},    "Dhankuta": {"Khotang": 90, "Bhojpur": 35, "Ilam": 60, "Jhapa": 110},    "Ilam": {"Bhojpur": 120, "Dhankuta": 60, "Jhapa": 30},    "Jhapa": {"Dhankuta": 110, "Ilam": 30},    "Kailali": {},} def cheapest(fees, start, goal):    return None # Your tests here
Answer
import heapq FEES = {    "Khotang": {"Bhojpur": 40, "Dhankuta": 90},    "Bhojpur": {"Khotang": 40, "Dhankuta": 35, "Ilam": 120},    "Dhankuta": {"Khotang": 90, "Bhojpur": 35, "Ilam": 60, "Jhapa": 110},    "Ilam": {"Bhojpur": 120, "Dhankuta": 60, "Jhapa": 30},    "Jhapa": {"Dhankuta": 110, "Ilam": 30},    "Kailali": {},}  def cheapest(fees, start, goal):    """The lowest total fee from start to goal, and the branches on the way, or None."""    best = {start: 0}    came_from = {start: None}    done = set()    waiting = [(0, start)]    while waiting:        cost, here = heapq.heappop(waiting)        if here in done:            continue        done.add(here)        if here == goal:            route = [goal]            while came_from[route[-1]] is not None:                route.append(came_from[route[-1]])            return cost, route[::-1]        for there, fee in fees[here].items():            if there not in best or cost + fee < best[there]:                best[there] = cost + fee                came_from[there] = here                heapq.heappush(waiting, (cost + fee, there))    return None  def test_same_branch():    assert cheapest(FEES, "Ilam", "Ilam") == (0, ["Ilam"])  def test_one_step():    assert cheapest(FEES, "Ilam", "Jhapa") == (30, ["Ilam", "Jhapa"])  def test_cheaper_round_about():    # straight from Khotang to Dhankuta costs 90; through Bhojpur, 75    assert cheapest(FEES, "Khotang", "Dhankuta") == (75, ["Khotang", "Bhojpur", "Dhankuta"])  def test_no_way():    assert cheapest(FEES, "Khotang", "Kailali") is None  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")print(cheapest(FEES, "Khotang", "Jhapa"))

Output

PASS test_same_branchPASS test_one_stepPASS test_cheaper_round_aboutPASS test_no_way4 passed, 0 failed(165, ['Khotang', 'Bhojpur', 'Dhankuta', 'Ilam', 'Jhapa'])

Rs 165, through Bhojpur, Dhankuta and Ilam: cheaper than Khotang → Bhojpur → Dhankuta → Jhapa (Rs 185) or the direct link from Dhankuta (Rs 200 from Khotang).

Marking scheme
  • Dijkstra’s algorithm: always takes the waiting branch with the lowest total so far (a heap, or the smallest from a list).
  • Relaxes each link: keeps a new total only when it is lower, with the branch it came from.
  • Reads the route 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 the direct link is not the cheapest (Khotang to Dhankuta, 75 through Bhojpur).
  • A runner that runs every test and reports passes and failures; all pass.
  • Prints Rs 165 by Khotang → Bhojpur → Dhankuta → Ilam → Jhapa.
P2.
[4]

The second child. A school’s requirement says: “Each family pays the full monthly fee for its first child at the school, and 10% less for every other child. The total is rounded to the nearest rupee.” Run the tests, find why some fail, fix the code, and run them again.

def family_fee(fees):    """The monthly total for one family; fees lists each child's fee, the first child first."""    total = fees[0]    for i in range(2, len(fees)):        total = total + fees[i] * 0.9    return round(total)  def test_one_child():    assert family_fee([4000]) == 4000  def test_two_children():    assert family_fee([4000, 3500]) == 7150, f"gave {family_fee([4000, 3500])}"  def test_three_children():    assert family_fee([4000, 3500, 3000]) == 9850, f"gave {family_fee([4000, 3500, 3000])}"  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

PASS test_one_childFAIL test_two_children gave 4000FAIL test_three_children gave 67001 passed, 2 failed

With two children the second child’s fee is missing altogether, and with three the total is 4,000 + 2,700: the second child (Rs 3,500 less 10%, Rs 3,150) is again left out. The loop on line 4 starts at 2, so it skips position 1, the second child. The first child is already in total, so the loop should start at 1:

def family_fee(fees):    """The monthly total for one family; fees lists each child's fee, the first child first."""    total = fees[0]    for i in range(1, len(fees)):        total = total + fees[i] * 0.9    return round(total)  def test_one_child():    assert family_fee([4000]) == 4000  def test_two_children():    assert family_fee([4000, 3500]) == 7150, f"gave {family_fee([4000, 3500])}"  def test_three_children():    assert family_fee([4000, 3500, 3000]) == 9850, f"gave {family_fee([4000, 3500, 3000])}"  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_one_childPASS test_two_childrenPASS test_three_children3 passed, 0 failed
Marking scheme
  • Runs the tests and names the two that fail, with what they gave.
  • Finds the cause: the loop on line 4 starts at 2, skipping the second child.
  • Fixes the code with range(1, len(fees)) (not the tests, which match the requirement: 4,000 + 3,150 = 7,150).
  • Runs all the tests again, and all pass.
P3.
[4]

Rice blast from a photo. A phone app tells farmers whether a rice plant has blast, a fungus disease, from a photo of its leaves. It was tested on 50 photos checked by an agriculture officer: truth has D where the plant really had blast, said has D where the app said blast, and phone is O for a photo taken on an old phone with a basic camera and N for one taken on a newer phone. (The photos and results are made up.)

Write a program that counts the four outcomes and works out the app’s precision and recall, for all 50 photos and for the old and newer phones apart. Then write one limit of the app, in a sentence for the farmers’ group, with the numbers that show it.

truth = "---D----DD--D-D------------D-----DDDD-----D-DD-D--"said  = "---D----DD--DDD--------D--DD-----DD-D-D----D---D--"phone = "ONONONOONNNNNOONOOONNONONONONONONNNOOONNNOONOONNOO" # Your program here
Answer
truth = "---D----DD--D-D------------D-----DDDD-----D-DD-D--"said  = "---D----DD--DDD--------D--DD-----DD-D-D----D---D--"phone = "ONONONOONNNNNOONOOONNONONONONONONNNOOONNNOONOONNOO"  def measure(name, which):    """Counts the outcomes for the photos whose phone letter is in `which`."""    tp = fp = fn = tn = 0    for real, model, kind in zip(truth, said, phone):        if kind not in which:            continue        if real == "D" and model == "D":            tp += 1        elif real == "D":            fn += 1        elif model == "D":            fp += 1        else:            tn += 1    precision = tp / (tp + fp)    recall = tp / (tp + fn)    print(f"{name:9} TP {tp:2}  FP {fp}  FN {fn}  TN {tn:2}  precision {precision:.0%}  recall {recall:.0%}")  measure("All", "ON")measure("Old phone", "O")measure("New phone", "N")

Output

All       TP 10  FP 5  FN 4  TN 31  precision 67%  recall 71%Old phone TP  3  FP 2  FN 4  TN 16  precision 60%  recall 43%New phone TP  7  FP 3  FN 0  TN 15  precision 70%  recall 100%

One limit: “The app found blast in every photo from a newer phone, but in only 3 of the 7 diseased plants photographed on an old phone (43%); and it was tested on only 50 photos, 14 of them with blast, too few to be sure of these numbers.” A farmer it misses doesn’t spray, and blast spreads to the whole field. It needs many more old-phone photos to learn from and be tested on; until then, farmers with old phones should show a doubtful plant to the agriculture officer.

Marking scheme
  • A loop over the strings together that counts true positives, false positives, false negatives and true negatives.
  • Precision and recall worked out from the counts: 67% and 71% for all photos.
  • Old and newer phones measured apart (recall 43% and 100%).
  • One limit stated in a sentence with its numbers (the old phones’ recall, or only 14 diseased plants).
P4.
[5]

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

  • i.Why are the fees stored as a dictionary of dictionaries, not as a table with a row and a column for every branch? Why is each link’s fee written at both of its ends? (2)
  • ii.In the school’s program, how did you decide that the code, not the tests, was wrong? (1)
  • iii.The rice app’s accuracy is 82%. Why doesn’t that show whether it works for farmers with old phones? What would you do about it? (2)
Answer
  • i.The search asks, again and again, “which branches can I send to from here, and for what fee?”: fees[here] answers it in one lookup, and only the links that exist are stored. A table for a cooperative’s many branches would be mostly empty squares. Each fee is written at both ends because money can move either way along a link: written only at one end, a search starting from the other branch would never see the link.
  • ii.By working the totals out from the requirement: two children pay 4,000 + 3,500 × 0.9 = 7,150, which is what the test expects, so the test is right and the code is wrong.
  • iii.Accuracy counts all photos together, and most plants were healthy: it hides that the app misses more than half the blast in old-phone photos. Measure each kind of phone apart, collect and label many more old-phone photos, retrain and test again, and send farmers with old phones to the agriculture officer in the meantime.
Marking scheme
  • i. One lookup gives a branch’s links and fees, and only real links are stored (a table would be mostly empty).
  • i. Both ends, so the link can be used from either branch.
  • ii. From the requirement: the test’s 7,150 is right, so the code is wrong.
  • iii. Overall accuracy mixes the groups, and most plants were healthy, so it hides the old phones’ low recall.
  • iii. Measure by kind of phone, more old-phone photos to train and test on, and the officer’s check meanwhile.

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