A-Level Revision Guides
All subjects covered
Amazon amazon.co.uk
Fastmail -- Private Email
Privacy-first email with no ads and no tracking
fastmail.com
Dynadot -- Domain Registration ->
Register or transfer domains with free SSL and affordable pricing
dynadot.com
Zen Internet -- UK Broadband ->
Award-winning UK broadband with no data caps and great customer service
zen.co.uk
A-Level Revision Aid: This resource is designed to support your revision. Content may contain errors. If you find a discrepancy with your class teaching, your teacher is correct — please let us know at alevelrevise@scott.scottrix.co.uk.

Fundamentals of Programming

Year 1 / ASYear 2 / A-Level AQA, OCR, WJEC/Eduqas

Exam-focused AQA 7517, OCR H446 and WJEC/Eduqas revision for programming fundamentals: data types, control flow, subroutines, parameter passing, recursion and exception handling with step-by-step code traces.

Fastmail

🎯 Learning Objectives

📋 Key Definitions and Core Concepts

Variable: A named memory location whose value can change during program execution.
Constant: A named value fixed at definition time that cannot be reassigned; prevents accidental modification and aids readability.
Type casting: Explicit conversion of a value from one data type to another, e.g. int('42') or str(3.5).
Integer division (DIV): Division that discards the fractional part; 17 DIV 5 = 3. In Python: 17 // 5.
Modulus (MOD): The remainder after integer division; 17 MOD 5 = 2. Used for parity tests, digit extraction and cyclical indexing.
Parameter by value: A copy of the actual argument is passed; changes to the formal parameter inside the subroutine do not affect the caller's variable.
Parameter by reference: A reference (address) to the caller's variable is passed; changes inside the subroutine persist after return.
Scope: The region of a program in which an identifier is visible. Local variables exist only within their subroutine; globals exist throughout.
Exception: A run-time error condition (e.g. division by zero, invalid file) raised during execution; uncaught exceptions terminate the program.
Base case: The terminating condition of a recursive subroutine that returns without further calls; without it the call stack overflows.

📌 Key Points

Data types: int, real/float, bool, char, string; casting with int(), str(), float(); constants vs variables (AQA 4.1.1/4.1.6)
Selection: if/elif/else and switch/case; iteration: for (count-controlled), while (condition-controlled), do-while (post-tested)
Subroutines: functions return a value, procedures do not; parameters by value copy, by reference alias (OCR 2.2.1)
Integer division and modulus: 17 DIV 5 = 3, 17 MOD 5 = 2; n MOD 2 == 0 tests evenness
Exceptions: try/except/else/finally; validate input at the boundary, never trust user data
File modes: read, write (overwrite), append; close files or use a with-block so the file is released even on error
Recursion needs a reachable base case; each call pushes a new stack frame, so depth is limited by stack size

Data types, variables, constants and operators

Every exam board expects you to choose and justify a data type, not just name it. The core set is integer (whole numbers), real/float (numbers with a fractional part), Boolean (True/False), character (a single symbol) and string (a sequence of characters). AQA 4.1.1 adds date/time and records; OCR 2.2.1 expects you to know that a string is stored as a sequence of character codes.

Marks are commonly lost by justifying types with tautologies ('an integer is an integer'). Give a consequence-based justification: a price stored as an integer loses pence in arithmetic; a Boolean flag makes a condition readable (isValid rather than status == 1); a constant for VAT rate means one change updates the whole program and prevents accidental reassignment.

OperationPseudocodePythonExample
Integer division17 DIV 517 // 53
Modulus (remainder)17 MOD 517 % 52
Exponent2 ^ 102 ** 101024
CastingstringToInt('42')int('42')42

DIV and MOD are heavily examined (AQA 4.1.3). Three standard idioms to memorise:

Rounding is a separate operation from casting: int(3.9) truncates to 3, whereas round(3.9) gives 4. Exams reward stating which one an algorithm uses. Also remember operator precedence: in most languages MOD and DIV bind like multiplication, so 10 + 3 MOD 4 evaluates as 10 + (3 MOD 4) = 13, not (10 + 3) MOD 4.

Selection and iteration

Selection chooses between branches; iteration repeats. For revision, the marks live in the differences between constructs, because 'state one difference' questions are near-guaranteed (AQA 4.1.2, OCR 2.2.1, WJEC Unit 2.1).

The classic written question is: 'Explain the difference between a while loop and a do-while loop.' Model phrasing: a while loop tests its condition before executing the body and so may execute it zero times, whereas a do-while/repeat-until loop tests after the body and therefore always executes at least once; choose do-when the loop must run at least once (e.g. reading a menu choice).

The classic trace trap is a sentinel-controlled loop where the loop condition is accidentally inverted or the sentinel is included in processing. Practice with this pattern:

total = 0
num = inputInt()
while num != -1:
    total = total + num
    num = inputInt()
print(total)

Dry run with inputs 4, 9, -1: pass 1 — num=4, not -1, total=4, read 9; pass 2 — num=9, total=13, read -1; pass 3 — condition fails, loop exits, output 13. The -1 is never added. A frequent error in candidates' answers is stopping the trace one iteration early and forgetting the final read that terminates the loop.

Nested selection inside iteration compounds trace difficulty. Keep a dry-run table with one column per variable and update it every time a value changes — examiners award method marks for a correct table even if the final answer is wrong. Also know break (leave the loop immediately) and continue (skip to the next iteration): OCR paper 2 has asked candidates to rewrite a loop that uses break as a condition-controlled loop without it.

Subroutines, parameter passing, scope and recursion

A function returns exactly one value and is used inside an expression; a procedure performs an action and returns nothing (it may still change things through reference parameters or output). Benefits of subroutines — a 4-marker across all boards: code is written once and reused (maintainability), a large problem is decomposed into named subproblems (decomposition), each subroutine can be tested independently (unit testing), and local variables prevent accidental interference between parts of the program.

Parameter passing is the highest-frequency written topic in this section (OCR 2.2.1, AQA 4.1.2). By value, the actual argument's value is copied into the formal parameter, so assignment inside the subroutine is invisible to the caller. By reference, the parameter is an alias for the caller's variable, so changes persist. Trace both versions:

// version A — by value
procedure doubleA(x)
    x = x * 2
n = 5
doubleA(n)
print(n)        // outputs 5

// version B — by reference
procedure doubleB(byref x)
    x = x * 2
n = 5
doubleB(n)
print(n)        // outputs 10

Step-by-step for version A: (1) n is created holding 5; (2) doubleA is called, the value 5 is copied into local parameter x; (3) x becomes 10 — this changes only the copy; (4) subroutine ends, x is destroyed; (5) n still holds 5. For version B the only difference is step 2–3: x is n, so writing 10 through x writes through to n. Practical rules worth quoting in essays: pass small scalars by value when the subroutine must not alter them; pass large structures (arrays, records) by reference to avoid copying costs — but then the subroutine can modify them, which is a documented side effect.

Scope: a variable declared inside a subroutine is local and destroyed on return; a global is visible everywhere. Two scope traps: (1) shadowing — a local parameter with the same name as a global hides the global inside that subroutine; (2) in Python, assigning to a global inside a function without a global declaration creates a new local instead. Exams ask you to argue why globals are poor style: any subroutine can change them, so the data flow of the program is not visible in the call structure, and debugging is harder.

Recursion (AQA 4.1.2, OCR 2.2.1): a subroutine that calls itself. It must have a base case (terminating condition) and a recursive case that moves towards it. Trace factorial(4) showing the stack:

function fact(n)
    if n == 0 then
        return 1
    else
        return n * fact(n - 1)

Winding: fact(4) calls fact(3) calls fact(2) calls fact(1) calls fact(0). At depth 5 the base case fires and returns 1. Unwinding: fact(0)=1, so fact(1)=1*1=1, fact(2)=2*1=2, fact(3)=3*2=6, fact(4)=4*6=24. Each call pushes a new stack frame holding its own n, which is why unbounded recursion causes a stack overflow — the classic exam link between recursion and the call stack. Any recursive routine can also be written iteratively (using a loop and an explicit accumulator); iterative versions avoid stack-depth limits and are usually faster, but recursive versions often mirror the problem definition more clearly.

Exception handling, validation and file I/O

Validation and exception handling are different defences and exams test that distinction (OCR 2.2.1; WJEC Unit 2.1). Validation checks that input is reasonable and in the right format before processing: range check (0 <= mark <= 100), length check, format/pattern check, type check, presence check. Exception handling deals with errors that validation cannot prevent — a file being missing, a network dropping, division by a value that turned out to be zero.

A typical full-credit Python pattern:

def read_mark():
    while True:
        try:
            mark = int(input('Enter mark (0-100): '))
            if 0 <= mark <= 100:
                return mark
            print('Out of range - try again')
        except ValueError:
            print('Not a whole number - try again')
        finally:
            pass  # runs after every attempt, success or failure

Walking through the blocks: the try block wraps code that may raise; except ValueError catches the specific exception when the cast fails; a general except catches everything else but should be avoided because it hides real bugs; else (not shown) runs only when no exception occurred; finally runs regardless — its exam purpose is cleanup such as closing files or connections. The with open(...) construct is the idiomatic cleanup for files: the file is closed automatically even if an exception occurs mid-read, which is the exact point to make for a 'why use with?' question.

File I/O modes: read (r) — file must exist; write (w) — creates a new file or truncates an existing one to empty; append (a) — writes after existing content. The write-truncates behaviour is a favourite one-marker: opening an existing data file in write mode and saving it erases the original data. Text files are read as strings, so numeric data must be cast after reading (int(line)) and cast to string before writing (str(total)) — forgetting the outbound cast is a common trace-error. CSV files split each line on a delimiter:

with open('scores.csv') as f:
    for line in f:
        parts = line.strip().split(',')
        name = parts[0]
        score = int(parts[1])

Exam question pattern: 'A program must read a file that may not exist. Describe how the program should respond.' Full-credit answer: attempt the open inside a try block; catch the file-not-found exception; on failure print an error message and either terminate gracefully or fall back to an empty/default structure — the program must not crash with an unhandled exception or silently continue with no data.

Dry-run technique: tracing programs under exam conditions

Every Paper 1/2 includes a trace worth 4–9 marks. The method that protects your marks:

Worked trace — identify what this prints (AQA-style pseudo-Python):

nums = [4, 7, 2, 9]
total = 0
count = 0
for i in range(len(nums)):
    if nums[i] > total:
        total = total + nums[i]
        count = count + 1
print(total, count)

The trap: the comparison is against the running total, not a fixed value. Trace table:

inums[i]nums[i] > total?totalcount
044 > 0 — true41
177 > 4 — true112
222 > 11 — false112
399 > 11 — false112

Output: 11 2. The algorithm keeps a running 'record so far' — it sums only values bigger than everything summed before them. If you traced against a fixed value such as nums[0] you would get 13 2 and lose the answer mark, though the table still earns method marks.

For 'state the output' questions on string manipulation, remember slicing is start-inclusive, end-exclusive ('revision'[0:3] is 'rev'), negative indices count from the end, and len, split, join, replace are the usual toolset. For 'write an algorithm' questions (OCR 2.2/2.3, AQA 4.1): declare a clearly-named subroutine, handle the edge case first (empty input, empty file), use a for-loop over indices when you need position and a for-each when you do not, and return rather than print inside a function — examiners penalise side-effecting functions. Finally, match the board's pseudocode conventions on the day: AQA exam pseudocode commonly indexes arrays from 1 in trace questions while Python code you write is 0-indexed; state your assumption if the paper does not specify.

💡 Worked Example

Exam-style: The procedure mystery is defined in pseudocode below. procedure mystery(n) x = 0 while n > 0 x = x + n MOD 10 n = n DIV 10 endwhile return x endprocedure (a) Trace mystery(9021), showing the values of x and n after each iteration of the loop. [4 marks] (b) State, with justification, the purpose of the procedure. [2 marks]
Mark-scheme logic: (a) Trace table (1 mark per correct iteration pair, 4 marks total): Start: x = 0, n = 9021. Iteration 1: x = 0 + 9021 MOD 10 = 0 + 1 = 1; n = 9021 DIV 10 = 902. Iteration 2: x = 1 + 902 MOD 10 = 1 + 2 = 3; n = 90. Iteration 3: x = 3 + 90 MOD 10 = 3 + 0 = 3; n = 9. Iteration 4: x = 3 + 9 MOD 10 = 3 + 9 = 12; n = 0. Loop condition n > 0 now fails; return 12. (b) The procedure returns the sum of the digits of n (1 mark). Justification: MOD 10 isolates the least significant digit and DIV 10 removes it, so the loop accumulates each digit in turn; for 9021 the digits 9+0+2+1 = 12 (1 mark).

❓ Practice Questions & Mark Schemes

Explain the difference between passing a parameter by value and passing a parameter by reference, and state one situation where passing by reference is preferable. [4 marks]
Answer: By value, a copy of the actual argument is passed into the subroutine, so assignments to the formal parameter do not affect the caller's variable (1). By reference, the parameter is a reference/alias to the caller's variable, so changes made inside the subroutine persist after it returns (1). By reference is preferable when the subroutine must return more than one value through its parameters (1) or when the argument is a large data structure such as an array that would be expensive to copy (1).
Trace the following code and state the final output: total = 0 num = inputInt() while num != 0 total = total + num num = inputInt() endwhile print(total) The inputs are 5, 12, 8, 0. [4 marks]
Answer: Trace: read 5 → 5 != 0 so total = 5, read 12 → total = 17, read 8 → total = 25, read 0 → condition num != 0 is false so the loop exits (3 marks for a fully correct table). Output: 25 (1). The sentinel value 0 is read but never added; candidates who add it get 25 with an extra 0 or stop one read early and lose the final-iteration mark.
Write a function isPrime(n) that returns True if the integer n is prime and False otherwise, using a loop and the modulus operator. State one edge case your function must handle. [6 marks]
Answer: function isPrime(n) if n < 2 then return False // edge case: 0, 1 (and negatives) are not prime for i = 2 to n DIV 2 if n MOD i == 0 then return False next i return True endfunction Award: loop from 2 upwards (1); modulus remainder test n MOD i == 0 (1); return False on the first divisor (1); return True after the loop completes (1); guard for n < 2 (1); any valid edge case stated — n = 0, 1, negative numbers, or n = 2 must return True because the loop body never runs (1).
A program reads integers from the file marks.txt and calculates their mean. The file may be missing or contain non-numeric lines. Describe how the program should use exception handling to respond robustly. [6 marks]
Answer: Open and read the file inside a try block (1). Catch the file-not-found exception: print an error message and terminate gracefully or return a sensible default rather than crashing (1). Cast each line inside the try block and catch the value/conversion exception: skip that line (or report it) and continue with the remaining data (1). Use finally, or a with-block, so the file handle is closed whether or not an exception occurred (1). Check for division by zero before computing the mean: if the count of valid values is 0 the mean is undefined, so output an error instead of dividing (1). Points for robustness: the program never terminates with an unhandled exception and never silently produces a wrong answer (1).
Show, using integer division and modulus, how to extract the hundreds digit of a four-digit number n stored as an integer. Illustrate with n = 4729. [3 marks]
Answer: hundreds = (n DIV 100) MOD 10 (1). Working for 4729: 4729 DIV 100 = 47 (1); 47 MOD 10 = 7, which is the hundreds digit (1). Alternative full-credit method: strip the last two digits with n DIV 100, then take the remainder on division by 10 — the order DIV-then-MOD (not MOD-then-DIV) is what makes it the hundreds digit.
Rewrite the following post-tested loop as a pre-tested loop that behaves identically for all inputs: repeat ch = inputChar() until ch == 'y' or ch == 'n'
Answer: ch = inputChar() while not (ch == 'y' or ch == 'n') ch = inputChar() endwhile The key marking point: because a repeat-until body always runs at least once, an equivalent while loop must perform the first read before the loop (1), then loop while the input is invalid (1), re-reading inside the body (1). A version that reads only inside the loop would test an undefined ch before the first read and is not equivalent.

🎬 Video Resources

📄 Past Papers & Exam Resources

🔗 Further Reading & Resources

🧠 Flashcards (Spaced Repetition)

📝 Exam Questions by Topic

🎯 Target Tests (Auto-Graded)

🎓 Smart Lesson (Guided)