Skip to content

← Final exam model papers

Final Exam Model Paper 9

Theory paper: 50 marksTime: 2 hours

Practical exam: 25 marksTime: 1 hour 30 minutes

All questions are compulsory.

A full practice run of the Grade 10 final exam: the theory paper (50 marks, 2 hours) and, below it, the practical exam (25 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.

The weather office signs up for a weather API and is given an API key. What is it, and how should the office treat it?

Pick an answer to see why.

b.

In Karnali, 20 weather stations (the office in Birendranagar among them) are joined by radio links so that every station can reach every other, with exactly one route between any two. How many radio links are there?

Pick an answer to see why.

c.

A weather database refuses any rainfall reading that is not from 0 to 500 mm. What kind of validation check is this?

Pick an answer to see why.

d.

Rupa works out, for four weather stations, the mean temperature and the mean height of the clouds, and the best-fit line between them. All four give the same means and the same line. She writes: “So the four stations behave the same way.” Which judgment is right?

Pick an answer to see why.

e.

A weather website’s hosting company promises 99.99% availability. This year the site was down for 3 hours in all. Did the company keep its promise?

Pick an answer to see why.

f.

A terminal shows sita@lab-pc:~/weather$. What does ~/weather tell Sita?

Pick an answer to see why.

g.

What is a large language model?

Pick an answer to see why.

h.

Bimala says: “A chatbot learns language the same way a child does.” Which is a real difference between them?

Pick an answer to see why.

i.

A company plans to launch 2,000 small satellites, low over the Earth, to collect weather data. Which of these is an environmental cost of that plan?

Pick an answer to see why.

j.

An advertisement says: “Our new AI rice cooker is an emerging technology: it will change how Nepal cooks.” It has a timer and three buttons, like the cookers of twenty years ago. Which judgment is best?

Pick an answer to see why.

Section B

10 × 2 = 20

Write short answers to the following questions.

2.
[2]

A program reads a weather forecast from an API:

import json text = '{"place": "Jomsom", "days": [{"day": "Sun", "wind_max": 38, "rain": 4.2}, {"day": "Mon", "wind_max": 52, "rain": 1.5}, {"day": "Tue", "wind_max": 45, "rain": 0}]}'forecast = json.loads(text)print(forecast["place"], len(forecast["days"]))for d in forecast["days"]:    if d["wind_max"] > 40:        print(d["day"], "windy:", d["wind_max"], "km/h")print(forecast["days"][-1]["day"], forecast["days"][-1]["rain"])
  • i.What kinds of Python value are forecast and forecast["days"]?
  • ii.Write the output.
Answer
  • i.forecast is a dictionary (a JSON object), and forecast["days"] is a list of dictionaries, one for each day (a JSON array).
  • ii.The place and the number of days, the two days over 40 km/h, then the last day (index −1) and its rain:

Output

Jomsom 3Mon windy: 52 km/hTue windy: 45 km/hTue 0
Marking scheme
  • i. A dictionary, and a list of dictionaries.
  • ii. The four lines: Jomsom 3, Mon 52, Tue 45, and Tue 0.
3.
[2]

A breadth-first search over a map of 1,000 villages and 2,500 trails takes about a second. Roughly how long would it take on a map twice as big, 2,000 villages and 5,000 trails? Explain why.

Answer

About 2 seconds. Each village is visited once (it is marked as seen when it is first added, and never added again), and each village’s list of neighbors is read once, so every trail is looked at a fixed number of times. The work grows in step with the number of villages and trails, linear growth: twice the map, about twice the work.

Marking scheme
  • About twice as long (2 seconds).
  • Each village is visited once and each list of neighbors read once, so the work grows in step with the size (linear).
4.
[2]

The weather office keeps daily rainfall in a table, rain (station TEXT, day TEXT written like 2026-07-14, mm REAL). Write an SQL query that gives the average daily rainfall at Pokhara from 1 to 15 July 2026, and one that lists the days in those two weeks when it rained more than 100 mm there, the wettest first.

Answer
SELECT AVG(mm) FROM rainWHERE station = 'Pokhara' AND day BETWEEN '2026-07-01' AND '2026-07-15'; SELECT day, mm FROM rainWHERE station = 'Pokhara' AND day BETWEEN '2026-07-01' AND '2026-07-15' AND mm > 100ORDER BY mm DESC;

BETWEEN includes both ends, and dates written year-month-day sort in the right order as text.

Marking scheme
  • AVG(mm) with station = 'Pokhara' and day BETWEEN '2026-07-01' AND '2026-07-15'.
  • The second query adds mm > 100 and ORDER BY mm DESC.
5.
[2]

The rain at Pokhara on the first eight days of Shrawan is in pokhara_shrawan.csv:

pokhara_shrawan.csv

day,mm1,42.52,118.03,7.04,0.05,96.56,151.07,23.08,64.0
  • i.Write pandas lines that read the file and print the rows of the three wettest days, the wettest first, and write what they print.
  • ii.What are the numbers at the left of each row, and why aren’t they 0, 1 and 2?
Answer

i.

import pandas as pd rain = pd.read_csv("pokhara_shrawan.csv")print(rain.sort_values("mm", ascending=False).head(3))

Output

   day     mm5    6  151.01    2  118.04    5   96.5

ii. They are the table’s index, the place each row had in the file, counted from 0: day 6 was row 5. sort_values gives back the same rows in a new order, and each row keeps its own index, so they no longer go 0, 1, 2.

Marking scheme
  • i. sort_values("mm", ascending=False) then head(3), printing days 6, 2 and 5 (151.0, 118.0, 96.5).
  • ii. The index: each row keeps the place it had in the file when the rows are sorted.
6.
[2]

Puja, at the weather office in Jumla, writes on the forum of the program that draws the office’s rain charts: “chart program not working plz help”. A day later, nobody has given her a useful answer.

  • i.Why are helpers unlikely to answer a question like hers?
  • ii.What four things should a better question tell them?
Answer
  • i.Nobody can see her computer, and her question tells them nothing: not what she was doing, what went wrong or what she tried. Almost any cause fits, so a helper would have to ask many questions before even starting, and most people pass over a question that is hard to answer.
  • ii.What she was trying to do and what she expected; what happened instead, with the exact error message (copied, or a screenshot with personal details covered); what she has already tried, and what each try did; and her device, operating system and the program’s version. (Often, writing all this makes her see the answer herself.)
Marking scheme
  • i. It says nothing about what she did, what happened or what she tried, so helpers can’t tell the cause and would have to ask first.
  • ii. The four: what she tried to do and expected; what happened, with the exact error; what she already tried; device, system and version.
7.
[2]

The weather office’s laptop says its disk is full. Its storage settings show:

What Size
Downloads: old installers and a film 9 GB
Recycle Bin, not emptied 4 GB
The station records since 2015 (the only copy) 6 GB
Programs in use 18 GB
  • i.Which two can be freed safely to make about 13 GB of space, and why are they safe?
  • ii.What should they do with the station records before deleting anything of them?
Answer
  • i.The Recycle Bin (4 GB: files already deleted still take space until it is emptied) and the Downloads (9 GB: installers can be downloaded again, and the film isn’t the office’s work). 4 + 9 = 13 GB.
  • ii.Never delete the only copy. Copy them to another disk or the cloud, check that the copy opens, and only then think about removing them from the laptop (better, keep a copy in two places).
Marking scheme
  • i. The Recycle Bin and the Downloads (13 GB), safe because the bin holds deleted files and installers can be fetched again.
  • ii. Copy the records elsewhere and check the copy opens before deleting anything (they are the only copy).
8.
[2]

A language model is writing a weather warning and has reached: “After the night’s rain, the road between the two villages ___”. The next word should be is, not are.

  • i.Why might a model that looks back only 2 words write “are”?
  • ii.How does a transformer’s attention help it write “is”?
Answer
  • i.It sees only “two villages”. After those words, “are” is the commoner next word in its training text, and the word that decides, “road”, is five words back, out of its sight. Each step is likely, so the sentence sounds right but is wrong.
  • ii.A transformer uses attention: for each new token it looks back over all the tokens in its context window and weighs those that matter most. It has learned to link the place of the verb to its subject, “road” (as it learned to link “its” to the noun it refers to), so it writes “is”.
Marking scheme
  • i. Looking back 2 words it sees only “two villages”, after which “are” is common; “road”, which decides, is out of its sight.
  • ii. Attention looks back over all the earlier tokens in its context and weighs those that matter, here “road”, so it writes “is”.
9.
[2]

A bank is about to put a chatbot on its website to answer customers’ questions about loans and fees. To be safe, the manager plans to write under it: “This chatbot can make mistakes. The bank is not responsible for its answers.” Judge the plan, and say what the bank should do instead.

Answer

The note doesn’t make the plan safe. The bank chooses to put the chatbot on its own website to answer customers, so what it says is information from the bank, like any other page there. In the Air Canada case (2024), the airline argued that its chatbot was responsible for its own words; the tribunal held the airline responsible for all the information on its website, chatbot included. And a customer can’t tell which answers are the wrong ones, while a wrong answer about fees costs real money. Instead, the bank should have the chatbot answer from its official fee pages (grounding), test it before use with real customers’ questions whose answers are checked against its rules, show the official fees with each answer, and honor or put right its mistakes.

Marking scheme
  • The note doesn’t move the responsibility: the bank chose to put the chatbot there, so its answers are the bank’s (as the tribunal held against Air Canada), and customers can’t tell which are wrong.
  • Instead: answer from its official fee pages, test it on checked questions before use, show the official fees, and put right its mistakes.
10.
[2]

What is OpenStreetMap, and how did volunteers use it after the 2015 earthquake?

Answer

OpenStreetMap is a free map of the world that anyone can edit, like Wikipedia. After the earthquake of 25 April 2015, Kathmandu Living Labs and the Humanitarian OpenStreetMap Team split the affected areas into small squares on a website; thousands of volunteers, in Nepal and around the world, each took a square and traced roads and buildings from satellite photos, and mappers in Nepal added names, paths and blocked roads. Aid teams used the maps to reach damaged villages.

Marking scheme
  • A free map of the world that anyone can edit.
  • After the earthquake, volunteers traced roads and buildings from satellite photos, square by square, and aid teams used the maps.
11.
[2]

A hydropower company in Sankhuwasabha is installing small computers that log the river’s flow and the turbines’ temperature. They count time as seconds since 1970 in a signed 32-bit number. The manager says: “That runs out in 2038. That’s twelve years away; we’ll deal with it then.” Judge his decision.

Answer

It is a poor decision. A signed 32-bit count of seconds since 1970 overflows in January 2038, and the logger will then think it is 1901, so its dates, and anything worked out from them (how long a turbine ran, when a reading was taken), go wrong. Small computers in machines are often left running for decades, so the loggers installed now will very likely still be in use in 2038, and finding every one later, inside a dam, will cost far more than choosing devices that store time in 64 bits today. The Year 2000 problem showed that programs and devices outlive everyone’s expectations: design for longer than you think it will last.

Marking scheme
  • At the overflow the loggers’ dates go wrong (back to 1901), and devices like these often run for decades, so they will still be there in 2038.
  • Fixing it now (64-bit time) is far cheaper than finding every device later; design for longer than expected, as Y2K showed.

Section C

5 × 4 = 20

Write long answers to the following questions.

12.
[4]

The weather office in Pokhara wants a module, rainfall.py, that summarizes a week of daily rain. Python’s standard library module statistics has statistics.mean() and statistics.median(); each raises statistics.StatisticsError when given an empty list.

  • i.The module’s documentation says that statistics.median() of an even number of values gives the mean of the two middle values. What does statistics.median([30, 0, 4, 10]) give? (1)
  • ii.Write rainfall.py with a function summary(daily) that returns the mean (rounded to 1 decimal place), the median and the number of heavy days (50 mm or more), or None for an empty list. Name the 50 mm as a constant, and write a docstring. (2)
  • iii.Write a main program that prints the summary of Pokhara’s week, [12.5, 0, 64.0, 30.5, 0, 8.0, 51.5], or “No readings” when there is none. Write what it prints. (1)
Answer

i. In order the values are 0, 4, 10, 30; the two middle ones are 4 and 10, and their mean is 7.0 (the median sorts the values itself).

ii.

rainfall.py

"""Summaries of daily rainfall."""import statistics HEAVY = 50      # mm in a day, or more, counts as a heavy day  def summary(daily):    """Given a list of daily rain in mm, return (mean rounded to 1 decimal,    median, number of heavy days), or None if the list is empty."""    try:        mean = statistics.mean(daily)    except statistics.StatisticsError:        return None    heavy = 0    for mm in daily:        if mm >= HEAVY:            heavy = heavy + 1    return round(mean, 1), statistics.median(daily), heavy  if __name__ == "__main__":    print(summary([]), "should be None")    print(summary([10, 50, 60]), "should be (40, 50, 2)")

iii.

import rainfall result = rainfall.summary([12.5, 0, 64.0, 30.5, 0, 8.0, 51.5])if result is None:    print("No readings")else:    mean, median, heavy = result    print("Mean", mean, "mm, median", median, "mm,", heavy, "heavy days")

Output

Mean 23.8 mm, median 12.5 mm, 2 heavy days

The 7 days add up to 166.5 mm, a mean of 23.79; in order the middle value is 12.5; 64.0 and 51.5 are heavy.

Marking scheme
  • i. 7.0: sorted, the middle two are 4 and 10, and their mean is 7.0.
  • ii. Uses statistics.mean and statistics.median, counts days of 50 mm or more using a constant, and returns the three as a tuple.
  • ii. Catches statistics.StatisticsError (or checks for an empty list) and returns None; has a docstring.
  • iii. Imports the module, unpacks the tuple, handles None, and prints mean 23.8, median 12.5, 2 heavy days.
13.
[4]

Six weather stations pass their readings to each other by radio. The weather office keeps the links as a table of 0s and 1s: 1 where two stations can talk directly, both ways.

Kathmandu Hetauda Bharatpur Damauli Pokhara Butwal
Kathmandu 0 1 0 1 0 0
Hetauda 1 0 1 0 0 0
Bharatpur 0 1 0 1 0 1
Damauli 1 0 1 0 1 0
Pokhara 0 0 0 1 0 1
Butwal 0 0 1 0 1 0
  • i.Write the links as a Python dictionary of neighbors, each list in the table’s order. (1)
  • ii.Do a breadth-first search from Kathmandu by hand: a row for each visit, with the station, its hops from Kathmandu and the list still to visit. How many hops does a reading from Butwal need to reach Kathmandu, and through which stations? (2)
  • iii.The office will add its 2,000 rain gauges, each linked to about 3 others. Why should its program keep a dictionary of neighbors rather than such a table? (1)
Answer

i. Each row’s 1s, in order:

links = {    "Kathmandu": ["Hetauda", "Damauli"],    "Hetauda": ["Kathmandu", "Bharatpur"],    "Bharatpur": ["Hetauda", "Damauli", "Butwal"],    "Damauli": ["Kathmandu", "Bharatpur", "Pokhara"],    "Pokhara": ["Damauli", "Butwal"],    "Butwal": ["Bharatpur", "Pokhara"],}

ii. Each station is noted when it is added, so none is added twice:

Visit Hops List still to visit, front first
Kathmandu 0 Hetauda, Damauli
Hetauda 1 Damauli, Bharatpur
Damauli 1 Bharatpur, Pokhara
Bharatpur 2 Pokhara, Butwal
Pokhara 2 Butwal
Butwal 3 (empty)

Butwal is 3 hops away: Butwal → Bharatpur → Hetauda → Kathmandu. (Butwal → Bharatpur → Damauli → Kathmandu, or Butwal → Pokhara → Damauli → Kathmandu, are 3 hops too.)
iii. The table would have 2,000 × 2,000 = 4 million cells, almost all 0, since each row has only about three 1s, and finding a gauge’s neighbors would mean reading a whole row of 2,000. A dictionary stores only the links that exist (about 3 names for each gauge) and finds a gauge’s neighbors in one lookup.

Marking scheme
  • i. A dictionary with each station’s list of neighbors, the 1s of its row.
  • ii. The visits in order: Kathmandu; Hetauda, Damauli; Bharatpur, Pokhara; Butwal, with their hops.
  • ii. Butwal is 3 hops away, through Bharatpur and Hetauda (or another 3-hop route).
  • iii. The table needs 4 million cells, almost all 0, and a whole row to read; the dictionary keeps only the links and finds neighbors in one lookup.
14.
[4]

The weather office keeps its stations and some daily readings in two tables.

stations

station_id name height_m
1 Pokhara 827
2 Jumla 2,366
3 Biratnagar 72
4 Jomsom 2,744

readings

reading_id station_id day max_temp rain_mm
1 1 2026-07-10 30.5 88.0
2 2 2026-07-10 23.0 6.5
3 3 2026-07-10 33.5 41.0
4 1 2026-07-11 29.0 112.5
5 2 2026-07-11 24.5 0.0
6 3 2026-07-11 34.0 12.0

Write what each query gives.

  • i.SELECT name FROM stations WHERE height_m > 2000 ORDER BY height_m DESC; (1)
  • ii.SELECT station_id, MAX(max_temp) FROM readings GROUP BY station_id; (1)
  • iii.(1)
SELECT stations.name, readings.rain_mmFROM readingsJOIN stations ON readings.station_id = stations.station_idWHERE readings.day = '2026-07-11' AND readings.rain_mm > 10;

iv. A new clerk wants to write days as 11/07/2026 (day/month/year) instead of 2026-07-11. Why would ORDER BY day and BETWEEN then give wrong answers? (1)

Answer
  • i.The stations above 2,000 m, the highest first: Jomsom, then Jumla.
  • ii.Each station’s hottest reading:
station_id MAX(max_temp)
1 30.5
2 24.5
3 34.0
  • iii.The stations with more than 10 mm of rain on 11 July: Pokhara 112.5 and Biratnagar 12.0 (Jumla had 0).
  • iv.Dates as text are compared character by character from the left. With the day first, they would sort by the day of the month: 02/08/2026 (2 August) would come before 11/07/2026 (11 July). And BETWEEN '01/07/2026' AND '15/07/2026' would also catch 05/08/2026, 5 August, since “05/08” falls between “01/07” and “15/07” as text. Written year-month-day, the biggest part comes first, so the order of the text is the order of the dates.
Marking scheme
  • i. Jomsom, then Jumla.
  • ii. 1: 30.5, 2: 24.5, 3: 34.0.
  • iii. Pokhara 112.5 and Biratnagar 12.0.
  • iv. Text is compared from the left, so with the day first, dates sort by day, not by date, and BETWEEN catches days from other months.
15.
[4]

A news website draws a line chart of the rain in July at Kathmandu airport each year from 2016 to 2025, from the weather office’s rain gauge there. The line goes down, with ups and downs along the way. Its headline says: “The monsoon is getting weaker all over Nepal.”

  • i.What question does the chart really answer? (1)
  • ii.Where does its data come from, and what does that mean for the headline? (1)
  • iii.How sure can such a chart be? (1)
  • iv.Name one thing it leaves out, and write a more honest headline. (1)
Answer
  • i.Only how the July rain at one gauge, Kathmandu airport, changed over these ten years. It doesn’t say why, and it says nothing about the rest of Nepal.
  • ii.From one rain gauge in one place. Rain in Nepal differs enormously from place to place (Pokhara gets several times as much as Mustang), and one gauge can’t speak for all of Nepal.
  • iii.Not very: it has only 10 values, one a year, and the rain in one month changes a lot from year to year by chance, so a line that goes down over ten years could be chance. Many more years, and the spread from year to year, would be needed.
  • iv.Any one: the other months of the monsoon (June to September); every other station; anything earlier than 2016. Honest: “July rain at Kathmandu airport was lower in recent years; one gauge and ten years can’t show whether Nepal’s monsoon is changing.”
Marking scheme
  • i. How July rain at one gauge changed over 10 years (not all Nepal, not why).
  • ii. One gauge in one place, while rain varies hugely across Nepal, so it can’t support “all over Nepal”.
  • iii. Only 10 values, which vary a lot by chance, so a downward line may be chance.
  • iv. Something left out (other months, other stations, earlier years) and a careful headline.
16.
[4]

Read the given passage and answer the questions that follow.

A weather service runs its forecasts on thousands of computers in a data center. In a month, the whole data center uses 15 million units of electricity, and its computers 10 million of them. Most of the rest goes to cooling. The service is choosing where to build its next data center: by a coal power station in a hot plain, or in a cool place with hydropower.

  • i.Why does a data center need so much electricity besides what its computers use? (1)
  • ii.What is PUE? Work out this data center’s PUE. (1)
  • iii.Give one reason why a cool place helps. (1)
  • iv.Why does the kind of power station matter, though the electricity is the same? (1)
Answer
  • i.Almost all the electricity a computer uses ends up as heat, which must be taken away or the computers overheat, so the data center uses electricity again for cooling (and for lights, batteries and losses in its wiring).
  • ii.Power usage effectiveness: the electricity used by the whole data center divided by the electricity used by its computers. Here 15 ÷ 10 = 1.5: for every 100 units the computers use, 50 more go to cooling and the rest.
  • iii.Cool outside air or cold water can take the heat away instead of air conditioning, which uses much less electricity (a lower PUE).
  • iv.Electricity from coal puts out a great deal of CO₂ (and smoke for the people nearby); hydropower puts out very little. The same number of units can do very different harm depending on how they were made.
Marking scheme
  • i. Computers turn electricity into heat, so more electricity is needed for cooling.
  • ii. PUE = whole data center ÷ computers; 15 ÷ 10 = 1.5.
  • iii. Cool air or water can cool it with less electricity.
  • iv. Coal power puts out much CO₂ (and smoke), hydropower very little.

Practical exam

25 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]

Monsoon totals. A rain gauge’s weekly readings are kept as (month, mm) pairs, several for each month.

At the computer, make two files in one folder:

  • monsoon.py, a module with a function monthly_totals(weekly) that returns a dictionary from each month to its total rain, with a docstring, and tests at the end that run only when monsoon.py itself is run (including an empty list, which gives an empty dictionary);
  • main.py, which imports it, works out the totals for the readings below, prints every month’s total, and then the months with more than 500 mm.
weekly = [("Jestha", 120.5), ("Asar", 310.0), ("Asar", 295.5), ("Shrawan", 402.0),          ("Shrawan", 380.5), ("Bhadra", 260.0), ("Bhadra", 190.0), ("Jestha", 88.0)]

Run monsoon.py, then main.py, in front of the teacher.

Answer

monsoon.py

"""Monthly rain totals from weekly readings."""  def monthly_totals(weekly):    """Given (month, mm) pairs, return a dictionary from each month    to its total mm, in the order the months first appear."""    totals = {}    for month, mm in weekly:        if month not in totals:            totals[month] = 0        totals[month] = totals[month] + mm    return totals  if __name__ == "__main__":    print(monthly_totals([]), "should be {}")    print(monthly_totals([("Asar", 10), ("Asar", 5), ("Shrawan", 2)]), "should be Asar 15, Shrawan 2")

Run by itself, monsoon.py prints its tests:

Output

{} should be {}{'Asar': 15, 'Shrawan': 2} should be Asar 15, Shrawan 2

main.py

import monsoon weekly = [("Jestha", 120.5), ("Asar", 310.0), ("Asar", 295.5), ("Shrawan", 402.0),          ("Shrawan", 380.5), ("Bhadra", 260.0), ("Bhadra", 190.0), ("Jestha", 88.0)] totals = monsoon.monthly_totals(weekly)for month in totals:    print(month, totals[month], "mm") print("Over 500 mm:")for month in totals:    if totals[month] > 500:        print(month)

Output

Jestha 208.5 mmAsar 605.5 mmShrawan 782.5 mmBhadra 450.0 mmOver 500 mm:AsarShrawan

(The readings are made up for this paper.)

Marking scheme
  • monsoon.py has a function monthly_totals(weekly) that returns a dictionary (it doesn’t print).
  • Starts a month at 0 (or with its first value) the first time it appears.
  • Adds each week’s mm to its month’s total.
  • A docstring that says what it takes and returns.
  • Tests under if __name__ == "__main__":, with the empty list among them, which don’t run when it is imported.
  • main.py imports monsoon and prints every month’s total (Jestha 208.5, Asar 605.5, Shrawan 782.5, Bhadra 450.0).
  • main.py prints only Asar and Shrawan as over 500 mm, run in front of the teacher.
P2.
[6]

Landslides. A district disaster office records the landslides in some municipalities of Sindhupalchok and Dolakha. This program makes the database and gives you ask(), which prints what a query gives. Run it, then add one ask() for each question:

  • i.The landslides in July 2026: the slide_id, muni_id and houses damaged, the earliest first. (2)
  • ii.Each municipality’s muni_id, with its number of landslides and the total houses damaged, in order of muni_id. (2)
  • iii.The landslides that blocked a road in Sindhupalchok: the municipality’s name and the day, the earliest first. (2)
import sqlite3 db = sqlite3.connect(":memory:")db.execute("CREATE TABLE municipalities (muni_id INTEGER PRIMARY KEY, name TEXT, district TEXT)")db.execute("""CREATE TABLE landslides (slide_id INTEGER PRIMARY KEY,              muni_id INTEGER REFERENCES municipalities(muni_id),              day TEXT, houses INTEGER, road_blocked INTEGER)""")db.executemany("INSERT INTO municipalities VALUES (?, ?, ?)", [    (1, "Jugal", "Sindhupalchok"),    (2, "Melamchi", "Sindhupalchok"),    (3, "Bhimeshwar", "Dolakha"),    (4, "Kalinchok", "Dolakha"),    (5, "Sunkoshi", "Sindhupalchok"),])db.executemany("INSERT INTO landslides VALUES (?, ?, ?, ?, ?)", [    (1, 2, "2026-06-28", 4, 1),    (2, 1, "2026-07-03", 0, 1),    (3, 3, "2026-07-05", 2, 0),    (4, 2, "2026-07-19", 7, 1),    (5, 5, "2026-08-02", 1, 0),    (6, 4, "2026-08-10", 3, 1),    (7, 2, "2026-08-21", 0, 0),    (8, 3, "2026-09-02", 5, 1),])  def ask(sql):    """Print each row the query gives, then a blank line."""    for row in db.execute(sql):        print(row)    print()  ask("SELECT * FROM municipalities")

(road_blocked is 1 for yes and 0 for no.)

Answer

The same program, with these three lines in place of the last one:

import sqlite3 db = sqlite3.connect(":memory:")db.execute("CREATE TABLE municipalities (muni_id INTEGER PRIMARY KEY, name TEXT, district TEXT)")db.execute("""CREATE TABLE landslides (slide_id INTEGER PRIMARY KEY,              muni_id INTEGER REFERENCES municipalities(muni_id),              day TEXT, houses INTEGER, road_blocked INTEGER)""")db.executemany("INSERT INTO municipalities VALUES (?, ?, ?)", [    (1, "Jugal", "Sindhupalchok"),    (2, "Melamchi", "Sindhupalchok"),    (3, "Bhimeshwar", "Dolakha"),    (4, "Kalinchok", "Dolakha"),    (5, "Sunkoshi", "Sindhupalchok"),])db.executemany("INSERT INTO landslides VALUES (?, ?, ?, ?, ?)", [    (1, 2, "2026-06-28", 4, 1),    (2, 1, "2026-07-03", 0, 1),    (3, 3, "2026-07-05", 2, 0),    (4, 2, "2026-07-19", 7, 1),    (5, 5, "2026-08-02", 1, 0),    (6, 4, "2026-08-10", 3, 1),    (7, 2, "2026-08-21", 0, 0),    (8, 3, "2026-09-02", 5, 1),])  def ask(sql):    """Print each row the query gives, then a blank line."""    for row in db.execute(sql):        print(row)    print()  ask("SELECT slide_id, muni_id, houses FROM landslides WHERE day LIKE '2026-07%' ORDER BY day")ask("SELECT muni_id, COUNT(*), SUM(houses) FROM landslides GROUP BY muni_id ORDER BY muni_id")ask("""SELECT municipalities.name, landslides.day FROM landslides       JOIN municipalities ON landslides.muni_id = municipalities.muni_id       WHERE landslides.road_blocked = 1 AND municipalities.district = 'Sindhupalchok'       ORDER BY landslides.day""")

Output

(2, 1, 0)(3, 3, 2)(4, 2, 7) (1, 1, 0)(2, 3, 11)(3, 2, 7)(4, 1, 3)(5, 1, 1) ('Melamchi', '2026-06-28')('Jugal', '2026-07-03')('Melamchi', '2026-07-19')

day BETWEEN '2026-07-01' AND '2026-07-31' is right for i too. (The landslides are made up for this paper.)

Marking scheme
  • i. Picks July’s rows (LIKE '2026-07%' or BETWEEN), selecting slide_id, muni_id and houses.
  • i. ORDER BY day, giving slides 2, 3 and 4.
  • ii. GROUP BY muni_id with COUNT(*) and SUM(houses).
  • ii. Ordered by muni_id, giving five rows, such as Melamchi’s 2 with 3 landslides and 11 houses.
  • iii. A JOIN of landslides and municipalities ON landslides.muni_id = municipalities.muni_id.
  • iii. Both conditions (road_blocked = 1, Sindhupalchok), by day: Melamchi, Jugal, Melamchi.
P3.
[6]

Snowed-in trails. A rescue team in Solukhumbu plans routes on the trails below (simplified). In winter, snow can close villages: no route may pass through a closed one. Write a function fewest_steps(graph, start, goal, closed) that returns the villages on a route with the fewest trails that passes through no village in the list closed, or None if there is none. Then print:

  • the route from Lukla to Gokyo, with nothing closed;
  • the route from Lukla to Gokyo when Khumjung is closed;
  • the route from Lukla to Lobuche when Pangboche is closed (or “no way” if there is none).
trails = {    "Lukla": ["Phakding"],    "Phakding": ["Lukla", "Namche"],    "Namche": ["Phakding", "Khumjung", "Thame", "Tengboche"],    "Khumjung": ["Namche", "Phortse", "Dole"],    "Thame": ["Namche"],    "Tengboche": ["Namche", "Pangboche", "Phortse"],    "Phortse": ["Khumjung", "Tengboche", "Dole"],    "Pangboche": ["Tengboche", "Dingboche"],    "Dingboche": ["Pangboche", "Lobuche"],    "Lobuche": ["Dingboche"],    "Dole": ["Khumjung", "Phortse", "Machhermo"],    "Machhermo": ["Dole", "Gokyo"],    "Gokyo": ["Machhermo"],} # Write fewest_steps here
Answer
trails = {    "Lukla": ["Phakding"],    "Phakding": ["Lukla", "Namche"],    "Namche": ["Phakding", "Khumjung", "Thame", "Tengboche"],    "Khumjung": ["Namche", "Phortse", "Dole"],    "Thame": ["Namche"],    "Tengboche": ["Namche", "Pangboche", "Phortse"],    "Phortse": ["Khumjung", "Tengboche", "Dole"],    "Pangboche": ["Tengboche", "Dingboche"],    "Dingboche": ["Pangboche", "Lobuche"],    "Lobuche": ["Dingboche"],    "Dole": ["Khumjung", "Phortse", "Machhermo"],    "Machhermo": ["Dole", "Gokyo"],    "Gokyo": ["Machhermo"],}  def fewest_steps(graph, start, goal, closed):    """The villages on a route with the fewest trails that avoids    every village in closed, or None if there is none."""    came_from = {start: None}    to_visit = [start]    while len(to_visit) > 0:        village = to_visit.pop(0)        if village == goal:            route = []            while village is not None:                route.append(village)                village = came_from[village]            route.reverse()            return route        for nxt in graph[village]:            if nxt not in came_from and nxt not in closed:                came_from[nxt] = village                to_visit.append(nxt)    return None  for goal, closed in [("Gokyo", []), ("Gokyo", ["Khumjung"]), ("Lobuche", ["Pangboche"])]:    route = fewest_steps(trails, "Lukla", goal, closed)    if route is None:        print("Lukla to", goal, "with", closed, "closed: no way")    else:        print(" → ".join(route), "(" + str(len(route) - 1), "trails)")

Output

Lukla → Phakding → Namche → Khumjung → Dole → Machhermo → Gokyo (6 trails)Lukla → Phakding → Namche → Tengboche → Phortse → Dole → Machhermo → Gokyo (7 trails)Lukla to Lobuche with ['Pangboche'] closed: no way
Marking scheme
  • A function with the graph, start, goal and the closed list, with a queue that starts with the start.
  • A queue: takes from the front with pop(0) and adds to the back with append(), marking a village as seen when it is added.
  • Never adds a village in closed (nxt not in closed).
  • Follows the notes back from the goal and reverses them to give the route.
  • Prints the 6-trail route, and the 7-trail route by Tengboche and Phortse with Khumjung closed.
  • Returns None when the queue runs out, and prints “no way” for Lobuche.
P4.
[6]

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

  • i.In main.py, what does for month in totals give you each time round, and how do you get that month’s total? Why does Jestha come first in your output, though its second reading is the last in the list? (2)
  • ii.In your first query, what does LIKE '2026-07%' match? What would '2026-07-_' match instead? (2)
  • iii.What does your function give for Lukla to Gokyo when Gokyo itself is closed? And when Lukla, the start, is closed? Is that right, and how would you fix it? (2)
Answer
  • i.It gives each key, a month’s name, one at a time, and totals[month] gives that month’s total. A dictionary keeps its keys in the order they were first added: Jestha was added by the first reading, and its second reading only added to the total already there.
  • ii.% matches any number of characters (none too), so it matches every day starting with 2026-07, all of July. _ matches exactly one character, so '2026-07-_' would match only a day such as 2026-07-5, written with one digit, which none of ours is: it would find nothing.
  • iii.With Gokyo closed, it is never added to the list, so the list runs out and the function returns None: “no way”, which is right. With Lukla closed, nothing changes: the start is put in came_from and the list before any check, so it still gives the 6-trail route. If a closed start means nobody can set out, that is wrong: check it first, if start in closed: return None.
Marking scheme
  • i. Each key (a month), with its total from totals[month].
  • i. Keys stay in the order first added, and a second reading only adds to the total.
  • ii. % matches any number of characters: every day of July.
  • ii. _ matches exactly one character, so it would match none of these days.
  • iii. A closed goal is never added, so it returns None; a closed start isn’t checked, so a route is still given.
  • iii. Fix with a check at the start: if start in closed: return None.

Your score

0 / 50 theory

0 / 25 practical

29 questions not marked yet

Section A–Full marks 10
Section B–Full marks 20
Section C–Full marks 20
Practical exam–Full marks 25

Marks lost, by unit

Mark a question to see your score here.

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