Final Exam Model Paper 2
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 = 101. Choose the correct option for each of the following questions.
When a programmer types pip install and the name of a third-party library, where does pip download the library from?
Pick an answer to see why.
On the night of Tihar, a Deusi group in a tole of Bhaktapur wants to sing its way along every lane of the tole exactly once. The lanes, as a dictionary of neighbors:
tole = { "Chowk": ["Temple", "Pati", "Well"], "Temple": ["Chowk", "Pati"], "Pati": ["Chowk", "Temple", "Well", "School"], "Well": ["Chowk", "Pati", "School"], "School": ["Pati", "Well"],}Can they do it, and where must they start?
Pick an answer to see why.
What is a composite key?
Pick an answer to see why.
At inter-house volleyball practice, Prabin served 3 times and all 3 went in. Sabina served 50 times and 41 went in. The coach says: “Prabin got 100% and Sabina 82%, so Prabin is the better server.” Which judgment is right?
Pick an answer to see why.
A municipality runs its online tax-payment site on two servers in different regions. Each server is down on about 1 day in 50, and they fail independently. About how often are both down at once, so that nobody can pay?
Pick an answer to see why.
What is the first step of troubleshooting a problem with a computer or a program?
Pick an answer to see why.
Inside a large language model, what is an embedding?
Pick an answer to see why.
Mina tells a chatbot her school’s new phone number, and it thanks her. The next day her friend, in a new chat, asks the same chatbot for the school’s number. Why can’t it give the new number?
Pick an answer to see why.
No quantum computer can yet break today’s public-key encryption, but someone could copy encrypted messages now and keep them until one can: harvest now, decrypt later. Which of these, sent today over the internet, most needs post-quantum encryption already?
Pick an answer to see why.
Rojan is tracing the history of the internet in Nepal. A website says Nepal’s first email was sent in 1993; a book says the first email service began in 1994. Which judgment is best?
Pick an answer to see why.
Section B
10 × 2 = 20Write short answers to the following questions.
Aarav keeps the score for his school’s cricket team. This function reads the runs scored off each ball of an over:
def summary(balls): total = 0 fours = 0 for runs in balls: total = total + runs if runs == 4: fours = fours + 1 return total, fours made, boundaries = summary([1, 4, 0, 4, 6, 2])print(made, boundaries)print(total)- i.What does line 11 print?
- ii.Line 12 stops the program with an error. Why, and what should Aarav print instead?
Answer
i. The function returns two values, a tuple, and line 10 puts them in made and boundaries: 1 + 4 + 0 + 4 + 6 + 2 = 17 runs, with two fours.
Output
17 2ii. total is a local variable of summary: it exists only while the function runs, and is gone when it returns. Outside the function there is no name total, so line 12 gives NameError: name 'total' is not defined. The function gave its total back with return, and it is now in made, so Aarav should write print(made).
Marking scheme
- i.
17 2. - ii. total is local to the function (it doesn’t exist outside it), so a NameError; print made instead.
A ward in Gulmi pipes water from one tank to 9 public taps. Each pipe runs from one place (the tank or a tap) to another, and the pipes form a tree with the tank as its root: there are no loops.
- i.When one pipe bursts, some taps go dry. Explain why, using what makes the pipes a tree.
- ii.The ward adds one pipe between two taps. What does that change, and why are the pipes then no longer a tree?
Answer
- i.In a tree there is exactly one route between any two places: each tap gets its water from one place above it, its parent, through one pipe. A burst pipe breaks the only route from the tank to every tap below it, so all of them go dry.
- ii.The new pipe makes a loop: there are now two routes to the taps on that loop, so when one of their pipes bursts the water can come round the other way. A tree has no loops (with 10 places it has exactly 9 pipes, and now there are 10), so the pipes are no longer a tree.
Marking scheme
- i. A tree has only one route from the tank to each tap, so a burst cuts off every tap below it.
- ii. The extra pipe makes a loop, a second route around a burst; a tree has no loops.
During sports week, a school canteen records its sales in a table, sales:
| sale_id | item | day | plates |
|---|---|---|---|
| 1 | Chowmein | Sunday | 48 |
| 2 | Samosa | Sunday | 65 |
| 3 | Chowmein | Monday | 52 |
| … | … | … | … |
Write an SQL query that gives each item with the total plates sold in the week, only for the items that sold more than 100 plates in all, the most sold first.
Answer
SELECT item, SUM(plates)FROM salesGROUP BY itemHAVING SUM(plates) > 100ORDER BY SUM(plates) DESC;The condition is on each item’s total, a group, so it goes in HAVING, after GROUP BY. WHERE plates > 100 would instead keep only single sales of more than 100 plates.
Marking scheme
SELECT item, SUM(plates) FROM sales GROUP BY item.HAVING SUM(plates) > 100(not WHERE), andORDER BY SUM(plates) DESC.
The sports teacher keeps the races’ results in results.csv:
results.csv
name,house,event,secondsAnisha,Red,100 m,13.8Bibek,Blue,100 m,12.9Chhiring,Green,200 m,27.4Dipendra,Red,100 m,14.6Eliza,Yellow,100 m,13.2Gaurav,Blue,200 m,26.1Hema,Green,100 m,15.0Write a program with pandas that prints the name, house and time of the runners in the 100 m who ran it in under 14 seconds, the fastest first. Write what it prints.
Answer
import pandas as pd results = pd.read_csv("results.csv")fast = results[(results["event"] == "100 m") & (results["seconds"] < 14)]print(fast[["name", "house", "seconds"]].sort_values("seconds"))Output
name house seconds1 Bibek Blue 12.94 Eliza Yellow 13.20 Anisha Red 13.8Each condition is in its own brackets, joined by & (both must be true). The numbers on the left are the rows’ places in the whole file.
Marking scheme
- Reads the file with
pd.read_csvand keeps the rows with both conditions:(results["event"] == "100 m") & (results["seconds"] < 14). - Picks the three columns and sorts by seconds, giving Bibek, Eliza, Anisha.
Two students try to open the ward office’s website from the school lab. Nirmala’s browser shows 404 Not Found. On another computer, Suman’s shows This site can’t be reached. Explain what each message means, and what each should check first.
Answer
404 Not Found means Nirmala’s computer reached the website, and the website answered, but there is no page at that address. She should check the address she typed (or followed from a link), or go to the site’s home page and look for the page from there.
This site can’t be reached means Suman’s computer is connected, but the site itself can’t be found or isn’t answering. He should check the spelling of the address, then try another website: if others open, the problem is with that site (or its name), not with his connection.
Marking scheme
- 404: the site answered but has no page at that address; check the address, or start from the home page.
- Can’t be reached: connected, but the site can’t be found or isn’t answering; check the spelling, and try another site.
Ramesh wants one folder called Sports Day 2026 for the class’s photos. He types:
Output
ramesh@lab-pc:~/school$ mkdir Sports Day 2026ramesh@lab-pc:~/school$ cd Sports Day 2026bash: cd: too many arguments- i.What did his
mkdircommand make, and why? - ii.Write the commands that make the folder he wanted and go into it.
Answer
- i.Three folders, called Sports, Day and 2026. In the shell a space separates arguments, so
mkdirwas given three names and made a folder for each. For the same reason,cdwas given three arguments, and it can go to only one folder. - ii.Put the name in quotes, so the shell reads it as one argument:
mkdir "Sports Day 2026"cd "Sports Day 2026"Marking scheme
- i. Three folders, Sports, Day and 2026, because a space separates arguments.
- ii.
mkdir "Sports Day 2026"andcd "Sports Day 2026", with the name in quotes.
Sunita’s school uses a chatbot through an API, and pays for the number of tokens. She notices that the same notice for parents costs more when it is written in Nepali than in English.
- i.Why does the Nepali notice use more tokens?
- ii.Give one other effect of this, besides the cost.
Answer
- i.The tokenizer learned its pieces by joining the commonest pairs in its training text, which was mostly English. English words became one token each, but few Nepali pieces were learned, so Nepali text is cut into small pieces: single letters and vowel signs, or even pieces of a letter’s bytes (a Devanagari letter is three bytes in UTF-8).
- ii.Any one: a Nepali conversation fills the context window sooner, so in a long chat the model loses sight of the earliest messages sooner; the answer takes longer to write, token by token; the model may be less reliable in Nepali, since Nepali was rare in its training text.
Marking scheme
- i. The tokenizer learned mostly from English, so it has few Nepali pieces and cuts Nepali into letters or bytes.
- ii. One other effect: fills the context window sooner, slower answers, or less reliable in Nepali.
A school office plans to use a chatbot for three jobs: (a) suggesting names for four new sports houses; (b) working out each student’s final percentage from their marks, for the report cards; (c) drafting the notice for the Dashain holidays, which the head teacher reads and corrects before it is sent. Which job needs the most checking before the school relies on it? Give two reasons.
Answer
Job (b), the percentages. Judge each job’s harm:
- How bad a mistake would be: a wrong percentage can change a student’s grade, or pass and fail, on an official record; a dull house name harms nobody.
- How likely it is to be acted on without checking: the numbers go straight onto report cards, while the notice is read by the head teacher first.
- Who is harmed: every student and their family, who may not find out or be able to recover.
- And language models are weak at exact arithmetic: they see numbers as tokens and predict likely digits, so they can be confidently wrong. Percentages are better worked out by a spreadsheet or a program, and checked.
Marking scheme
- Job (b), with one reason: a mistake is serious (grades, an official record), or it is likely to be used without checking.
- A second reason: who is harmed (every student), or models are weak at exact arithmetic, or the other jobs are harmless or checked by a person.
What is a portfolio, for someone looking for online work? Name two things a Grade 10 student could put in one.
Answer
A portfolio is a collection of your best work that shows what you can do, because clients pay for skills they can see. A student could put in, for example: a program they wrote, a website made for someone, a data analysis with its charts, a design, their Unit 8 team project.
Marking scheme
- A collection of your own work that shows clients what you can do.
- Two things it could hold (programs, a website, a data analysis, a design, a project).
For the school’s new rules, a group of students proposes: “Using ChatGPT for homework is banned.” Judge this rule, and write a better one.
Answer
It is a weak rule. It names one product, so it isn’t technology-neutral: other chatbots, and AI inside other apps, aren’t covered, and next year’s tools won’t be either. It can’t be enforced: a teacher can’t tell for sure who used it. And it blocks good uses too, such as asking for a hard idea to be explained another way.
A better rule says what matters, for any tool: “Work you hand in must be your own. If you use an AI tool, say which one and what you used it for. AI tools may not be used in tests. A teacher may ask you to explain any work you hand in.”
Marking scheme
- A judgment with a reason: it names one product (not technology-neutral), or can’t be enforced, or blocks good uses.
- A better, technology-neutral rule (about any AI tool: own work, saying what was used, explaining it).
Section C
5 × 4 = 20Write long answers to the following questions.
The scoreboard of an inter-school cricket tournament in Ghorahi, Dang, shows two figures. The run rate is the runs a team scores per over (6 balls). The needed rate is the runs per over the team batting second still needs, to reach its target with the balls it has left.
- i.Write a module, cricket.py, with two functions, each with a docstring:
run_rate(runs, balls)andneeded_rate(target, runs, balls_left), which return the figures rounded to 2 decimal places. Before a ball is bowled the run rate is 0; once the target is reached, the needed rate is 0; with no balls left,needed_ratereturnsNone. (2) - ii.Add tests at the end of the module that run only when cricket.py itself is run, including each of the three special cases. (1)
- iii.Write a separate program that imports the module and prints both figures for a team chasing a target of 142, which has 87 runs from 70 balls, with 50 balls left. (1)
Answer
i. and ii.
cricket.py
"""Run rates for the tournament's scoreboard.""" BALLS_PER_OVER = 6 def run_rate(runs, balls): """Runs per over so far, to 2 decimal places (0 before the first ball).""" if balls == 0: return 0 return round(runs / balls * BALLS_PER_OVER, 2) def needed_rate(target, runs, balls_left): """Runs per over still needed to reach target; 0 once it is reached, None if no balls are left.""" still_needed = target - runs if still_needed <= 0: return 0 if balls_left == 0: return None return round(still_needed / balls_left * BALLS_PER_OVER, 2) if __name__ == "__main__": # tests: an ordinary case, and the three special cases print(run_rate(30, 18), "should be 10.0") print(run_rate(0, 0), "should be 0") print(needed_rate(100, 88, 12), "should be 6.0") print(needed_rate(100, 100, 6), "should be 0") print(needed_rate(100, 90, 0), "should be None")iii.
import cricket print("Run rate:", cricket.run_rate(87, 70))print("Needed rate:", cricket.needed_rate(142, 87, 50))Output
Run rate: 7.46Needed rate: 6.687 runs in 70 balls is 87 ÷ 70 × 6 ≈ 7.46 runs an over. The team still needs 142 − 87 = 55 runs from 50 balls: 55 ÷ 50 × 6 = 6.6 an over. The check for a reached target must come before the check for no balls left: a team that won on the last ball needs 0, not None. Any clear names and messages are fine.
Marking scheme
- i.
run_rateandneeded_ratewith docstrings that return (not print) runs ÷ balls × 6 and (target − runs) ÷ balls left × 6, rounded to 2 places. - i. The special cases handled without a crash: 0 balls bowled, target reached, no balls left (
None). - ii. Tests under
if __name__ == "__main__":that include the special cases, with what each should give. - iii. A program that imports cricket and prints both figures (7.46 and 6.6).
A team from the District Administration Office, Baglung, visits the villages of one ward to give out citizenship certificates, starting from the ward office. This dictionary shows which places are joined by a trail (the trails are simplified for this question):
ward = { "Ward office": ["Deurali", "Simle", "Thulogaun"], "Deurali": ["Ward office", "Phedi"], "Simle": ["Ward office", "Phedi", "Pipalbot"], "Thulogaun": ["Ward office", "Pipalbot"], "Phedi": ["Deurali", "Simle", "Lamagaun"], "Pipalbot": ["Simle", "Thulogaun", "Lamagaun"], "Lamagaun": ["Phedi", "Pipalbot", "Danda"], "Danda": ["Lamagaun"],}- i.Do a breadth-first search from the Ward office by hand. Write a row for each visit: the place visited, its steps, the new places added (with their steps), and the list still to visit. (2)
- ii.In how few trails can the team reach Danda? Write the route, from the notes of where each place was first reached from. (1)
- iii.Which one trail, if it were closed for repair, would cut a village off from the ward office? Explain why closing any other single trail cuts no village off. (1)
Answer
i.
| Visit | Steps | New places (steps) | List still to visit, front first |
|---|---|---|---|
| (start) | Ward office (0) | Ward office | |
| Ward office | 0 | Deurali, Simle, Thulogaun (1) | Deurali, Simle, Thulogaun |
| Deurali | 1 | Phedi (2) | Simle, Thulogaun, Phedi |
| Simle | 1 | Pipalbot (2); Phedi already seen | Thulogaun, Phedi, Pipalbot |
| Thulogaun | 1 | none (Pipalbot already seen) | Phedi, Pipalbot |
| Phedi | 2 | Lamagaun (3) | Pipalbot, Lamagaun |
| Pipalbot | 2 | none (Lamagaun already seen) | Lamagaun |
| Lamagaun | 3 | Danda (4) | Danda |
| Danda | 4 | none | (empty) |
- ii.4 trails. Danda was first reached from Lamagaun, Lamagaun from Phedi, Phedi from Deurali, Deurali from the Ward office: Ward office → Deurali → Phedi → Lamagaun → Danda.
- iii.Lamagaun–Danda. It is the only trail to Danda, so closing it leaves Danda with no route at all. Every other trail lies on a loop (Ward office, Deurali, Phedi, Simle; Ward office, Simle, Pipalbot, Thulogaun; Simle, Phedi, Lamagaun, Pipalbot), so when one of them is closed, the places it joined can still be reached the other way round the loop.
Marking scheme
- i. The visits in the right order: Ward office; Deurali, Simle, Thulogaun; then Phedi, Pipalbot; then Lamagaun; then Danda.
- i. Correct steps (1 for the first three, 2 for Phedi and Pipalbot, 3 for Lamagaun, 4 for Danda) and the list kept as a queue (new places at the back).
- ii. 4 trails, Ward office → Deurali → Phedi → Lamagaun → Danda.
- iii. Lamagaun–Danda, the only trail to Danda; every other trail is on a loop, so there is another way round.
A ward’s youth club in Dhankuta keeps its members and their fees for Kartik in two tables. A fee not yet paid has an empty (NULL) paid_on; Ekta joined late and has no fee row yet.
members
| member_id | name | sport |
|---|---|---|
| 1 | Asmita Rai | table tennis |
| 2 | Bishal Limbu | volleyball |
| 3 | Chandra Tamang | table tennis |
| 4 | Dikshya Karki | volleyball |
| 5 | Ekta Basnet | karate |
| 6 | Jenish Shrestha | karate |
fees
| member_id | month | paid_on |
|---|---|---|
| 1 | Kartik | 2026-10-20 |
| 2 | Kartik | NULL |
| 3 | Kartik | 2026-10-22 |
| 4 | Kartik | 2026-10-18 |
| 6 | Kartik | NULL |
Write what each query gives.
- i.
SELECT name FROM members WHERE sport IN ('volleyball', 'karate') ORDER BY name;(1) - ii.
SELECT COUNT(*), COUNT(paid_on) FROM fees;(1) - iii.(1)
SELECT members.name, fees.paid_onFROM membersLEFT JOIN fees ON fees.member_id = members.member_idWHERE fees.paid_on IS NULLORDER BY members.name;iv. Why would the query in iii miss one member who hasn’t paid, if it used a plain JOIN instead of LEFT JOIN? (1)
Answer
- i.The members who play volleyball or karate, in alphabetical order: Bishal Limbu, Dikshya Karki, Ekta Basnet, Jenish Shrestha.
- ii.5, 3.
COUNT(*)counts every row;COUNT(paid_on)counts only the rows where paid_on isn’t NULL, the three paid fees.
| COUNT(*) | COUNT(paid_on) |
|---|---|
| 5 | 3 |
iii. Every member whose fee isn’t paid, in alphabetical order. Ekta has no fee row at all, so the LEFT JOIN keeps her with paid_on filled in as NULL:
| name | paid_on |
|---|---|
| Bishal Limbu | NULL |
| Ekta Basnet | NULL |
| Jenish Shrestha | NULL |
iv. A plain JOIN keeps only members who have a matching row in fees. Ekta has none, so she would be dropped before the WHERE is checked, and the list would show only Bishal and Jenish. A LEFT JOIN keeps every row of the first table, members, matched or not.
Marking scheme
- i. Bishal Limbu, Dikshya Karki, Ekta Basnet, Jenish Shrestha, in that order.
- ii. 5 and 3, because COUNT(paid_on) skips the NULLs.
- iii. Bishal Limbu, Ekta Basnet and Jenish Shrestha, each with NULL.
- iv. A plain join drops Ekta, who has no row in fees; a LEFT JOIN keeps every member.
Students sign up for the inter-house quiz on a form, typing their house’s name themselves. The school has three houses: Annapurna, Dhaulagiri and Manaslu. The sign-ups are in signups.csv:
signups.csv
name,house,gradeAashma,Annapurna,9Bipin,annapurna ,10Chandani,Dhaulagiri,9Dinesh,DHAULAGIRI,10Eva,Manaslu,9Firoj,Manasulu,10Bipin,annapurna ,10A program counts them, cleans the house names, and counts again:
import pandas as pd signups = pd.read_csv("signups.csv")print(signups["house"].value_counts())signups["house"] = signups["house"].str.strip().str.title()signups["house"] = signups["house"].replace({"Manasulu": "Manaslu"})signups = signups.drop_duplicates()print(signups["house"].value_counts())- i.Line 4 counts more than three houses. Why? (1)
- ii.What does line 5 do to “annapurna ” and to “DHAULAGIRI”? Why is line 6 still needed? (1)
- iii.What does line 7 do, and which row does it remove? (1)
- iv.Write the counts that line 8 prints. (1)
Answer
- i.To a computer, text must match exactly. “Annapurna” and “annapurna ” (small a, with a space at the end) are different values, and so are “Dhaulagiri” and “DHAULAGIRI”, and “Manaslu” and the misspelling “Manasulu”. So it counts six different houses.
- ii.
.str.strip()takes the space off the end, and.str.title()makes the first letter capital and the rest small: both become Annapurna and Dhaulagiri. But “Manasulu” is a different spelling, not a matter of spaces or capitals, so it needsreplace, with the dictionary saying what it should become. - iii.It removes rows that are exactly the same as an earlier row: Bipin signed up twice, so his second row goes. (After cleaning, the two rows are identical in every column.)
- iv.Each house now has two students:
Output
houseAnnapurna 2Dhaulagiri 2Manaslu 2Name: count, dtype: int64Marking scheme
- i. Values must match exactly: different capitals, a space and a misspelling make different values.
- ii. strip and title turn both into Annapurna and Dhaulagiri; the misspelling needs replace.
- iii. It removes repeated rows: Bipin’s second sign-up.
- iv. Annapurna 2, Dhaulagiri 2, Manaslu 2.
Read the given passage and answer the questions that follow.
The water tank on the roof of a school in Bhaktapur kept running dry in the middle of the school day. The computer club fitted a sensor that measures how full the tank is, joined to a small computer with Wi-Fi. When the water falls below a quarter, the small computer switches on the pump that fills the tank from the well, and sends a message to the caretaker’s phone. A chart of the tank’s level, hour by hour, can be seen on any phone through a company’s cloud service. The small computer came from the factory with the username “admin” and the password “admin”.
- i.Name the four parts of an IoT system. (1)
- ii.What is an actuator? Name the actuator in this system. (1)
- iii.Why should the club change the password “admin” at once? (1)
- iv.Write one reason why the small computer itself, not the cloud service, should decide when to switch the pump on. (1)
Answer
- i.Sense (the sensor measures the tank’s level), connect (the Wi-Fi sends the readings), process (a program decides what the readings mean) and act (the pump is switched on, or the caretaker is told).
- ii.An actuator is a part that does something in the physical world when the computer tells it to. Here it is the pump (or the switch that turns it on).
- iii.Factory usernames and passwords are the same on thousands of devices and are published, so anyone can log in to a device that still has them. In 2016 the program Mirai took over about a hundred thousand cameras and routers just by trying such passwords.
- iv.Any one: it keeps working when the Wi-Fi or internet is down; it acts at once, with no delay for the readings to go to the cloud and back; it doesn’t depend on the company’s service still running (or being paid for).
Marking scheme
- i. Sense, connect, process, act.
- ii. A part that does something physical when told; the pump.
- iii. Factory passwords are known to everyone, so attackers can take the device over (as Mirai did).
- iv. It still works when the network or the company’s service is down, or acts with no delay.
Practical exam
25 marksMarked 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.
The Tihar offer. A sweet shop in Dhankuta sells laddu at Rs 450 a box. For Tihar, every 4th box is free (buy 3, get 1 free), and an order that still costs Rs 5,000 or more after that gets a further Rs 200 off.
At the computer, make two files in one folder:
- sweets.py, a module with a function
price(boxes)that returns the price of that many boxes, with tests at the end that run only when sweets.py itself is run; - main.py, which imports it, asks 3 customers how many boxes each wants, prints each customer’s price, and then the day’s total.
Run sweets.py, then main.py with 4, 7 and 15 boxes. (On this page, try your function in the box below first.)
# Try your price function heredef price(boxes): return 0Answer
sweets.py
"""The sweet shop's Tihar offer.""" BOX_PRICE = 450 # rupeesBIG_ORDER = 5000 # rupees: from here, Rs 200 offBIG_ORDER_OFF = 200 def price(boxes): """The price in rupees of this many boxes: every 4th box free, and Rs 200 off if that still costs Rs 5,000 or more.""" free = boxes // 4 cost = (boxes - free) * BOX_PRICE if cost >= BIG_ORDER: cost = cost - BIG_ORDER_OFF return cost if __name__ == "__main__": # tests at the edges: the 4th box, and either side of Rs 5,000 print(price(3), "should be 1350") print(price(4), "should be 1350") print(price(5), "should be 1800") print(price(14), "should be 4950") print(price(16), "should be 5200")Run by itself, sweets.py prints its tests:
Output
1350 should be 13501350 should be 13501800 should be 18004950 should be 49505200 should be 5200main.py
import sweets total = 0for customer in range(1, 4): boxes = int(input(f"Customer {customer}: how many boxes? ")) cost = sweets.price(boxes) print("Price: Rs", cost) total = total + costprint("Today's total: Rs", total)Output
Customer 1: how many boxes? 4Price: Rs 1350Customer 2: how many boxes? 7Price: Rs 2700Customer 3: how many boxes? 15Price: Rs 5200Today's total: Rs 92504 boxes: 1 free, 3 paid, Rs 1,350. 7 boxes: 1 free, 6 paid, Rs 2,700. 15 boxes: 3 free, 12 paid, Rs 5,400, which is Rs 5,000 or more, so Rs 5,200. Together Rs 9,250.
Marking scheme
- sweets.py has a function
price(boxes)that returns the price (it doesn’t print it). - One box in every 4 free (
boxes // 4, or the same worked out another way). - Rs 200 off only when the price after the free boxes is Rs 5,000 or more.
- Constants for the prices, or clear numbers with comments, and a docstring.
- Tests under
if __name__ == "__main__":at the edges (such as 3, 4 and either side of Rs 5,000), which don’t run when it is imported. - main.py imports sweets and uses the returned values to print each price and add up the total, asking with
int(input(…)). - Runs both in front of the teacher, and 4, 7, 15 give Rs 1,350, Rs 2,700, Rs 5,200 and Rs 9,250.
Tihar sales. A shop in Dhading Besi kept its Tihar sales in a database. This program makes it and gives you ask(), which prints what a query gives. Run it, then add one ask() for each question:
- i.The name and price of each sweet that costs less than Rs 500, the cheapest first. (2)
- ii.How many things were sold on each day, in all: one row per day. (2)
- iii.The names of the things sold on Laxmi Puja, with how many of each, the most first. (2)
import sqlite3 db = sqlite3.connect(":memory:")db.execute("CREATE TABLE items (item_id INTEGER PRIMARY KEY, name TEXT, kind TEXT, price INTEGER)")db.execute("""CREATE TABLE sales (sale_id INTEGER PRIMARY KEY, item_id INTEGER REFERENCES items(item_id), day TEXT, quantity INTEGER)""")db.executemany("INSERT INTO items VALUES (?, ?, ?, ?)", [ (1, "Laddu box", "sweet", 450), (2, "Barfi box", "sweet", 600), (3, "Diyo, pack of 12", "lamp", 120), (4, "Marigold garland", "flower", 80), (5, "Candles, pack of 10", "lamp", 150), (6, "Jeri, 1 kg", "sweet", 380),])db.executemany("INSERT INTO sales VALUES (?, ?, ?, ?)", [ (1, 3, "Kag Tihar", 14), (2, 4, "Kag Tihar", 20), (3, 1, "Kukur Tihar", 6), (4, 4, "Kukur Tihar", 35), (5, 3, "Laxmi Puja", 40), (6, 4, "Laxmi Puja", 60), (7, 2, "Laxmi Puja", 9), (8, 6, "Laxmi Puja", 12), (9, 5, "Laxmi Puja", 25),]) 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 items")Answer
The same program, with these three lines in place of the last one:
import sqlite3 db = sqlite3.connect(":memory:")db.execute("CREATE TABLE items (item_id INTEGER PRIMARY KEY, name TEXT, kind TEXT, price INTEGER)")db.execute("""CREATE TABLE sales (sale_id INTEGER PRIMARY KEY, item_id INTEGER REFERENCES items(item_id), day TEXT, quantity INTEGER)""")db.executemany("INSERT INTO items VALUES (?, ?, ?, ?)", [ (1, "Laddu box", "sweet", 450), (2, "Barfi box", "sweet", 600), (3, "Diyo, pack of 12", "lamp", 120), (4, "Marigold garland", "flower", 80), (5, "Candles, pack of 10", "lamp", 150), (6, "Jeri, 1 kg", "sweet", 380),])db.executemany("INSERT INTO sales VALUES (?, ?, ?, ?)", [ (1, 3, "Kag Tihar", 14), (2, 4, "Kag Tihar", 20), (3, 1, "Kukur Tihar", 6), (4, 4, "Kukur Tihar", 35), (5, 3, "Laxmi Puja", 40), (6, 4, "Laxmi Puja", 60), (7, 2, "Laxmi Puja", 9), (8, 6, "Laxmi Puja", 12), (9, 5, "Laxmi Puja", 25),]) 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, price FROM items WHERE kind = 'sweet' AND price < 500 ORDER BY price")ask("SELECT day, SUM(quantity) FROM sales GROUP BY day")ask("""SELECT items.name, sales.quantity FROM sales JOIN items ON sales.item_id = items.item_id WHERE sales.day = 'Laxmi Puja' ORDER BY sales.quantity DESC""")Output
('Jeri, 1 kg', 380)('Laddu box', 450) ('Kag Tihar', 34)('Kukur Tihar', 41)('Laxmi Puja', 146) ('Marigold garland', 60)('Diyo, pack of 12', 40)('Candles, pack of 10', 25)('Jeri, 1 kg', 12)('Barfi box', 9)(The sales are made up for this paper.)
Marking scheme
- i.
WHERE kind = 'sweet' AND price < 500, with the text in quotes. - i.
ORDER BY price, giving Jeri (380) and then the laddu box (450). - ii.
GROUP BY day. - ii.
SUM(quantity)for each day: Kag Tihar 34, Kukur Tihar 41, Laxmi Puja 146. - iii. A JOIN of sales and items
ON sales.item_id = items.item_id. - iii. Only Laxmi Puja, the most first: Marigold garland 60, Diyo 40, Candles 25, Jeri 12, Barfi box 9.
Lost at the mela. At the Dashain mela on the school ground, children who get lost are taken to the help desk by the fewest paths between stalls. The dictionary below shows which places are joined by a path (the fireworks area is fenced off). Write a function fewest_steps(graph, start, goal) that returns the route with the fewest paths as a list of places, or None if there is no way. Then print the route and the number of paths:
- from the Swings to the Help desk;
- from the Parking to the Help desk;
- from the Fireworks area to the Help desk (print “No way” if there is none).
mela = { "Main gate": ["Parking", "Food stalls", "Ferris wheel"], "Parking": ["Main gate"], "Food stalls": ["Main gate", "Stage", "Toilets"], "Ferris wheel": ["Main gate", "Swings"], "Swings": ["Ferris wheel", "Stage"], "Stage": ["Food stalls", "Swings", "Help desk"], "Toilets": ["Food stalls", "Help desk"], "Help desk": ["Stage", "Toilets"], "Fireworks area": [],} # Write fewest_steps hereAnswer
mela = { "Main gate": ["Parking", "Food stalls", "Ferris wheel"], "Parking": ["Main gate"], "Food stalls": ["Main gate", "Stage", "Toilets"], "Ferris wheel": ["Main gate", "Swings"], "Swings": ["Ferris wheel", "Stage"], "Stage": ["Food stalls", "Swings", "Help desk"], "Toilets": ["Food stalls", "Help desk"], "Help desk": ["Stage", "Toilets"], "Fireworks area": [],} 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: place = to_visit.pop(0) if place == goal: route = [] while place is not None: route.append(place) place = came_from[place] route.reverse() return route for nxt in graph[place]: if nxt not in came_from: came_from[nxt] = place to_visit.append(nxt) return None for start in ["Swings", "Parking", "Fireworks area"]: route = fewest_steps(mela, start, "Help desk") if route is None: print(start, "to Help desk: No way") else: print(start, "to Help desk:", " → ".join(route), "(" + str(len(route) - 1), "paths)")Output
Swings to Help desk: Swings → Stage → Help desk (2 paths)Parking to Help desk: Parking → Main gate → Food stalls → Stage → Help desk (4 paths)Fireworks area to Help desk: No wayFrom the Parking, the way through the Toilets is also 4 paths: any route 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 withappend(). - Marks a place 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 route and the number of paths (one less than the places): 2 and 4.
- Returns
Nonewhen the list runs out, and the program prints “No way” for the fireworks area.
Viva. The teacher asks each student about their own work, for example:
- i.In sweets.py, what does
boxes // 4work out, and why did you test 14 and 16 boxes? (2) - ii.In your Tihar sales, what does
GROUP BY daydo in the second query? What wouldSELECT SUM(quantity) FROM salesgive without it? (2) - iii.In
fewest_steps, why do you put a place incame_fromwhen you add it to the list, and not later, when you visit it? (2)
Answer
- i.
//divides and keeps only the whole number: the number of complete groups of 4 boxes, which is the number of free boxes (15 // 4 is 3). 14 boxes cost Rs 4,950 and 16 boxes Rs 5,400 before the Rs 200 off, so they test both sides of the Rs 5,000 edge, where mistakes such as>instead of>=, or taking the Rs 200 off before the free boxes, show up. - ii.It makes one group for each day, and
SUM(quantity)adds up the quantity within each group, so there is one row per day. Without it, all the rows are one group: a single row, the total for the whole festival, 221. - iii.So that no place is added to the list twice. Stage, for example, is next to both the Food stalls and the Swings; if it were marked only when visited, it would be added once from each and visited twice, which wastes work. Marking it when it is first added also keeps the note of where it was first reached from, which is on a route with the fewest paths.
Marking scheme
- i.
//gives the whole number of groups of 4: the free boxes. - i. 14 and 16 are either side of the Rs 5,000 edge, where mistakes hide.
- ii. GROUP BY makes one group (one row) per day, and SUM adds within each group.
- ii. Without it, one row: the total for all days, 221.
- iii. So that no place is added (and visited) twice.
- iii. The first note kept is where it was first reached from, on a route with the fewest steps.
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.
