CONTENT AREA 2 · CORE PAPER 1

Content Area 2: Introduction to Programming

Content area 2 is the programming core. In the exam you will be asked to read, write, trace and fix Python 3.10+ code, and to explain programming concepts and make judgements about algorithms and testing. The Employer Set Project also relies on this content.

Spec checklist

Rate each point. Be honest: 'Secure' means you could answer an exam question on it now without notes.

2.1.1Define integer, float, string and Boolean and say when each is used
2.2.1–2Define variables and constants, their purpose and when they are used
2.2.3Explain why data type conversion functions are used
2.2.4–6Define scope, explain global and local variables, and use scope in code
2.2.7–9Declare and use variables and constants; use int(), float(), str(), bool()
2.3.1Describe lists, arrays and dictionaries and when each is used
2.3.2–4Interpret, develop and debug code that uses data structures
2.4.1–3Explain arithmetic, relational and Boolean operators
2.4.4–7Use, interpret, create and debug code using operators
2.5.1–2Implement keyboard, screen and text file input and output
2.5.3–5Interpret, create and debug input/output code
2.6.1–4Explain sequence, selection (if, elif, else, match/case) and iteration (for, while)
2.6.5Give benefits and drawbacks of loops
2.6.6–8Interpret, develop and debug code using sequence, selection and iteration
2.7.1–2Describe the characteristics of functions and procedures
2.7.3–4Say where functions and procedures come from; benefits and drawbacks of pre-written code
2.7.5–7Interpret, develop and debug user-written and pre-written functions and procedures
2.8.1Define validation and explain presence, length, range, type, format and check digit checks
2.8.2–4Interpret, develop and debug validation code
2.9.1–4Decide the logical order of actions and operations; choose data structures for time and memory efficiency
2.9.5–6Explain naming conventions (meaningful names, camelCase, snake_case) and code style
2.9.7Judge the suitability of an algorithm
2.10.1Describe the characteristics of robust code
2.10.2–5Explain debugging; locate and correct errors in code
2.11.1–2Explain how linear search, binary search, bubble sort, insertion sort and merge sort work
2.11.3–5Compare algorithms using memory, execution time, comparisons, and best/worst/average case
2.11.6–7Judge which searching or sorting algorithm suits a situation
2.12.1Explain why components are tested separately before being combined
2.12.2Define and use the testing methods (concept to open box)
2.12.3Explain macros, scripts and functional testing tools for automation
2.12.4Create valid, invalid, boundary and erroneous test data and write a test plan

2.1 Standard data types

Every value in a program has a data type. The data type decides what the value can store and what you can do with it.

Data typePythonWhat it storesExample valuesUse it for
IntegerintWhole numbers42, -7, 0Counting, ages, quantities, scores, loop counters
FloatfloatNumbers with a decimal part3.99, -0.5, 2.0Prices, measurements, averages, temperatures
StringstrText: letters, digits, symbols"Leeds", "07700 900123"Names, addresses, postcodes, phone numbers
BooleanboolOne of two valuesTrue, FalseFlags and yes/no states: logged_in, in_stock
quantity = 3            # int
price = 4.75            # float
product = "Meal deal"   # str
in_stock = True         # bool
print(type(quantity), type(price), type(product), type(in_stock))
<class 'int'> <class 'float'> <class 'str'> <class 'bool'>

✗ COMMON MISTAKE

  • Phone numbers and postcodes are strings, not integers. You never do maths on them, and an integer would drop a leading zero (07700 becomes 7700).
  • "42" in quotes is a string. 42 without quotes is an integer. "4" + "2" gives "42", not 6.
  • Money is often stored as a float in exam answers, but floats can give tiny rounding errors: 0.1 + 0.2 gives 0.30000000000000004. Real payment systems often store pence as an integer.

? QUICK CHECK

  • Which data type would you use for: a student's date of birth day number; a bank balance; an email address; whether a user has accepted cookies?
  • Why is a mobile number stored as a string?
Integer
A whole number, positive, negative or zero. Python type int.
Float
A number with a decimal (fractional) part. Python type float.
String
A sequence of characters, written in quotes. Python type str.
Boolean
A value that is either True or False. Python type bool.

2.2 Variables, constants, conversion and scope

Variables and constants

VariableConstant
DefinitionA named memory location whose value can change while the program runs.A named value that does not change while the program runs.
PurposeStore data the program needs to work with and update, e.g. a running total.Store a fixed value once, so it is easy to read and to update in one place.
Python examplescore = 0 then score = score + 10VAT_RATE = 0.2
When usedUser input, totals, counters, results of calculations.Tax rates, maximum login attempts, pi, file names.

Python has no built-in way to lock a constant. By convention, a name in CAPITALS tells other programmers not to change it.

MAX_ATTEMPTS = 3   # constant
attempts = 0       # variable
attempts = attempts + 1
print(f"Attempt {attempts} of {MAX_ATTEMPTS}")
Attempt 1 of 3

★ EXAM TIP

Benefit of constants: if the VAT rate changes, you change it on one line and every calculation updates. This avoids missing one copy of 0.2 buried in the code and makes the program easier to maintain.

Data type conversion (casting)

input() always returns a string. To do maths with it, convert it first. Conversion is also needed to join numbers into strings.

FunctionConverts toExampleResult
int()Integerint("25") / int(7.9)25 / 7 (decimal part is cut off, not rounded)
float()Floatfloat("3.5") / float(4)3.5 / 4.0
str()Stringstr(99)"99"
bool()Booleanbool(0) / bool("hello") / bool("")False / True / False
age = int(input("Enter your age: "))
print("Next year you will be " + str(age + 1))
Enter your age: 17
Next year you will be 18

✗ COMMON MISTAKE

  • int("3.5") crashes with a ValueError. Convert to float first: int(float("3.5")) gives 3.
  • bool("False") is True. Any non-empty string converts to True.
  • print("Total: " + 10) crashes with a TypeError. Use str(10) or an f-string.

Scope: global and local variables

Scope is the part of the program where a variable can be used.

  • A global variable is created outside any function. It can be read anywhere in the program.
  • A local variable is created inside a function. It only exists while the function is running and cannot be used outside it.
  • To change a global variable inside a function, Python needs the global keyword.
basket_total = 0            # global

def add_item(price):
    global basket_total
    discount = 0.1          # local: only exists inside add_item
    basket_total = basket_total + price * (1 - discount)

add_item(20)
add_item(10)
print(basket_total)
27.0
Global variablesLocal variables
BenefitsAvailable everywhere, so useful for values many parts of the program need (e.g. settings).Can't be changed by accident elsewhere. The same name can be reused in different functions. Memory is freed when the function ends. Functions are self-contained and easier to test and reuse.
DrawbacksAny function can change them, so bugs are hard to trace. Use memory for the whole run. Make functions depend on outside values.Values are lost when the function ends unless returned.

★ EXAM TIP

Good practice is to use local variables and pass values in as parameters and back out with return. If asked why, say: it reduces side effects, makes code easier to debug, and makes functions reusable.

Variable
A named location in memory that stores a value which can change while the program runs.
Constant
A named value that does not change while the program runs. In Python, written in CAPITALS by convention.
Casting / type conversion
Changing a value from one data type to another, e.g. int("42").
Scope
The part of a program where a variable can be accessed.
Global variable
A variable declared outside any function, which can be read anywhere in the program.
Local variable
A variable declared inside a function. It only exists while that function runs.

2.3 Data structures

StructureDescriptionPythonUse it when
ListOrdered, changeable, can hold mixed types, grows and shrinks.orders = ["latte", "tea", 3]You have a collection that changes size, e.g. a shopping basket.
ArrayOrdered collection where every item is the same data type. More memory efficient.import array
temps = array.array("f", [12.5, 13.0])
You store lots of values of one type, e.g. sensor readings. In exams, a list of one type is often used as an array.
DictionaryUnordered by position; stores key: value pairs. Keys must be unique.stock = {"cola": 12, "water": 30}You need to look something up by a label, e.g. product code to price, username to password hash.

List and dictionary operations (Appendix 2)

queue = ["Asha", "Ben", "Chloe"]
queue.append("Dev")          # add to end
queue.insert(0, "Ellie")     # add at index 0
queue.remove("Ben")          # remove by value
first = queue.pop(0)         # remove and return item at index 0
print(first, queue, len(queue))
print(queue.index("Chloe"), "Dev" in queue, "Ben" not in queue)
queue.sort()
print(queue)
Ellie ['Asha', 'Chloe', 'Dev'] 3
1 True True
['Asha', 'Chloe', 'Dev']
prices = {"latte": 3.20, "tea": 1.80}
prices["mocha"] = 3.50       # add a new key
prices["tea"] = 1.95         # update an existing key
for drink, price in prices.items():
    print(f"{drink}: £{price:.2f}")
print("cocoa" in prices)
latte: £3.20
tea: £1.95
mocha: £3.50
False

2D lists

A list can hold other lists, which works like a table. Use two indexes: [row][column].

seats = [["A1", "A2", "A3"],
         ["B1", "B2", "B3"]]
print(seats[1][2])
for row in seats:
    print(len(row), row[0])
B3
3 A1
3 B1

✗ COMMON MISTAKE

  • Indexes start at 0. In a list of 5 items, the last index is 4. items[5] raises an IndexError.
  • Looking up a key that does not exist in a dictionary raises a KeyError. Check with if key in my_dict: first.

Worked example: debugging a data structure

This code should print the total of all marks. It crashes. Find and fix the error.

marks = [45, 67, 89, 72]
total = 0
for i in range(1, len(marks) + 1):
    total = total + marks[i]
print(total)
Found it? Click to check.

Error: range(1, len(marks) + 1) produces 1, 2, 3, 4. Index 4 does not exist, so an IndexError occurs on the last loop. It also skips index 0. Fix: use range(len(marks)) or loop directly over the list:

marks = [45, 67, 89, 72]
total = 0
for mark in marks:
    total = total + mark
print(total)
273
List
An ordered, changeable collection of items that can hold mixed data types and grow or shrink.
Array
An ordered collection of items that are all the same data type.
Dictionary
A collection of key–value pairs. Values are looked up by key rather than position.
Index
The position of an item in a list, array or string. Python starts counting at 0.

2.4 Operators

Arithmetic operators

OperatorNameExampleResultTypical use
+Add7 + 29Totals
-Subtract7 - 25Change given, stock left
*Multiply7 * 214Price × quantity
/Divide7 / 23.5 (always a float)Averages
**Exponentiation7 ** 249Powers, compound interest
//Integer division7 // 23How many full boxes, whole hours from minutes
%Modulus (remainder)7 % 21Odd/even, items left over, wrapping around

Worked example: // and %

minutes = 135
hours = minutes // 60
left_over = minutes % 60
print(f"{hours} h {left_over} min")
eggs = 26
print("Full boxes:", eggs // 6, "Spare eggs:", eggs % 6)
2 h 15 min
Full boxes: 4 Spare eggs: 2

Relational operators

Relational operators compare two values and always give a Boolean result.

OperatorMeaningExampleResult
==Equal to (equivalence)5 == 5True
!=Not equal to5 != 3True
<Less than3 < 5True
>Greater than3 > 5False
<=Less than or equal to5 <= 5True
>=Greater than or equal to4 >= 5False

✗ COMMON MISTAKE

= assigns a value. == compares. if age = 18: is a syntax error.

Boolean operators

OperatorTrue when...Example
andboth conditions are Trueage >= 18 and has_id
orat least one condition is Trueday == "Sat" or day == "Sun"
notthe condition is False (it reverses it)not logged_in
ABA and BA or Bnot A
TrueTrueTrueTrueFalse
TrueFalseFalseTrueFalse
FalseTrueFalseTrueTrue
FalseFalseFalseFalseTrue

Order of operations

Python follows BIDMAS: brackets, then **, then * / // %, then + -. Then relational operators, then not, and, or.

print(2 + 3 * 4)
print((2 + 3) * 4)
print(10 - 4 / 2)
mark_a, mark_b = 60, 80
print(mark_a + mark_b / 2)      # logic error
print((mark_a + mark_b) / 2)    # correct average
14
20
8.0
100.0
70.0

▲ STRETCH

Explain why (mark_a + mark_b) / 2 must use brackets, and why the wrong version does not produce an error message. (It is a logic error: the code is valid Python, so it runs, but the output is wrong.)

2.5 Input and output

Keyboard and screen

  • input("prompt") displays the prompt, waits for the user to press Enter and returns what they typed as a string.
  • print() outputs to the screen. Separate items with commas, join strings with +, or use an f-string.
  • .format() and f-strings can format numbers: {price:.2f} shows 2 decimal places.
name = input("Name: ")
hours = float(input("Hours worked: "))
rate = 11.44
pay = hours * rate
print(f"{name} earned £{pay:.2f}")
print("{} earned £{:.2f}".format(name, pay))
Name: Sam
Hours worked: 16
Sam earned £183.04
Sam earned £183.04

Text files

StepCodeNotes
Open for writingf = open("log.txt", "w")"w" creates the file or overwrites it. "a" appends to the end.
Write linesf.write("Login OK\n")write() does not add a new line. Add \n yourself. Only strings can be written.
Closef.close()Saves the data and frees the file. Data may be lost if you forget.
Open for readingf = open("log.txt", "r")Raises FileNotFoundError if the file does not exist.
Readf.read() / f.readline() / f.readlines()Whole file as one string / one line / list of lines.
scores = {"Asha": 18, "Ben": 12, "Chloe": 20}

f = open("scores.txt", "w")
for name, score in scores.items():
    f.write(name + "," + str(score) + "\n")
f.close()

f = open("scores.txt", "r")
for line in f.readlines():
    parts = line.strip().split(",")
    print(parts[0], "scored", int(parts[1]))
f.close()
Asha scored 18
Ben scored 12
Chloe scored 20

line.strip() removes the \n and spaces from each end. line.split(",") breaks the line into a list at every comma.

★ EXAM TIP

You may also see with open("scores.txt", "r") as f:. This closes the file automatically when the indented block ends, even if an error happens. It is good practice, and worth mentioning in a 'robust code' answer.

✗ COMMON MISTAKE

  • Opening an existing file in "w" mode wipes it. Use "a" to add to it.
  • f.write(score) crashes if score is an integer. Use str(score).
  • Forgetting .strip() leaves \n on the end, so "Ben\n" == "Ben" is False.

2.6 Actions: sequence, selection and iteration

ConstructWhat it doesWhen it is used
SequenceRuns instructions one after another, in order.Always. The order matters: you must get input before you process it.
SelectionChooses which block of code to run based on a condition.When the program needs to make a decision: grade boundaries, menu choices, login checks.
IterationRepeats a block of code.When something needs doing more than once: processing every item in a list, re-asking for valid input.

Selection: if / elif / else

mark = 64
if mark >= 70:
    grade = "Distinction"
elif mark >= 55:
    grade = "Merit"
elif mark >= 40:
    grade = "Pass"
else:
    grade = "Fail"
print(grade)
Merit

Conditions are checked from the top. The first True one runs and the rest are skipped. That is why the highest boundary goes first: if mark >= 40 came first, 64 would get a Pass.

Selection: match / case (Python 3.10+)

match compares one value against several possible patterns. It is tidier than a long elif chain when you are checking a single value for exact matches, such as a menu choice.

choice = "2"
match choice:
    case "1":
        print("View basket")
    case "2":
        print("Checkout")
    case "3" | "q":
        print("Quit")
    case _:
        print("Invalid option")
Checkout

case _: is the default and works like else. | means 'or'. match cannot do range checks like mark >= 70 without extra syntax, so use if for those.

Iteration

LoopTypePythonUse when
Count-controlledRepeats a fixed number of timesfor i in range(5):
for item in basket:
You know how many times before the loop starts: every item in a list, 10 questions.
Condition-controlledRepeats while a condition is True ('while do')while password != "admin123":You don't know how many times: until valid input, until the user quits.
for i in range(1, 11, 3):
    print(i, end=" ")
print()
total = 0
count = 0
while total < 20:
    total = total + 7
    count = count + 1
print(total, count)
1 4 7 10
21 3

range(start, stop, step): stop is not included. range(5) gives 0, 1, 2, 3, 4.

Benefits and drawbacks of loops (2.6.5)

BenefitsDrawbacks
  • Less code: one block instead of copying lines
  • Easier to maintain: change it once
  • Works for any amount of data, e.g. a list of 10 or 10,000
  • Fewer chances of a copy-and-paste error
  • Infinite loop if the condition never becomes False (program hangs)
  • Off-by-one errors with range() boundaries
  • Nested loops on large data can be slow
  • Harder for beginners to trace than straight-line code

Worked example: trace table

A trace table records the value of each variable as the code runs, line by line. It is the best way to answer 'what is the output' questions. Draw your own before you check.

n = 5
result = 1
while n > 1:
    result = result * n
    n = n - 2
print(result)
15
Show the trace table
nresultn > 1?Output
51True
35True
115False
15

? QUICK CHECK

  • Rewrite the loop above as a for loop using range() with a step.
  • Why is a while loop the right choice for asking a user to re-enter a PIN until it is correct?
Sequence
Instructions run one after another in the order written.
Selection
Choosing which code to run based on a condition (if, elif, else, match/case).
Iteration
Repeating a block of code (a loop).
Count-controlled loop
A loop that repeats a set number of times (for).
Condition-controlled loop
A loop that repeats while a condition is True (while).

2.7 Functions and procedures

FunctionProcedure
ParametersMay or may not take parametersMay or may not take parameters
Returns a value?Must return a result using returnMust not return a result
Example useCalculate VAT and return it; validate an email and return True/FalseDisplay a menu; write a line to a log file
def calculate_vat(price, rate=0.2):      # function: returns a value
    return round(price * rate, 2)

def print_receipt(item, price):          # procedure: no return value
    vat = calculate_vat(price)
    print(f"{item:<10} £{price:>6.2f}  VAT £{vat:.2f}")

print_receipt("Keyboard", 24.99)
print_receipt("Mouse", 9.5)
Keyboard   £ 24.99  VAT £5.00
Mouse      £  9.50  VAT £1.90

price and rate are parameters. 24.99 is an argument: the actual value passed in. rate=0.2 is a default value used if no argument is given.

Where functions and procedures come from (2.7.3)

SourceExample
User-writtencalculate_vat() above
Pre-written, built into the languageprint(), len(), round(), max(), min(), range(), ord(), chr()
Pre-written, in libraries supplied with the language (standard library)math.sqrt(), math.floor(), math.ceil(), random.randint(), datetime.now()
Pre-written, in third-party librariespandas, matplotlib, requests (installed with pip)
import math
import random

print(math.floor(7.8), math.ceil(7.2), math.trunc(-7.8))
print(math.sqrt(81), math.pow(2, 5), round(math.pi, 3))
roll = random.randint(1, 6)
print(1 <= roll <= 6)
print(ord("A"), chr(66), max([4, 9, 2]), min(4, 9, 2))
7 8 -7
9.0 32.0 3.142
True
65 B 9 2

Benefits and drawbacks of pre-written code (2.7.4)

BenefitsDrawbacks
  • Saves development time and cost
  • Usually well tested, so fewer bugs
  • Written by specialists, often more efficient than your own
  • Lets you do complex things (graphs, data analysis) without expert knowledge
  • Documentation and community support available
  • May not do exactly what you need
  • You may not understand how it works, making debugging hard
  • Third-party code can contain security vulnerabilities or malicious code
  • Can be abandoned or stop being updated; updates can break your code
  • Licence restrictions may apply
  • Adds size to the program

★ EXAM TIP

Benefits of writing your own subroutines (user-written): reusable, easier to test each part on its own (unit testing), easier to read, and a team can work on different subroutines at the same time.

String handling methods (Appendix 2)

email = "  Sam.Jones@Example.co.uk  "
email = email.strip().lower()
print(email)
print(email.find("@"), email.index("."), email.count("o"))
user, domain = email.split("@")
print(user, domain, len(user))
print("abc123".isalnum(), "abc".isalpha())
print("2024".isdigit(), "ABC".isupper())
print(email.replace("example", "sample"))
sam.jones@example.co.uk
9 3 2
sam.jones example.co.uk 9
True True
True True
sam.jones@sample.co.uk
Function
A named subroutine that may take parameters and must return a value.
Procedure
A named subroutine that may take parameters and does not return a value.
Parameter
A variable listed in a subroutine definition that receives a value when the subroutine is called.
Argument
The actual value passed to a subroutine when it is called.
Library
A collection of pre-written code that can be imported, e.g. math, random.

2.8 Validation

Validation is an automatic check that input data is sensible and follows set rules before it is accepted. It reduces errors and stops a program crashing on bad data. It cannot check that data is correct: a valid date of birth may still be the wrong one.

CheckWhat it checksExample
PresenceSomething has been enteredSurname cannot be left blank
LengthNumber of characters is within limitsPassword at least 8 characters; mobile number exactly 11 digits
RangeA value is between a lower and upper limitAge 16–99; quantity 1–10
TypeData is the right data typeQuantity must be a whole number
FormatData matches a patternPostcode like LS1 4AP; email contains @ and a dot after it
Check digitA calculated digit at the end matches the rest of the numberISBN-13 on books, barcodes, bank card numbers
def get_quantity():
    while True:
        entry = input("Quantity (1-10): ")
        if entry == "":                        # presence check
            print("Error: quantity cannot be blank.")
        elif not entry.isdigit():              # type check
            print("Error: enter a whole number.")
        elif not 1 <= int(entry) <= 10:        # range check
            print("Error: quantity must be between 1 and 10.")
        else:
            return int(entry)

qty = get_quantity()
print("Accepted:", qty)
Quantity (1-10):
Error: quantity cannot be blank.
Quantity (1-10): two
Error: enter a whole number.
Quantity (1-10): 15
Error: quantity must be between 1 and 10.
Quantity (1-10): 4
Accepted: 4
def valid_password(pw):
    return len(pw) >= 8                        # length check

def valid_email(email):                        # simple format check
    if email.count("@") != 1:
        return False
    user, domain = email.split("@")
    return len(user) > 0 and "." in domain

print(valid_password("letmein"))
print(valid_email("ali@wakefield.ac.uk"))
print(valid_email("ali.wakefield"))
False
True
False

Check digit worked example: ISBN-13

Multiply the 13 digits alternately by 1 and 3 and add the results. If the total divides exactly by 10, the number is valid. A single mistyped digit or two swapped digits will usually fail.

def valid_isbn13(isbn):
    if len(isbn) != 13 or not isbn.isdigit():
        return False
    total = 0
    for i in range(13):
        weight = 1 if i % 2 == 0 else 3
        total = total + int(isbn[i]) * weight
    return total % 10 == 0

print(valid_isbn13("9780306406157"))
print(valid_isbn13("9780306406158"))
True
False

Try it: ISBN-13 checker

Try changing one digit, or swapping two neighbouring digits.

✗ COMMON MISTAKE

Range checks: if 1 < qty < 10 rejects 1 and 10. If the limits are allowed, use <=. Boundary test data catches exactly this error.

Validation
Automatic checks that input data is sensible and follows rules before it is accepted. It does not check data is correct.
Check digit
An extra digit calculated from the other digits in a number, used to detect input errors.

2.9 Design considerations and programming practices

Order of actions and operations (2.9.1–2.9.2, 2.9.4)

  • Actions must happen in a logical order: get input, validate it, process it, output the result. You cannot calculate a total before reading the prices.
  • Initialise variables before a loop. Setting total = 0 inside the loop resets it every time.
  • Use brackets so calculations follow the order you intend. This keeps outputs accurate and avoids logic errors.
  • Check for zero before dividing: if count > 0: average = total / count. This avoids a ZeroDivisionError.
  • For efficiency, do work once rather than inside a loop. Calculate len(items) once before the loop; put the most likely condition first in an if chain; stop a search as soon as the item is found.

Choosing data structures for efficiency (2.9.3)

SituationBetter choiceWhy
Look up a price by product code thousands of timesDictionaryLooking up a key is direct; a list would need searching item by item (slower execution time).
Store 1 million temperature readingsArray of floatsAll the same type, stored compactly, so less memory than a list of mixed objects.
A basket that grows and shrinksListEasy to append and remove items.
Fixed values that never changeConstants (or a tuple)Clear and protected from accidental change.

Naming conventions (2.9.5)

ConventionExampleNotes
Meaningful namestotal_price not tp or xCode explains itself; fewer comments needed; easier to maintain.
camelCasetotalPrice, getUserName()Used in Java, C# and JavaScript.
snake_casetotal_price, get_user_name()Python's style guide (PEP 8) recommends this for variables and functions.
CAPITALSMAX_SIZEConstants in Python.

Code style and readability (2.9.6)

  • Naming conventions: consistent names let any developer guess what a variable holds.
  • White space: blank lines between functions, spaces around operators (x = a + b), and consistent indentation make structure obvious. In Python, indentation is required, not optional.
  • Maximum line length: PEP 8 suggests 79 characters. Short lines can be read without scrolling sideways and are easier to compare side by side.

Hard to read:

def a(b,c):
    d=b*c
    if d>100:d=d*0.9
    return d
print(a(12,10))
108.0

Same logic, readable:

BULK_DISCOUNT = 0.9
BULK_THRESHOLD = 100


def order_cost(unit_price, quantity):
    cost = unit_price * quantity
    if cost > BULK_THRESHOLD:
        cost = cost * BULK_DISCOUNT
    return cost


print(order_cost(12, 10))
108.0

Judging an algorithm (2.9.7)

When asked to judge the suitability of an algorithm or program, comment on each of these:

CriterionQuestions to ask
Meets requirementsDoes it do everything the brief asks? Does it handle all cases, including edge cases?
Efficiency: storageDoes it keep unnecessary copies of data? Is the data structure memory efficient?
Efficiency: execution timeDoes it repeat work? Does it stop early when it can? Are there unnecessary nested loops?
Data structures and typesIs a dictionary used where lookups are needed? Are prices floats and counts integers?
Variables and constantsAre fixed values constants? Are variables local where possible?
PresentationIs output clear and formatted? Are prompts and error messages helpful?
MaintainabilityMeaningful names, comments, subroutines, consistent style, constants instead of magic numbers.
camelCase
Naming style where words are joined and each word after the first starts with a capital: totalPrice.
snake_case
Naming style where words are lower case and joined with underscores: total_price. Recommended for Python variables.

2.10 Robust code

Characteristics of robust code (2.10.1)

  • Handles unexpected inputs: validates input and re-prompts instead of crashing. Letters typed into a number field are rejected.
  • Handles unexpected terminations: uses try/except to catch runtime errors (missing file, network down, divide by zero) and closes files or saves data safely.
  • Produces specific and meaningful error messages: 'Quantity must be between 1 and 10' tells the user what to fix. 'Error' does not.
def read_total(filename):
    try:
        with open(filename, "r") as f:
            values = [float(line.strip()) for line in f]
        return sum(values)
    except FileNotFoundError:
        print(f"Error: '{filename}' was not found. Check the file name.")
    except ValueError:
        print(f"Error: '{filename}' contains a line that is not a number.")
    return None

with open("sales.txt", "w") as f:
    f.write("12.50\n8.25\nten\n")

print(read_total("sale.txt"))
print(read_total("sales.txt"))
Error: 'sale.txt' was not found. Check the file name.
None
Error: 'sales.txt' contains a line that is not a number.
None

Types of error

Error typeWhat happensExample
SyntaxCode breaks the language rules. It will not run at all.Missing colon: if x > 5; missing bracket; pritn(); bad indentation
RuntimeProgram starts but crashes when the line runs.10 / 0 (ZeroDivisionError); int("abc") (ValueError); items[10] (IndexError); missing file (FileNotFoundError)
LogicProgram runs but gives the wrong result. No error message.> instead of >=; wrong order of operations; total reset inside loop

Debugging (2.10.2–2.10.5)

Debugging is locating errors and then correcting them. It is used during development, after a test fails and when users report faults. Debugging makes code robust because each error found and fixed is one less way for the program to crash or give wrong results.

TechniqueHow it helps
Read the error messagePython gives the error type and line number.
Trace tables / dry runsFollow the code by hand to find where values go wrong. Essential for logic errors.
Print statementsPrint variable values at key points to see what is really happening.
IDE breakpointsPause the program at a chosen line and inspect variables.
SteppingRun one line at a time and watch the flow through selection and loops.
Test with planned dataValid, invalid, boundary and erroneous data show which cases fail.

Worked example: locate and correct

This program should count how many students passed (40 or more) and print the pass rate. It contains three errors. Find them before you check.

marks = [38, 40, 72, 55, 19]
for mark in marks:
    passed = 0
    if mark > 40:
        passed = passed + 1
rate = passed / len(marks) * 100
print("Pass rate: " + rate + "%")
Show the three errors and the corrected code
LineErrorTypeCorrection
3passed = 0 inside the loop resets the count each timeLogicMove it above the for line
4> 40 excludes a mark of exactly 40Logicif mark >= 40:
7Cannot join a float to a string with +Runtime (TypeError)print("Pass rate: " + str(rate) + "%")

Corrected:

marks = [38, 40, 72, 55, 19]
passed = 0
for mark in marks:
    if mark >= 40:
        passed = passed + 1
rate = passed / len(marks) * 100
print("Pass rate: " + str(rate) + "%")
Pass rate: 60.0%
Robust code
Code that handles unexpected inputs and terminations and gives specific, meaningful error messages.
Debugging
Locating and correcting errors in code.
Syntax error
Code that breaks the rules of the language, so it cannot run.
Runtime error
An error that happens while the program is running, causing it to crash, e.g. dividing by zero.
Logic error
The program runs but gives the wrong result.
Exception
An error object raised at runtime. Can be caught with try/except.

2.11 Common algorithms

You need to know how each algorithm works, be able to trace it, and judge when to use it. Big O notation is not required: compare using logical reasoning about comparisons, time and memory.

Try it: algorithm stepper

Pick an algorithm, type a list, then press Step to watch it work one comparison at a time.

Linear search

  1. Start at the first item.
  2. Compare it with the target.
  3. If it matches, stop and return the position.
  4. Otherwise move to the next item.
  5. If you reach the end without a match, the item is not there.
def linear_search(items, target):
    for i in range(len(items)):
        if items[i] == target:
            return i
    return -1

print(linear_search(["Leeds", "York", "Hull", "Wakefield"], "Hull"))
print(linear_search(["Leeds", "York"], "Bradford"))
2
-1

Binary search

The list must be sorted first.

  1. Find the middle item.
  2. If it is the target, stop.
  3. If the target is smaller, discard the middle item and everything above it.
  4. If the target is larger, discard the middle item and everything below it.
  5. Repeat on the half that is left until the target is found or nothing is left.
def binary_search(items, target):
    low = 0
    high = len(items) - 1
    while low <= high:
        mid = (low + high) // 2
        if items[mid] == target:
            return mid
        elif target < items[mid]:
            high = mid - 1
        else:
            low = mid + 1
    return -1

numbers = [3, 8, 12, 19, 25, 31, 40, 47, 52]
print(binary_search(numbers, 40))
6
Steplowhighmiditems[mid]Action
10842540 > 25, so low = 5
258640Found at index 6

Linear search would have needed 7 comparisons to find 40. Binary search needed 2.

Bubble sort

  1. Compare the first two items. If they are in the wrong order, swap them.
  2. Move along one place and compare the next pair. Repeat to the end of the list: this is one pass.
  3. After each pass the largest unsorted item has 'bubbled' to its correct place at the end.
  4. Repeat passes until a whole pass makes no swaps.
def bubble_sort(items):
    n = len(items)
    swapped = True
    while swapped:
        swapped = False
        for i in range(n - 1):
            if items[i] > items[i + 1]:
                items[i], items[i + 1] = items[i + 1], items[i]
                swapped = True
        n = n - 1
    return items

print(bubble_sort([5, 1, 4, 2, 8]))
[1, 2, 4, 5, 8]
After passListSwaps made
Start5 1 4 2 8
11 4 2 5 83 (5↔1, 5↔4, 5↔2)
21 2 4 5 81 (4↔2)
31 2 4 5 80, so stop

Insertion sort

  1. Treat the first item as a sorted list of one.
  2. Take the next item.
  3. Compare it with items in the sorted part, moving larger items one place right, until you find where it belongs.
  4. Insert it. Repeat until every item has been inserted.
def insertion_sort(items):
    for i in range(1, len(items)):
        current = items[i]
        j = i - 1
        while j >= 0 and items[j] > current:
            items[j + 1] = items[j]
            j = j - 1
        items[j + 1] = current
    return items

print(insertion_sort([7, 3, 9, 1, 5]))
[1, 3, 5, 7, 9]
InsertList afterwards (sorted part in bold)
Start7 3 9 1 5
33 7 9 1 5
93 7 9 1 5
11 3 7 9 5
51 3 5 7 9

Merge sort

  1. Split the list in half, then split each half again, until every list has one item (a list of one is sorted).
  2. Merge pairs of lists back together: compare the front item of each list and take the smaller one each time.
  3. Keep merging until there is one sorted list.
def merge_sort(items):
    if len(items) <= 1:
        return items
    mid = len(items) // 2
    left = merge_sort(items[:mid])
    right = merge_sort(items[mid:])
    merged = []
    i = j = 0
    while i < len(left) and j < len(right):
        if left[i] <= right[j]:
            merged.append(left[i])
            i = i + 1
        else:
            merged.append(right[j])
            j = j + 1
    merged = merged + left[i:] + right[j:]
    return merged

print(merge_sort([38, 27, 43, 3, 9, 82, 10]))
[3, 9, 10, 27, 38, 43, 82]
StageLists
Split[38 27 43] [3 9 82 10]
Split[38] [27 43] [3 9] [82 10]
Split[38] [27] [43] [3] [9] [82] [10]
Merge[38] [27 43] [3 9] [10 82]
Merge[27 38 43] [3 9 10 82]
Merge[3 9 10 27 38 43 82]

Comparing algorithms (2.11.3–2.11.5)

Metrics: memory space used, execution time, and number of comparisons. The table assumes a list of n items.

AlgorithmBest caseWorst caseAverage caseMemory
Linear searchTarget is first: 1 comparisonTarget is last or missing: n comparisonsAbout n ÷ 2 comparisonsNo extra memory
Binary searchTarget is the middle item: 1 comparisonKeeps halving until 1 item left: about 10 comparisons for 1,000 items, 20 for 1,000,000Close to the worst caseNo extra memory (but list must already be sorted)
Bubble sortAlready sorted: one pass, n − 1 comparisons, no swapsReverse order: every pair compared and swapped on every passMany passes; slow on large listsSorts in place, no extra memory
Insertion sortAlready sorted: n − 1 comparisonsReverse order: each item moves all the way to the frontSlow on large lists; good on small or nearly sorted listsSorts in place, no extra memory
Merge sortSame as worst: always splits and merges fullyMuch faster than bubble or insertion on large listsConsistent performanceNeeds extra memory for the sub-lists
AlgorithmBenefitsDrawbacks
Linear searchSimple. Works on unsorted data. Fine for short lists.Slow on long lists.
Binary searchVery fast on large lists.Data must be sorted first, which takes time. More complex to code.
Bubble sortSimple to understand and code. In place. Can detect a sorted list in one pass.Very slow on large or reversed lists.
Insertion sortSimple. In place. Fast for small or nearly sorted lists. Can sort data as it arrives.Slow on large, unsorted lists.
Merge sortFast and consistent on large lists.Uses more memory. More complex. Overkill for tiny lists.

★ EXAM TIP: JUDGING SUITABILITY (2.11.6–2.11.7)

  • Always link your choice to the scenario: size of the data, whether it is already sorted, how often it is searched, and memory limits.
  • A phone contact list searched many times a day: keep it sorted and use binary search; the sorting cost is paid once.
  • A list of 12 items searched once: linear search; sorting first would waste time.
  • A leaderboard where one new score is added to an already sorted list: insertion sort.
  • Sorting 2 million transaction records on a server with plenty of RAM: merge sort.
  • An embedded device with very little memory: an in-place sort (insertion or bubble).
Linear search
Checks each item in turn from the start until the target is found or the list ends.
Binary search
Repeatedly checks the middle item of a sorted list and discards the half that cannot contain the target.
Bubble sort
Compares adjacent pairs and swaps them if they are in the wrong order, repeating passes until no swaps are made.
Insertion sort
Builds a sorted section one item at a time by inserting each item into its correct position.
Merge sort
Splits a list into single items, then merges them back together in order.

2.12 Testing

Why test components separately (2.12.1)

Each part of a solution is tested on its own before everything is put together. Faults are easier and cheaper to find and fix in a small part than in the finished system, where it is hard to tell which part caused the problem.

ComponentWhy test it firstExample
SoftwareEach module must work before it is combined, so faults can be traced to one place.Test the login function on its own.
HardwareConfirms devices work and meet requirements before software depends on them.Check a barcode scanner reads codes reliably.
DataConfirms data is accurate, complete and in the right format.Check imported product prices have no blanks or text.
InterfacesConfirms components pass data correctly between each other and to users.Check the app sends the right data to the payment API.
Resulting service (final product)Confirms the whole system meets the requirements for real users.Full test of an online order from basket to confirmation email.

Testing methods (2.12.2)

MethodWhat it isBenefitsDrawbacksWhen
ConceptTesting an idea or prototype with users before full development.Finds bad ideas early, cheaply.Prototype may not reflect the real product.Start of a project
UnitTesting one component, such as a single function, on its own.Errors easy to locate. Can be automated.Does not show if parts work together.During development
BoundaryTesting values at and just beyond the edges of valid ranges.Finds off-by-one errors in conditions.Only covers limits, not general logic.Whenever there are ranges
IntegrationTesting that combined components work together.Finds interface and data-passing faults.Harder to locate which part failed.After unit testing
PerformanceMeasuring speed and responsiveness under normal use.Confirms the system is fast enough.Needs realistic environment and tools.Before release
SystemTesting the complete system against the requirements.Checks everything works end to end.Time-consuming. Faults found late cost more.After integration
AcceptanceThe client or end users check the system meets their needs.Confirms the client is happy before sign-off.Users may find issues that need major changes.Before handover
UsabilityWatching real users try tasks to see how easy the system is to use.Finds confusing design and accessibility issues.Subjective. Needs representative users.Prototype and before release
RegressionRe-running earlier tests after a change.Shows a fix has not broken something else.Repetitive; best automated.After every change or update
Load / stressLoad: expected peak users. Stress: pushing beyond limits to find the breaking point.Shows how the system copes on busy days and how it fails.Needs special tools to simulate users.Before launch, e.g. ticket sites
Closed boxTesting inputs and outputs without seeing the code (black box).Tests from the user's view. Tester needs no code knowledge.Some code paths may never be tested.System and acceptance testing
Open boxTesting with knowledge of the code, checking every path (white box).Can test every branch and loop.Needs programming knowledge. Time-consuming.Unit testing

Automation (2.12.3)

MethodPurposeWhen used
MacrosRecord and replay a sequence of actions, e.g. keystrokes and clicks in an application.Repetitive tasks in applications such as entering test data into a form or spreadsheet.
ScriptsCode written to run tests or tasks automatically, e.g. a Python script that calls a function with 100 sets of test data and checks results.Unit and regression testing; running the same tests after every change.
Functional testing toolsSoftware that tests whether features work as specified, often by driving the user interface automatically (e.g. Selenium, pytest).Regression, system and load testing on larger projects.

A simple test script:

def is_valid_age(age):
    return 16 <= age <= 99

tests = [(15, False), (16, True), (50, True), (99, True), (100, False)]
for value, expected in tests:
    actual = is_valid_age(value)
    result = "PASS" if actual == expected else "FAIL"
    print(value, "expected", expected, "got", actual, result)
15 expected False got False PASS
16 expected True got True PASS
50 expected True got True PASS
99 expected True got True PASS
100 expected False got False PASS

Test data (2.12.4.1–2.12.4.2)

Example: a cinema app accepts a number of tickets from 1 to 8.

TypeDefinitionExample dataExpected result
ValidData that should be accepted4Accepted
InvalidCorrect data type but breaks a rule, so should be rejected12, -3Rejected with error message
BoundaryValues at the limits and just outside them1 and 8 (accepted); 0 and 9 (rejected)1, 8 accepted; 0, 9 rejected
ErroneousWrong data type, should be rejected"four", 2.5, blankRejected with error message

Quick sort: what type of test data is it?

The cinema app accepts 1 to 8 tickets. Choose the type for each item.

Test plan (2.12.4.3)

A test plan is written before testing and completed during testing. Its steps are: identify the tests; describe the purpose of each; identify the test data; describe the expected results; record the actual results.

No.Purpose of testTest dataTypeExpected resultActual result
1Check a normal number of tickets is accepted4ValidAccepted, total shown
2Check upper limit is accepted8BoundaryAccepted
3Check just above upper limit is rejected9BoundaryError: 'Choose 1 to 8 tickets'
4Check text is rejectedfourErroneousError: 'Enter a whole number'
5Check blank entry is rejected(blank)ErroneousError: 'Enter a number of tickets'

★ EXAM TIP

The 'actual result' column is filled in when the test is run. If actual ≠ expected, the test has failed: record what happened, fix the code, then re-test (and regression test).

Test plan
A document listing the tests to run, their purpose, the test data, expected results and actual results.
Valid test data
Data that should be accepted and processed normally.
Invalid test data
Data of the correct type that should be rejected because it breaks a rule, e.g. age = 150.
Boundary test data
Data at the edge of what is allowed, and just outside it, e.g. 0, 1, 100, 101 for a 1–100 range.
Erroneous test data
Data of the wrong type that should be rejected, e.g. "ten" when a number is expected.
Unit testing
Testing one component (e.g. a function) on its own.
Integration testing
Testing that components work correctly together.
Regression testing
Re-running earlier tests after a change to check nothing that worked before is now broken.
Open box testing
Testing with knowledge of the code, checking every path runs correctly (also called white box).
Closed box testing
Testing inputs and outputs without looking at the code (also called black box).

Knowledge organiser

DATA TYPES

  • int: whole numbers
  • float: decimals
  • str: text (phone numbers too)
  • bool: True / False
  • input() always returns a string

VARIABLES AND SCOPE

  • Variable changes; CONSTANT doesn't
  • int() float() str() bool() convert types
  • Local: inside a function only
  • Global: whole program; needs global to change inside a function

DATA STRUCTURES

  • List: ordered, changeable, mixed types
  • Array: one data type, memory efficient
  • Dictionary: key → value lookup
  • append, insert, remove, pop, index, sort, in

OPERATORS

  • + - * / ** // %
  • // integer division, % remainder
  • == != < > <= >=
  • and, or, not
  • BIDMAS: use brackets

ACTIONS

  • Sequence, selection, iteration
  • if / elif / else; match / case
  • for = count-controlled; while = condition-controlled
  • range(start, stop, step): stop not included

SUBROUTINES AND VALIDATION

  • Function returns a value; procedure doesn't
  • Built-in, standard library, third-party, user-written
  • Checks: presence, length, range, type, format, check digit
  • Validation ≠ correct data

ROBUST CODE AND DEBUGGING

  • Handles bad input and unexpected termination
  • Specific error messages
  • try / except
  • Errors: syntax, runtime, logic
  • Trace tables, breakpoints, print statements

ALGORITHMS AND TESTING

  • Linear: any list, slow; binary: sorted list, halves each time
  • Bubble: swap pairs; insertion: insert into sorted part; merge: split then merge (extra memory)
  • Test data: valid, invalid, boundary, erroneous
  • Unit → integration → system → acceptance; regression after changes

Flashcards

Every Quick recall definition on this page. Click the card to flip it; use the arrow keys to move.

Quiz me

Random questions on CA2 from the course question bank. Pick a topic or question type, answer in your head or on paper, then check. Your score is saved on this device.

Exam-style questions

Allow about 1 hour 45 minutes. Questions get harder as you go.

State the most suitable data type for each of these: (i) the number of items in a basket; (ii) a customer's postcode; (iii) whether an order has been dispatched.

  • (i) Integer
  • (ii) String
  • (iii) Boolean

Explain why a constant should be used to store the VAT rate in a till program.

  • The value is stored once and cannot be changed by accident during the program (1)…
  • …so if the VAT rate changes, it only needs updating in one place / every calculation updates / fewer errors (1).
  • Accept: makes code easier to read because the name explains the value (1).

A program uses age = input("Enter age: ") then if age >= 18:. Explain why this produces an error and how to fix it.

  • input() returns a string, which cannot be compared with an integer using >= / causes a TypeError (1).
  • Convert it: age = int(input("Enter age: ")) (1).

State the output of each line: (a) print(17 // 5) (b) print(17 % 5) (c) print(2 ** 3 + 1) (d) print(not (5 > 3 and 2 > 4)).

  • (a) 3
  • (b) 2
  • (c) 9
  • (d) True

Describe the difference between a local variable and a global variable.

  • A local variable is declared inside a subroutine and can only be used within it / only exists while it runs (1).
  • A global variable is declared outside subroutines and can be accessed anywhere in the program (1).

Give one similarity and one difference between a function and a procedure.

  • Similarity: both are named blocks of code / both may take parameters / both can be called many times (1).
  • Difference: a function must return a value; a procedure does not (1).

A gym app stores member IDs and their membership type, e.g. M104 is "Off-peak". Explain why a dictionary is more suitable than a list for this data.

  • A dictionary stores key–value pairs, so the member ID can be the key and the membership type the value (1)…
  • …so a type can be looked up directly by ID without searching through the list / faster lookup / IDs are kept unique (1).

Describe how a binary search would find the value 31 in this list: [4, 9, 15, 22, 31, 40, 58].

  • Find the middle item: index 3 = 22 (1).
  • 31 is greater than 22, so discard 22 and everything below it, leaving [31, 40, 58] (1).
  • Middle item is 40; 31 is less, so discard 40 and above; check 31: found (1). Accept a correct alternative midpoint convention applied consistently.

Complete a trace table for this code and state the output.

total = 0
for i in range(2, 9, 3):
    total = total + i
    print(i, total)
  • i takes the values 2, 5, 8 (1)
  • total takes the values 2, 7, 15 (1)
  • Output lines: 2 2, 5 7, 8 15 (2: one mark for first two lines, one for the last)

Write a Python program that asks the user for a password and keeps asking until it is at least 8 characters long and contains at least one digit. It should print a specific error message each time and print "Password set" when a valid one is entered.

  • Gets input from the user (1)
  • Uses a condition-controlled loop that repeats until valid (1)
  • Length check using len() >= 8 (1)
  • Checks for a digit, e.g. loop with isdigit() or any() (1)
  • Specific error message for each failed rule (1)
  • Prints "Password set" only when valid (1)

Example answer:

while True:
    password = input("Enter a password: ")
    has_digit = False
    for ch in password:
        if ch.isdigit():
            has_digit = True
    if len(password) < 8:
        print("Error: password must be at least 8 characters.")
    elif not has_digit:
        print("Error: password must contain at least one digit.")
    else:
        print("Password set")
        break
Enter a password: cat
Error: password must be at least 8 characters.
Enter a password: elephants
Error: password must contain at least one digit.
Enter a password: elephant5
Password set

The code below should read a file of temperatures (one per line) and print the average. It contains three errors. Identify each error and state the correction.

f = open("temps.txt", "w")
total = 0
count = 0
for line in f.readlines():
    total = total + line.strip()
    count = count + 1
f.close()
print("Average:", total // count)
  • Line 1: file opened in write mode, which wipes it / cannot read (1). Correction: open("temps.txt", "r") (1).
  • Line 5: adding a string to a number causes a TypeError (1). Correction: float(line.strip()) (1).
  • Line 8: integer division // gives a whole number, losing accuracy (1). Correction: total / count (1).
  • Accept: no check for count > 0 before dividing, if justified, in place of one error.

A cinema's booking form accepts an age from 3 to 120. Give one item of each type of test data and the expected result: valid, boundary, invalid, erroneous.

  • Valid: e.g. 35, accepted (1)
  • Boundary: 3 or 120 accepted, or 2 or 121 rejected (1)
  • Invalid: e.g. 150 or -5, rejected with error message (1)
  • Erroneous: e.g. "ten" or blank, rejected with error message (1)
  • Expected result must be given for the mark.

Explain two characteristics of robust code, using a self-service checkout as your example.

  • Handles unexpected inputs (1), e.g. if a customer scans an item that is not in the database, it displays a message instead of freezing (1).
  • Handles unexpected terminations (1), e.g. if the card reader disconnects mid-payment, the transaction is saved and can be resumed (1).
  • Specific and meaningful error messages (1), e.g. 'Unexpected item in bagging area: please remove the last item' rather than 'Error 37' (1).

Explain the difference between integration testing and regression testing.

  • Integration testing checks that separate components work together correctly (1), e.g. data passes correctly from the basket module to the payment module (1).
  • Regression testing re-runs previous tests after a change (1) to make sure the change has not broken parts that worked before (1).

Write a function count_vowels(word) that returns the number of vowels (a, e, i, o, u) in a word, ignoring case. Show how it would be called and its result printed.

  • Function defined with a parameter (1)
  • Converts to lower case or checks both cases (1)
  • Loops through characters and counts vowels (1)
  • Returns the count, and calls/prints it (1)

Example answer:

def count_vowels(word):
    count = 0
    for letter in word.lower():
        if letter in "aeiou":
            count = count + 1
    return count

print(count_vowels("Wakefield"))
4

A logistics company keeps a list of 250,000 parcel tracking numbers. New parcels are added throughout the day and customers search for their parcel thousands of times per hour. Evaluate the use of linear search and binary search for this system, including how the data should be sorted.

Indicative content. Credit other valid points.

  • Linear search works on unsorted data, so new parcels can simply be appended with no sorting cost.
  • Linear search is slow here: worst case 250,000 comparisons, average about 125,000, repeated thousands of times per hour, so slow responses and high server load.
  • Binary search needs about 18 comparisons in the worst case for 250,000 items, so it is far faster for frequent searches.
  • Binary search requires the list to be sorted; sorting takes time, but this cost is paid once rather than on every search.
  • New parcels could be inserted into the correct position as they arrive (insertion sort is efficient for one new item into a sorted list), or added in batches and the list re-sorted with merge sort overnight.
  • Merge sort is fast on large data but needs extra memory; a server is likely to have enough.
  • Judgement: binary search on a sorted list is the better choice because searches far outnumber insertions; the extra complexity is justified.

A developer has written a working program for a café's loyalty scheme, but it uses single-letter variable names, no subroutines, no comments and the value 0.1 (the discount) typed in 14 places. Discuss the impact of these practices on the café and the developer's team.

◆ SUPPORT: SENTENCE STARTERS FOR 16 AND 17

  • Linear search would be suitable because... However, with 250,000 items...
  • Binary search needs the data to be sorted, which means...
  • When new parcels are added, the company could...
  • Overall, the best approach is ... because ...
  • Single-letter names make it harder for another developer to...
  • Typing 0.1 in 14 places means that if the discount changes...

Indicative content. Credit other valid points.

  • Single-letter names make the code hard for other developers to understand, so changes take longer and cost the café more.
  • No subroutines means repeated code; bugs must be fixed in many places, and parts cannot be tested on their own.
  • No comments make it harder to maintain if the original developer leaves.
  • The discount typed in 14 places (a 'magic number') means a change to the discount risks one copy being missed, so customers are charged inconsistently, a logic error that is hard to spot.
  • Using a constant such as LOYALTY_DISCOUNT = 0.1 would allow a single change.
  • On the other hand, the program works now, so there is no immediate impact on customers; the cost appears later when it needs updating.
  • Refactoring takes time and money in the short term, but reduces long-term maintenance cost.

▲ STRETCH

  • For question 16: estimate how many comparisons each search would need in the worst case and use the figures in your answer.
  • For question 10: extend your program so the password must also contain an upper-case letter, and write a test plan with five tests for it.

My corrections: what I need to go back over

my_notes.txt