Skip to content

← Final exam model papers

Final Exam Model Paper 4

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.

Which of these modules is part of Python’s standard library, so that it needs no installing?

Pick an answer to see why.

b.

A school club’s app in Gorkha suggests new friends: someone who isn’t your friend yet, with the most friends in common with you. Who is friends with whom:

friends = {    "Anu": ["Bibek", "Chiran", "Deepa"],    "Bibek": ["Anu", "Chiran", "Gita"],    "Chiran": ["Anu", "Bibek", "Gita", "Hari"],    "Deepa": ["Anu"],    "Gita": ["Bibek", "Chiran"],    "Hari": ["Chiran"],}

Whom does the app suggest to Anu?

Pick an answer to see why.

c.

What is a database’s data dictionary?

Pick an answer to see why.

d.

Rajan asked 12 students in his class, 6 boys and 6 girls, which sport they like most. 5 boys and 2 girls chose football. He concludes: “This proves that in Nepal boys like football more than girls do.” Which judgment is right?

Pick an answer to see why.

e.

A municipality’s office keeps a small server running day and night, all year. It uses 300 W (0.3 kW). How much electricity does it use in a year (8,760 hours)?

Pick an answer to see why.

f.

Which command shows what is inside a text file, such as notes.txt, in the terminal?

Pick an answer to see why.

g.

When is a language model’s answer called a hallucination?

Pick an answer to see why.

h.

Rekha pastes the school’s notice about the Dashain holidays into a chatbot and asks: “Using only this notice, on which day does school open again?” Why is this answer more likely to be right than asking the question with no notice?

Pick an answer to see why.

i.

A ward’s new app needs a smartphone, data every time, English, sight of the screen, and a monthly fee. Hari is blind; he has a smartphone and data and reads English with his phone’s screen reader. Which one design change would let him use the app?

Pick an answer to see why.

j.

Delivery by drone is new in Nepal. A minister says: “We should make no rules for drone delivery for ten years, until we fully understand it.” Which judgment is best?

Pick an answer to see why.

Section B

10 × 2 = 20

Write short answers to the following questions.

2.
[2]

For sports day, each class teacher in a school in Bhojpur typed the number of students in her class on a form. A program adds them up:

typed = ["42", "38", "", "4l", "45"]total = 0for text in typed:    try:        n = int(text)    except ValueError:        print("Not a number: [" + text + "]")    else:        total = total + nprint("Total:", total)
  • i.Write the output.
  • ii.What would happen if the program used total = total + int(text) with no try?
Answer

i. int("") and int("4l") (a small L, not a 1) raise ValueError, so the except part prints a message for each; for the others the else part adds the number: 42 + 38 + 45 = 125.

Output

Not a number: []Not a number: [4l]Total: 125

ii. The program would stop with an error at the empty text, ValueError: invalid literal for int() with base 10: '', and print no total at all.

Marking scheme
  • i. The two messages, for the empty text and for 4l, and Total: 125.
  • ii. It would stop with a ValueError at the empty text (no total).
3.
[2]

Sunil is making a Tihar poster in a drawing app. He taps the paint bucket inside the outline of a diyo, and the inside of the diyo turns orange, but nothing outside it does. Explain how this flood fill is a graph search: what are the nodes and the edges, and why does the paint stop at the outline?

Answer

Each square (pixel) of the picture is a node. An edge joins a square to each neighbor above, below, left and right that has the same color. Breadth-first search starts from the tapped square and paints every square it can reach, ring by ring. The outline’s squares are a different color, so there is no edge across the outline: the search can’t reach the squares outside, and they stay as they were. (If the outline has a gap, the paint leaks out through it.)

Marking scheme
  • Nodes are the squares; edges join neighboring squares of the same color; the search paints every square reachable from the tapped one.
  • The outline is another color, so no edge crosses it and the search can’t reach the outside.
4.
[2]

A chess club in Nepalgunj keeps its members in a table, members:

member_id name grade rating
1 Aayan Khan 9 1210
2 Bandana Tharu 10 1340
3 Chetan Oli 8 1105
  • i.Write the SQL to add a new member: Dipika Shah, member 4, Grade 9, rating 1000.
  • ii.Chetan wins a tournament and his rating becomes 1180. Write the SQL to change it.
Answer

i.

INSERT INTO members VALUES (4, 'Dipika Shah', 9, 1000);

ii.

UPDATE members SET rating = 1180 WHERE member_id = 3;

The WHERE picks out Chetan’s row by its primary key. Without it, every member’s rating would become 1180.

Marking scheme
  • i. INSERT INTO members VALUES (4, 'Dipika Shah', 9, 1000); with the name in quotes.
  • ii. UPDATE members SET rating = 1180 WHERE member_id = 3; (WHERE by the key, or the name).
5.
[2]

A school in Dailekh gives every student free textbooks. students.csv lists the students, and books.csv the students who have collected them:

students.csv

roll,name1,Asha2,Bimal3,Chitra4,Dilu5,Esha

books.csv

roll,collected1,2026-04-203,2026-04-214,2026-04-21

Write a program with pandas that joins the two, keeping every student, and prints the names of the students who haven’t collected their books. Write what it prints.

Answer
import pandas as pd students = pd.read_csv("students.csv")books = pd.read_csv("books.csv")both = students.merge(books, on="roll", how="left")print(both[both["collected"].isna()]["name"])

Output

1    Bimal4     EshaName: name, dtype: str

how="left" keeps every student, and leaves collected missing for those with no row in books.csv; isna() picks them out. A plain merge would drop Bimal and Esha, the very students the school is looking for.

Marking scheme
  • merge on roll with how="left", so every student is kept.
  • Picks the rows where collected is missing (isna()): Bimal and Esha.
6.
[2]

Pema’s slideshow program worked yesterday. Today she copied 16 new photos into its folder, and now it stops at once. She suspects one of the photos is broken. Explain how she can find it in at most 4 tries, and why this works.

Answer

Take half of the new photos (8) out of the folder and run the program. If it works, the broken photo is among the 8 taken out; if it still stops, it is among the 8 left in. Either way, 8 photos are ruled out. Repeat with the 8 suspects: 4, then 2, then 1. 16 → 8 → 4 → 2 → 1 is 4 tries. It works because each test splits what is still possible into two halves, so either result rules out half, like binary search. Trying the photos one at a time could take 16 tries.

Marking scheme
  • Remove half the photos and test; the result shows which half holds the broken one; repeat with that half (16, 8, 4, 2, 1).
  • Each test rules out half (binary search), so 4 tests are enough instead of up to 16.
7.
[2]

Ramila typed these commands in her class10 folder. Explain each error, and write the command she meant.

Output

ramila@lab-pc:~/class10$ lsmarks.csv  quiz.pyramila@lab-pc:~/class10$ pyhton3 quiz.pybash: pyhton3: command not foundramila@lab-pc:~/class10$ cd quiz.pybash: cd: quiz.py: Not a directory
Answer

pyhton3: command not found: there is no program with that name: she misspelled python3. She meant python3 quiz.py.
Not a directory: quiz.py is a file, and cd can only go into a folder. She probably wanted to see what is in it: cat quiz.py (or to run it, with python3 quiz.py).

Marking scheme
  • command not found: no program by that name, a misspelling; python3 quiz.py.
  • Not a directory: quiz.py is a file, not a folder; cat quiz.py (or python3 quiz.py).
8.
[2]

A base model, trained only on a huge amount of text from the internet, is given: “Write a notice about the school’s sports day.” Instead of a notice, it writes: “Write a notice about the school’s prize day. Write a notice about the parents’ meeting. …”

  • i.Why does it do this?
  • ii.What is done to turn a base model into a chatbot that answers?
Answer
  • i.Pretraining taught it one thing: to carry on text in the style of what it was given. On the internet, a line like this is often one of a list of exercises, followed by more of the same, so more requests are the likely continuation. It was never taught to answer.
  • ii.It is fine-tuned: trained further on thousands of example conversations, a request followed by a good answer, written by people; then trained on people’s ratings of its answers, so that it gives the answers people find helpful.
Marking scheme
  • i. A base model only carries on text the way it usually continues, and a list of requests is usually followed by more.
  • ii. Fine-tuning on example conversations (and training on people’s ratings of answers).
9.
[2]

A website ranks chatbots with a test of 100 questions: 1 mark for a right answer, 0 for a wrong one, and 0 for “I don’t know”. Chatbot X answered every question: 76 right and 24 wrong. Chatbot Y got 70 right and said “I don’t know” to the other 30. The website ranks X first. Which chatbot should a school prefer for students revising for their exams? How should the website change its marking?

Answer

Chatbot Y. When Y answers, it is right (70 of 70), and it says when it doesn’t know. X gives 24 wrong answers that sound as confident as its right ones, so a student revising can’t tell which to trust, and may learn wrong facts for the exam.
X ranks first only because of the marking: a wrong answer costs nothing, so guessing can only add marks, and a model judged this way learns to guess. The website should take marks away for a wrong answer (or give some credit for “I don’t know”). With −1 for each wrong answer, X scores 76 − 24 = 52 and Y still 70.

Marking scheme
  • Y, because X’s 24 wrong answers look as confident as its right ones (and Y says when it doesn’t know).
  • The marking rewards guessing; take marks away for wrong answers (X 52, Y 70), or give credit for “I don’t know”.
10.
[2]

What is the difference between freelancing and remote employment?

Answer

In freelancing, you work for yourself and take on separate jobs for different clients, often found through a freelancing platform, which holds the payment and takes a share.
In remote employment, a company (often abroad) employs you, full time or part time, and you work from home; sometimes it pays through a firm in Nepal that employs you for it.

Marking scheme
  • Freelancing: working for yourself, separate jobs for different clients (often through a platform).
  • Remote employment: employed by one company, working from home.
11.
[2]

Five friends from one class in a Kathmandu school, all of whom speak English at home, are making an app to help shopkeepers in a bazaar of Doti keep their accounts. Judge their team, and say who should be added to it, and why.

Answer

The team has one kind of experience, and none of its members is a user: they don’t know how a shopkeeper in Doti keeps accounts, what phone and signal they have, which language they read best (Doteli or Nepali), or what they would pay for. A team where everyone thinks alike shares the same blind spots. They should add, or work closely with, shopkeepers from the bazaar (to say what they need and test each design), someone who speaks the local language, and perhaps someone who knows accounting or the tax rules for small shops. Different people bring knowledge the others don’t have, as local mappers did in the 2015 earthquake mapping.

Marking scheme
  • The team is all alike and has no users in it, so it shares blind spots (needs, language, phones, signal).
  • Add shopkeepers from the bazaar (or speakers of the local language, someone who knows accounts), because they know what the others don’t.

Section C

5 × 4 = 20

Write long answers to the following questions.

12.
[4]

The football league of Gorkha gives each match’s result through a web API, as JSON text like this:

{"match": 12, "home": {"team": "Arughat", "goals": 2}, "away": {"team": "Palungtar", "goals": 1}}
  • i.Write a module, league.py, with a function result(text) that takes this JSON text and returns the winning team’s name, or "Draw", with a docstring. (2)
  • ii.Add tests at the end of the module that run only when league.py itself is run: a home win, an away win and a draw. (1)
  • iii.Write a separate program that imports the module and prints the result of the match above. (1)
Answer

i. and ii.

league.py

"""Results of the league's matches, from its web API.""" import json  def result(text):    """The winning team's name from a match's JSON text, or "Draw"."""    match = json.loads(text)    home = match["home"]    away = match["away"]    if home["goals"] > away["goals"]:        return home["team"]    if away["goals"] > home["goals"]:        return away["team"]    return "Draw"  if __name__ == "__main__":    home_win = '{"match": 1, "home": {"team": "A", "goals": 3}, "away": {"team": "B", "goals": 0}}'    away_win = '{"match": 2, "home": {"team": "A", "goals": 1}, "away": {"team": "B", "goals": 2}}'    draw = '{"match": 3, "home": {"team": "A", "goals": 2}, "away": {"team": "B", "goals": 2}}'    print(result(home_win), "should be A")    print(result(away_win), "should be B")    print(result(draw), "should be Draw")

iii.

import league text = '{"match": 12, "home": {"team": "Arughat", "goals": 2}, "away": {"team": "Palungtar", "goals": 1}}'print("Match 12:", league.result(text))

Output

Match 12: Arughat

json.loads turns the JSON object into a Python dictionary, with a dictionary inside it for each team, so match["home"]["goals"] is the home team’s goals. The JSON text is put in single quotes in Python because it is full of double quotes.

Marking scheme
  • i. A function result(text) with a docstring that uses json.loads and reaches the nested values (match["home"]["goals"], match["home"]["team"]).
  • i. Returns (doesn’t print) the home team, the away team, or "Draw", correctly.
  • ii. Tests under if __name__ == "__main__": for a home win, an away win and a draw, with what each should give.
  • iii. A program that imports league and prints the result for the given text (Arughat).
13.
[4]

A shop in Nepalgunj delivers to six places. The roads between them, with their lengths in km:

Road km
Shop – Mill 6
Shop – Bazaar 2
Bazaar – Mill 5
Bazaar – Chowk 2
Chowk – Temple 1
Temple – School 2
Mill – School 5
  • i.Which route to the School has the fewest roads? How long is it? (1)
  • ii.Find the shortest route to the School by going nearest first: at each step, visit the nearest place not yet visited, and check whether going on from it gives a shorter way to its neighbors. Write the places in the order they are visited, with their distance from the Shop. (2)
  • iii.Why does breadth-first search find a different route from the one in ii? (1)
Answer

i. Shop → Mill → School: 2 roads, 6 + 5 = 11 km. (Nothing has fewer: no road joins the Shop to the School.)
ii.

Visit Distance from the Shop Shorter ways found to its neighbors
Shop 0 Bazaar 2, Mill 6
Bazaar 2 Chowk 2 + 2 = 4 (Mill by the Bazaar would be 7, not shorter than 6)
Chowk 4 Temple 4 + 1 = 5
Temple 5 School 5 + 2 = 7
Mill 6 none (School by the Mill would be 11, not shorter than 7)
School 7 (reached: its distance is final)

The shortest route is Shop → Bazaar → Chowk → Temple → School, 7 km, following the notes back from the School.
iii. Breadth-first search treats every road as one step, whatever its length, so it finds the fewest roads (2, but 11 km). Going nearest first adds up the lengths, so it finds the shortest distance (7 km), even though that route has 4 roads. This is how a map app works, with travel times as the weights.

Marking scheme
  • i. Shop → Mill → School, 2 roads, 11 km.
  • ii. The places in the order Shop 0, Bazaar 2, Chowk 4, Temple 5, Mill 6, School 7.
  • ii. The shortest route Shop → Bazaar → Chowk → Temple → School, 7 km.
  • iii. Breadth-first search counts roads, not their lengths; nearest first adds up the lengths.
14.
[4]

Four schools of Bhojpur held a science quiz in three rounds.

schools

school_id name
1 Janata School
2 Saraswati School
3 Himalaya School
4 Kalika School

scores

round school_id points
1 1 30
1 2 25
1 3 35
1 4 20
2 1 40
2 2 32
2 3 25
2 4 35
3 1 20
3 2 42
3 3 30
3 4 25

Write what each query gives.

  • i.SELECT school_id, AVG(points) FROM scores GROUP BY school_id HAVING AVG(points) >= 30; (1)
  • ii.SELECT MAX(points) AS best, MIN(points) AS worst FROM scores WHERE round = 3; (1)
  • iii.(1)
SELECT schools.name, SUM(scores.points) AS totalFROM scoresJOIN schools ON scores.school_id = schools.school_idGROUP BY schools.nameORDER BY total DESCLIMIT 1;

iv. Why does query i use HAVING and not WHERE for AVG(points) >= 30? (1)

Answer

i. Each school’s average over the three rounds is 30, 33, 30 and 26.7 (80 ÷ 3), so three schools are kept:

school_id AVG(points)
1 30.0
2 33.0
3 30.0

ii. Round 3’s highest and lowest, under the names given by AS:

best worst
42 20

iii. The totals are Janata 90, Saraswati 99, Himalaya 90, Kalika 80; the highest only:

name total
Saraswati School 99

iv. WHERE checks each row, before the rows are grouped, and a single row has no average. The average belongs to a group, so a condition on it goes in HAVING, which is checked after GROUP BY.

Marking scheme
  • i. Schools 1, 2 and 3, with averages 30, 33 and 30.
  • ii. best 42, worst 20.
  • iii. Saraswati School, 99.
  • iv. WHERE works on single rows before grouping; HAVING works on each group’s values, such as an average.
15.
[4]

Rahul is writing a report on his family’s electronics shop in Nepalgunj for the month of Kartik, with charts drawn by Matplotlib.

  • i.Which kind of chart should show how many of each of its five best-selling items were sold in the month? Give a reason. (1)
  • ii.Which kind of chart should show the money taken each day of Kartik, to see the rush before Tihar? Give a reason. (1)
  • iii.He draws this chart for the 40 items the shop sells. What does each dot show, and what question does the chart answer? (1)
plt.scatter(items["price"], items["sold"])plt.xlabel("Price (Rs)")plt.ylabel("Number sold in Kartik")

iv. Which kind of chart should show how the prices of the 40 items are spread out: how many are under Rs 1,000, how many from Rs 1,000 to Rs 5,000, and so on? (1)

Answer
  • i.A bar chart, with the axis starting from 0: it compares groups (the five items), one bar each, and bars from 0 make the lengths fair to compare.
  • ii.A line chart, with the days across: it shows how something changes over time, so the rise before Tihar and the fall after it can be seen.
  • iii.Each dot is one item: across, its price; up, how many were sold in Kartik. It answers whether the two numbers go together: for example, whether cheaper items sell many more.
  • iv.A histogram: bars that count how many values fall in each range of prices, showing how one number is spread out.
Marking scheme
  • i. A bar chart (from 0), because it compares groups.
  • ii. A line chart, because it shows change over time.
  • iii. Each dot is an item (price across, number sold up); it shows whether price and sales go together.
  • iv. A histogram, counting the items in each range of prices.
16.
[4]

Read the given passage and answer the questions that follow.

A shop in Nepalgunj buys old phones. Its owner tells customers: before you sell your phone, back up your photos, then sign out of your accounts, and only then reset it to its factory settings. He won’t buy phones whose batteries have swollen, and sends them for safe disposal. Phones too broken to mend pile up in a box at the back of his shop, and he would like the companies that sell phones in Nepal to pay to collect and recycle them.

  • i.Old phones that can’t be used are passed to a proper recycler. Why is a phone worth recycling, and why is it harmful when it is dumped or burned? (1)
  • ii.Why must a swollen battery never be thrown in with ordinary rubbish, or punctured? (1)
  • iii.Where should a phone that can’t be used or mended go, and where should it never go? (1)
  • iv.What is the rule called that makes the companies that sell a product pay to collect and recycle it? (1)
Answer
  • i.It holds valuable metals (copper, gold and silver in its circuit boards, lithium and cobalt in its battery) that can be recovered, so fewer mines are dug. It can also hold poisons, such as lead in older solder, which seep into soil and water from a dump, and burning it in the open sends poisonous smoke into the air.
  • ii.A swollen lithium battery is damaged, and can catch fire on its own, or if it is crushed, punctured or heated, as in a rubbish truck or on a dump. A repair shop can take it out safely, and it goes to an e-waste collector.
  • iii.To an e-waste collector that passes it to a proper recycler; never into the household rubbish, a river or a fire.
  • iv.Extended producer responsibility.
Marking scheme
  • i. Valuable metals can be recovered; dumped or burned, its poisons get into soil, water and air.
  • ii. A damaged lithium battery can catch fire if crushed, punctured or heated.
  • iii. To an e-waste collector (proper recycling), never the rubbish, a river or a fire.
  • iv. Extended producer responsibility.

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]

Who won the set? In volleyball, a set is won by the first team to score at least 25 points with a lead of at least 2. At 24–24 the set goes on, until one team is 2 points ahead (26–24, 27–25, …).

At the computer, make two files in one folder:

  • volleyball.py, a module with a function set_winner(a, b) that returns "A" if team A has won the set with a points against b, "B" if team B has, and None if the set isn’t over, with tests at the end that run only when volleyball.py itself is run;
  • main.py, which imports it, asks the points of Bajhang (team A) and Doti (team B) in each of 3 finished sets, prints who won each set, and then who won the match.

Run volleyball.py, then main.py with the sets 25–23, 24–26 and 27–25. (On this page, try your function in the box below first.)

# Try your set_winner function heredef set_winner(a, b):    return None
Answer

volleyball.py

"""Volleyball scoring.""" TO_WIN = 25      # points neededLEAD = 2         # lead needed  def set_winner(a, b):    """ "A" or "B" if that team has won the set, None if it isn't over."""    if a >= TO_WIN and a - b >= LEAD:        return "A"    if b >= TO_WIN and b - a >= LEAD:        return "B"    return None  if __name__ == "__main__":    # tests at the edges: 25 with a lead of 2, 25 with a lead of 1, past 25    print(set_winner(25, 23), "should be A")    print(set_winner(25, 24), "should be None")    print(set_winner(26, 24), "should be A")    print(set_winner(23, 25), "should be B")    print(set_winner(24, 22), "should be None")    print(set_winner(28, 30), "should be B")

Run by itself, volleyball.py prints its tests:

Output

A should be ANone should be NoneA should be AB should be BNone should be NoneB should be B

main.py

import volleyball TEAMS = {"A": "Bajhang", "B": "Doti"}sets_won = {"A": 0, "B": 0}for s in range(1, 4):    a = int(input(f"Set {s}, Bajhang's points? "))    b = int(input(f"Set {s}, Doti's points? "))    winner = volleyball.set_winner(a, b)    if winner is None:        print("This set isn't over.")    else:        print("Set", s, "won by", TEAMS[winner])        sets_won[winner] = sets_won[winner] + 1if sets_won["A"] > sets_won["B"]:    print("Bajhang won the match")else:    print("Doti won the match")

Output

Set 1, Bajhang's points? 25Set 1, Doti's points? 23Set 1 won by BajhangSet 2, Bajhang's points? 24Set 2, Doti's points? 26Set 2 won by DotiSet 3, Bajhang's points? 27Set 3, Doti's points? 25Set 3 won by BajhangBajhang won the match
Marking scheme
  • volleyball.py has a function set_winner(a, b) that returns "A", "B" or None (it doesn’t print).
  • A team wins only with at least 25 points.
  • A team wins only with a lead of at least 2 (25–24 is not over; 26–24 is).
  • Either team can win: the check is made both ways.
  • Tests under if __name__ == "__main__": at the edges (such as 25–23, 25–24, 26–24, 24–22), which don’t run when it is imported.
  • main.py imports volleyball, asks with int(input(…)), uses the returned value to name each set’s winner and counts the sets.
  • Runs both in front of the teacher, and the three sets give Bajhang, Doti, Bajhang, and Bajhang winning the match.
P2.
[6]

The festival committee. The festival committee of a tole in Dadeldhura records who gave how much for each festival. This program makes its database and gives you ask(), which prints what a query gives. Run it, then add one ask() for each question:

  • i.The names of the donors who live in a tole whose name starts with B, in alphabetical order. (2)
  • ii.For each festival, the total given and the average gift: one row per festival. (2)
  • iii.For Dashain only, the total given from each tole. (2)
import sqlite3 db = sqlite3.connect(":memory:")db.execute("CREATE TABLE donors (donor_id INTEGER PRIMARY KEY, name TEXT, tole TEXT)")db.execute("""CREATE TABLE gifts (gift_id INTEGER PRIMARY KEY,              donor_id INTEGER REFERENCES donors(donor_id),              festival TEXT, amount INTEGER)""")db.executemany("INSERT INTO donors VALUES (?, ?, ?)", [    (1, "Ganga Bhatt", "Bagbazar"),    (2, "Harish Joshi", "Bhatkanda"),    (3, "Kamala Awasthi", "Gairagaun"),    (4, "Laxmi Pant", "Bagbazar"),    (5, "Mohan Bista", "Gairagaun"),])db.executemany("INSERT INTO gifts VALUES (?, ?, ?, ?)", [    (1, 1, "Dashain", 1000),    (2, 2, "Dashain", 500),    (3, 3, "Dashain", 1500),    (4, 4, "Dashain", 700),    (5, 5, "Dashain", 300),    (6, 1, "Tihar", 500),    (7, 3, "Tihar", 800),    (8, 4, "Tihar", 200),    (9, 2, "Gaura", 600),    (10, 5, "Gaura", 400),])  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 donors")
Answer

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

import sqlite3 db = sqlite3.connect(":memory:")db.execute("CREATE TABLE donors (donor_id INTEGER PRIMARY KEY, name TEXT, tole TEXT)")db.execute("""CREATE TABLE gifts (gift_id INTEGER PRIMARY KEY,              donor_id INTEGER REFERENCES donors(donor_id),              festival TEXT, amount INTEGER)""")db.executemany("INSERT INTO donors VALUES (?, ?, ?)", [    (1, "Ganga Bhatt", "Bagbazar"),    (2, "Harish Joshi", "Bhatkanda"),    (3, "Kamala Awasthi", "Gairagaun"),    (4, "Laxmi Pant", "Bagbazar"),    (5, "Mohan Bista", "Gairagaun"),])db.executemany("INSERT INTO gifts VALUES (?, ?, ?, ?)", [    (1, 1, "Dashain", 1000),    (2, 2, "Dashain", 500),    (3, 3, "Dashain", 1500),    (4, 4, "Dashain", 700),    (5, 5, "Dashain", 300),    (6, 1, "Tihar", 500),    (7, 3, "Tihar", 800),    (8, 4, "Tihar", 200),    (9, 2, "Gaura", 600),    (10, 5, "Gaura", 400),])  def ask(sql):    """Print each row the query gives, then a blank line."""    for row in db.execute(sql):        print(row)    print()  ask("SELECT name FROM donors WHERE tole LIKE 'B%' ORDER BY name")ask("SELECT festival, SUM(amount), AVG(amount) FROM gifts GROUP BY festival")ask("""SELECT donors.tole, SUM(gifts.amount) FROM gifts       JOIN donors ON gifts.donor_id = donors.donor_id       WHERE gifts.festival = 'Dashain' GROUP BY donors.tole""")

Output

('Ganga Bhatt',)('Harish Joshi',)('Laxmi Pant',) ('Dashain', 4000, 800.0)('Gaura', 1000, 500.0)('Tihar', 1500, 500.0) ('Bagbazar', 1700)('Bhatkanda', 500)('Gairagaun', 1800)

(The gifts are made up for this paper.)

Marking scheme
  • i. WHERE tole LIKE 'B%' (the tole, not the name).
  • i. ORDER BY name: Ganga Bhatt, Harish Joshi, Laxmi Pant.
  • ii. GROUP BY festival with SUM(amount) and AVG(amount).
  • ii. Dashain 4,000 and 800, Gaura 1,000 and 500, Tihar 1,500 and 500.
  • iii. A JOIN of gifts and donors ON gifts.donor_id = donors.donor_id, with WHERE gifts.festival = 'Dashain'.
  • iii. GROUP BY donors.tole with SUM(gifts.amount): Bagbazar 1,700, Bhatkanda 500, Gairagaun 1,800.
P3.
[6]

Word ladders. The English club of a school in Arghakhanchi plays word ladders: change a word into another one letter at a time, making a real word at each step. The dictionary below joins each word the club allows to the allowed words one letter away. Write a function fewest_steps(graph, start, goal) that returns the ladder with the fewest steps as a list of words, or None if there is none. Then print the ladder and the number of steps:

  • from cold to warm;
  • from ball to cart;
  • from jump to cold (print “No ladder” if there is none).
words = {    "cold": ["cord", "bold", "colt"],    "cord": ["cold", "card", "word"],    "bold": ["cold", "bald", "bolt"],    "colt": ["cold", "bolt"],    "card": ["cord", "ward", "cart"],    "word": ["cord", "ward", "wore"],    "bald": ["bold", "ball"],    "bolt": ["bold", "colt"],    "ward": ["card", "word", "warm"],    "cart": ["card"],    "wore": ["word"],    "ball": ["bald"],    "warm": ["ward"],    "jump": [],} # Write fewest_steps here
Answer
words = {    "cold": ["cord", "bold", "colt"],    "cord": ["cold", "card", "word"],    "bold": ["cold", "bald", "bolt"],    "colt": ["cold", "bolt"],    "card": ["cord", "ward", "cart"],    "word": ["cord", "ward", "wore"],    "bald": ["bold", "ball"],    "bolt": ["bold", "colt"],    "ward": ["card", "word", "warm"],    "cart": ["card"],    "wore": ["word"],    "ball": ["bald"],    "warm": ["ward"],    "jump": [],}  def fewest_steps(graph, start, goal):    """The route from start to goal with the fewest steps, or None."""    came_from = {start: None}    to_visit = [start]    while len(to_visit) > 0:        word = to_visit.pop(0)        if word == goal:            route = []            while word is not None:                route.append(word)                word = came_from[word]            route.reverse()            return route        for nxt in graph[word]:            if nxt not in came_from:                came_from[nxt] = word                to_visit.append(nxt)    return None  for start, goal in [("cold", "warm"), ("ball", "cart"), ("jump", "cold")]:    ladder = fewest_steps(words, start, goal)    if ladder is None:        print(start, "to", goal + ": No ladder")    else:        print(start, "to", goal + ":", " → ".join(ladder), "(" + str(len(ladder) - 1), "steps)")

Output

cold to warm: cold → cord → card → ward → warm (4 steps)ball to cart: ball → bald → bold → cold → cord → card → cart (6 steps)jump to cold: No ladder

cold → cord → word → ward → warm is also 4 steps: any ladder of 4 is right.

Marking scheme
  • A function with the graph, start and goal, that starts its list (and its notes) with the start.
  • A queue: takes from the front with pop(0) and adds to the back with append().
  • Marks a word as seen (in came_from) when it is added, so none is added twice.
  • Stops at the goal and follows the notes back to the start, then reverses them.
  • Prints each ladder and the number of steps (one less than the words): 4 and 6.
  • Returns None when the list runs out, and the program prints “No ladder” for jump.
P4.
[6]

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

  • i.Why does set_winner return None for 25–24, instead of printing “not over”? Why test 25–24 and 26–24? (2)
  • ii.In your third query, the WHERE comes before the GROUP BY. What does each do, and in what order does the database do them? (2)
  • iii.cold is in cord’s list and cord in cold’s. Why doesn’t your search go back and forth between them forever? How does it know there is no ladder from jump? (2)
Answer
  • i.main.py must decide what to do with the result: count the set, or say it isn’t over. A returned value lets it do that; a printed message can’t be tested or counted, and would appear even where it isn’t wanted. 25–24 and 26–24 are on both sides of the lead of 2 edge: a mistake such as > 2 for >= 2, or forgetting the lead, shows up there.
  • ii.WHERE keeps only the rows of Dashain’s gifts; GROUP BY then puts the rows that are left into one group per tole, and SUM adds up each group. The database does the WHERE first, then the grouping, so the other festivals’ gifts never reach the totals.
  • iii.A word is put in came_from the moment it is first added, and a word already there is never added again, so cord, once seen, is not added again from cold, nor cold from cord. Each word is visited at most once. From jump the list of neighbors is empty, so the list to visit runs out before the goal is reached, and the function returns None.
Marking scheme
  • i. A returned value lets the calling program decide what to do (count sets, print a message).
  • i. 25–24 and 26–24 are either side of the lead-of-2 edge, where mistakes hide.
  • ii. WHERE picks the rows (Dashain), GROUP BY makes one group per tole for SUM.
  • ii. The WHERE is done first, before the grouping.
  • iii. Words are marked as seen when added and never added again, so none is visited twice.
  • iii. From jump the list runs out without reaching the goal, so it returns 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