GCSE Computer Science Paper 2: Application of Computational Thinking
A full length 1CP2/02 onscreen paper in Python 3: complete a temperature converter, fix the logic errors in a grading program, then write a rainfall report, a Caesar cipher, a gym report that reads and writes files, and the subprograms for a sports day.
Instructions
- Time allowed
- 2 hours
- Total marks
- 75
- Calculator
- You do not need a calculator.
- Answer all the questions.
- The number of marks for each question is shown in brackets. Use it as a guide to how much to write.
- The clock at the top counts down from the real time allowed. When it reaches zero the paper is locked and marked, as it would be collected in the exam hall.
- Each question gives you a code file to amend. Write your answers in Python 3.
- Use the Run button to test your program. In the real exam you would save each file as, for example, Q01FINISHED.py.
- Read each question to the end before you start. Run your program on the example in the question, and on values at the edges, before you move on. Every program is marked by running it.
Questions
Answer every question, then finish the paper to have it marked. Marking as you go teaches you far less.
# Convert a temperature from Celsius to Fahrenheit
# -----------------------------------------------------------------
# Global variables
# -----------------------------------------------------------------
celsius = 0.0
fahrenheit = 0.0
# -----------------------------------------------------------------
# Main program
# -----------------------------------------------------------------
# =====> Take a temperature in Celsius as a real number input from the user
# =====> Convert the temperature to Fahrenheit, using F = C x 9 / 5 + 32
# =====> Display the temperature in Fahrenheit, with a message
# =====> Display Freezing if the temperature is 0 Celsius or below
- LTakes the temperature as an input
- LConverts the input to a real number, so 21.5 is accepted
- LConverts correctly: 100 Celsius is 212 Fahrenheit
- LConverts correctly with a fraction: 21.5 Celsius is 70.7 Fahrenheit
- LDisplays the Fahrenheit temperature with a message
- LDisplays Freezing for 0 Celsius and below
- LDoes not display Freezing above 0 Celsius
float() accepts a real number. The condition uses <= so that exactly 0 counts as freezing.
# Convert a temperature from Celsius to Fahrenheit
celsius = 0.0
fahrenheit = 0.0
celsius = float(input("Enter a temperature in Celsius: "))
fahrenheit = celsius * 9 / 5 + 32
print("The temperature in Fahrenheit is", fahrenheit)
if celsius <= 0:
print("Freezing")# Grade the test marks of five students and count how many passed
passed = 0
for student in range(1, 5):
mark = int(input("Enter a mark out of 50: "))
if (mark < 0) and (mark > 50):
print("Invalid mark")
elif (mark > 40):
print("Distinction")
passed = passed + 1
elif (mark >= 30):
print("Merit")
passed = passed + 1
elif (mark >= 20):
print("Merit")
passed = passed + 1
else:
print("Fail")
print("Number passed:", passed)
- LGrades five students
- LDisplays Invalid mark for a mark below 0
- LDisplays Invalid mark for a mark above 50
- LGives a Distinction for exactly 40
- LGives a Pass, not a Merit, for 20 to 29
- LStill gives Merit for 30 to 39 and Fail below 20
- LCounts the passes: 3 for 45, 35, 25, 15 and 5
- LDoes not count an invalid mark as a pass
Four fixes: range(5) grades five students, or replaces and because no mark is both below 0 and above 50, >= 40 includes 40, and the third grade is Pass.
# Grade the test marks of five students and count how many passed
passed = 0
for student in range(5):
mark = int(input("Enter a mark out of 50: "))
if (mark < 0) or (mark > 50):
print("Invalid mark")
elif (mark >= 40):
print("Distinction")
passed = passed + 1
elif (mark >= 30):
print("Merit")
passed = passed + 1
elif (mark >= 20):
print("Pass")
passed = passed + 1
else:
print("Fail")
print("Number passed:", passed)Example output for the readings 0, 12.5, 3, 0, 20, 8.5 and 0
Total: 44.0 mm
Average: 6.3 mm
Highest: 20.0 mm on Friday
Dry days: 3
Dry week# Weekly rainfall report
days = ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"]
rainfall = []
# =====> Write your program here
- LTakes seven readings as real numbers: total 62.5 for the second week
- LAccepts a reading of 0: total 44.0 for the example
- LRejects a negative reading
- LKeeps asking until the reading is valid
- LDisplays the average rounded to 1 decimal place: 6.3
- LDisplays the correct average for other readings: 8.9
- LDisplays the highest rainfall: 20.0
- LDisplays the day of the highest rainfall: Friday
- LFinds the highest when it falls on the last day
- LFinds the highest when it falls on the first day
- LCounts the dry days: 3
- LCounts no dry days when every day had rain
- LDisplays Wet week when the total is more than 50 mm
- LDisplays Dry week when the total is exactly 50 mm
- LDisplays the four results in the order and format shown
Validate each reading with a while loop before appending it. One pass through the list can then add up the total, track the highest reading and its day, and count the zeros.
# Weekly rainfall report
days = ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"]
rainfall = []
for day in days:
reading = float(input("Rainfall on " + day + " in mm: "))
while reading < 0:
print("Rainfall cannot be negative")
reading = float(input("Rainfall on " + day + " in mm: "))
rainfall.append(reading)
total = 0.0
highest = rainfall[0]
highestDay = days[0]
dryDays = 0
for index in range(len(rainfall)):
total = total + rainfall[index]
if rainfall[index] > highest:
highest = rainfall[index]
highestDay = days[index]
if rainfall[index] == 0:
dryDays = dryDays + 1
average = round(total / len(rainfall), 1)
print("Total:", total, "mm")
print("Average:", average, "mm")
print("Highest:", highest, "mm on", highestDay)
print("Dry days:", dryDays)
if total > 50:
print("Wet week")
else:
print("Dry week")# Caesar cipher
# =====> Write your program here
- LEncrypts a lower case message
- LKeeps upper case letters in upper case
- LWraps round from z to a
- LWraps round from Z to A
- LKeeps the case of each letter in a mixed message
- LLeaves spaces unchanged
- LLeaves digits and punctuation unchanged
- LDecrypts a message
- LDecrypts with wrapping round from a to z
- LAccepts e or d in lower case
- LKeeps asking until E or D is entered
- LRejects a shift of 0 and asks again
- LRejects a shift of 26 and asks again
- LAccepts a shift of 25
- LKeeps asking until the shift is valid, however many times
ord() and chr() convert between letters and codes. Taking the position in the alphabet, adding the shift and using % 26 wraps round in both directions; decrypting is encrypting with the shift made negative.
# Caesar cipher
choice = input("Encrypt or decrypt (E/D)? ").upper()
while choice != "E" and choice != "D":
choice = input("Please enter E or D: ").upper()
message = input("Enter the message: ")
shift = int(input("Enter a shift from 1 to 25: "))
while shift < 1 or shift > 25:
shift = int(input("The shift must be from 1 to 25: "))
if choice == "D":
shift = -shift
result = ""
for character in message:
if "A" <= character <= "Z":
result = result + chr((ord(character) - ord("A") + shift) % 26 + ord("A"))
elif "a" <= character <= "z":
result = result + chr((ord(character) - ord("a") + shift) % 26 + ord("a"))
else:
result = result + character
print("Result:", result)members.txt
Asha,34,12
Ben,19,3
Cara,45,20
Dev,27,0
Emi,52,4
Finn,38,9Example output for this file
Members: 6
Most visits: Cara
Average age: 35.8
Reminders written: 3# Gym members report
# Each line of members.txt holds a member's name, age and number of visits this month
# =====> Write your program here
- LReads every line of the file: 6 members
- LCounts the members in a different file: 4
- LFinds the member with the most visits: Cara
- LFinds the most visits when it is a later member: Yara
- LFinds the most visits when it is the first member: Omar
- LCompares visits as numbers, not as text: 10 is more than 9
- LCalculates the average age: 35.8
- LRounds the average age to 1 decimal place: 34.3
- LCreates the file reminders.txt
- LWrites every member with fewer than 5 visits
- LWrites no member with 5 or more visits, so Quin, with exactly 5, is left out
- LWrites one name per line, with nothing else
- LDisplays how many names were written: 3
- LDisplays the count for a different file: 1
- LDisplays the results in the order and format shown
Read the file a line at a time, strip the newline and split on commas, converting the age and visits to integers so they compare as numbers. Open reminders.txt for writing before the loop, so it is created even when nothing is written.
# Gym members report
count = 0
totalAge = 0
mostVisits = -1
mostName = ""
written = 0
reminders = open("reminders.txt", "w")
members = open("members.txt", "r")
for line in members:
parts = line.strip().split(",")
name = parts[0]
age = int(parts[1])
visits = int(parts[2])
count = count + 1
totalAge = totalAge + age
if visits > mostVisits:
mostVisits = visits
mostName = name
if visits < 5:
reminders.write(name + "\n")
written = written + 1
members.close()
reminders.close()
print("Members:", count)
print("Most visits:", mostName)
print("Average age:", round(totalAge / count, 1))
print("Reminders written:", written)# Sports day results
# Each record holds a runner's name, house and time in seconds
results = [
["Ava", "Red", 14.2],
["Ben", "Blue", 13.8],
["Cal", "Green", 15.1],
["Dee", "Red", 13.5],
["Eli", "Blue", 14.9],
["Fay", "Green", 13.9]
]
# -----------------------------------------------------------------
# Subprograms
# -----------------------------------------------------------------
def fastest(records):
# =====> Return the name of the runner with the lowest time
pass
def houseCount(records, house):
# =====> Return the number of runners in the given house
pass
def averageTime(records, house):
# =====> Return the average time of the runners in the given house,
# rounded to 2 decimal places. Return 0 if the house has no runners.
pass
def points(position):
# =====> Return the points for a finishing position:
# 1st 10, 2nd 8, 3rd 6, 4th to 6th 3, any other position 0
pass
# -----------------------------------------------------------------
# Main program
# -----------------------------------------------------------------
# =====> Display the name of the fastest runner, then the average time for each house
- Lfastest returns Dee for the results given
- Lfastest works when the fastest runner is first
- Lfastest works when the fastest runner is last
- LhouseCount returns 2 for Red
- LhouseCount returns 0 for a house with no runners
- LaverageTime returns 13.85 for Red
- LaverageTime returns 14.35 for Blue
- LaverageTime rounds to 2 decimal places
- LaverageTime returns 0 for a house with no runners
- Lpoints gives 10, 8 and 6 for the first three places
- Lpoints gives 3 for 4th, 5th and 6th place
- Lpoints gives 0 for any other position
- LThe main program displays the fastest runner
- LThe main program displays the average time for each house
- LThe main program uses the subprograms rather than repeating their code
Each subprogram loops through the records once. averageTime checks for an empty house first, so it never divides by zero, and rounds only the final answer.
# Sports day results
# Each record holds a runner's name, house and time in seconds
results = [
["Ava", "Red", 14.2],
["Ben", "Blue", 13.8],
["Cal", "Green", 15.1],
["Dee", "Red", 13.5],
["Eli", "Blue", 14.9],
["Fay", "Green", 13.9]
]
def fastest(records):
best = records[0]
for record in records:
if record[2] < best[2]:
best = record
return best[0]
def houseCount(records, house):
count = 0
for record in records:
if record[1] == house:
count = count + 1
return count
def averageTime(records, house):
if houseCount(records, house) == 0:
return 0
total = 0
for record in records:
if record[1] == house:
total = total + record[2]
return round(total / houseCount(records, house), 2)
def points(position):
if position == 1:
return 10
elif position == 2:
return 8
elif position == 3:
return 6
elif position >= 4 and position <= 6:
return 3
else:
return 0
print("Fastest runner:", fastest(results))
for house in ["Red", "Blue", "Green"]:
print(house, "average time:", averageTime(results, house))This is an original paper modelled on the real Pearson Edexcel 1CP2/02 past papers: the same structure, the same balance of topics, the same command words and mark tariffs, 75 marks in 2 hours, exactly as the real paper allows. It is not a past paper. Real past papers are the copyright of the exam board and cannot be republished here, so links to the official papers on the board's own site are on the exam papers page.