Pseudocode in the exam languages

OCR's exam reference language and AQA's pseudo-code side by side with Python, the traps in translating, and a stack class that brings the robot home.

A15.4Exam preparationA level45 min

Covers OCR H446 2.2.1 Programming techniques · AQA 7517 4.4.1.2 Following and writing algorithms · Eduqas A500QS 1.8 Program construction

Do this lesson in the simulator

Exams cannot assume you know Python, so they give code in a pseudocode that every candidate can read, and accept answers in pseudocode or a real language. OCR has its exam reference language; AQA has its pseudo-code. You met both through the course. This lesson puts them side by side, points out where translating goes wrong, and practises the question that turns one into working code.

The two languages side by side

Construct OCR exam reference language AQA pseudo-code Python
Assignment x = 3 x ← 3 x = 3
Equal, not equal ==, != =, ≠ ==, !=
Integer division, remainder DIV, MOD DIV, MOD //, %
Output, input print(x), x = input("") OUTPUT x, x ← USERINPUT print(x), x = input()
Selection if … then … elseif … else … endif IF … THEN … ELSE … ENDIF if … elif … else
Count-controlled loop for i = 0 to 9 … next i FOR i ← 0 TO 9 … ENDFOR for i in range(0, 10)
Condition at the start while … endwhile WHILE … ENDWHILE while …:
Condition at the end do … until … REPEAT … UNTIL … while True: … if …: break
Subroutines function … endfunction, procedure … endprocedure SUBROUTINE … ENDSUBROUTINE def
Array array route[10], route[0] route ← [0, 0, 0], route[0] route = [0] * 10, route[0]
Length route.length LEN(route) len(route)
Class class … endclass, constructor new class, constructor __init__

The traps in translating

  1. Inclusive loops. for i = 0 to 9 and FOR i ← 0 TO 9 include 9, so they run ten times. The Python is range(0, 10). This is the commonest translation error.
  2. Post-condition loops. do … until and REPEAT … UNTIL run the body at least once and stop when the condition becomes true. A Python while checks first and continues while the condition is true, so the condition is reversed and the body must run once regardless.
  3. Assignment and comparison. AQA's = compares; its ← assigns. OCR's = assigns; its == compares.
  4. DIV with negatives. Python's // rounds down, so -7 // 2 is -4. Exam questions avoid relying on this, but do not assume it.
  5. Fixed-size arrays. Pseudocode arrays usually have a declared size and an index you manage yourself, such as a top pointer. A Python list grows with append. Either translation is accepted if it behaves the same, but a question that asks you to complete the pseudocode wants the pointer.
  6. Parameters by reference. OCR marks :byRef. Python cannot pass a number by reference, so return the new value instead (lesson A1.4).
Which values of i each loop visits: the exam loops to 9 include 9, and Python's range stops before its end012345678910for i = 0 to 9OCR: includes 9, ten timesFOR i ← 0 TO 9AQA: includes 9, ten timesrange(0, 10)Python: stops before 10, ten timesrange(0, 9)the slip: nine times, 9 is missed
Filled dots are the values i takes. The exam languages' 0 to 9 includes 9, so the Python translation needs range(0, 10). Writing range(0, 9) runs one time too few, and the ringed 9 is never visited.

A post-condition loop, both ways:

do
    reading = distance()
until reading < 30
readings = iter([55, 42, 31, 29, 18])    # stands in for distance() so this cell runs anywhere

while True:
    reading = next(readings)
    print("read", reading)
    if reading < 30:                     # until: stop when the condition is true
        break

Run this in the simulator

Two flowcharts: do until runs the body and then tests, stopping when the test is true; while tests first and runs the body while it is truedo … untilreading = distance()reading < 30true yet?yesstopnobody runs at least oncewhile …conditiontrue?yesbodynostopbody may never run
The test sits in a different place. do … until runs the body before it tests, and leaves when the test is true. A while loop tests first and keeps going while its test is true, so the Python has to run the body once and reverse the condition.

Reading a class in the exam reference language

OCR questions often give a class and ask you to complete a method or use it. This stack keeps its items in a fixed-size array with a pointer to the top:

class Stack
    private items
    private top

    public procedure new()
        array items[20]
        top = -1
    endprocedure

    public procedure push(item)
        top = top + 1
        items[top] = item
    endprocedure

    public function pop()
        if top == -1 then
            return ""          // nothing to pop
        endif
        item = items[top]
        top = top - 1
        return item
    endfunction

    public function isEmpty()
        return top == -1
    endfunction
endclass

Translate it one method at a time, keeping its structure. new becomes __init__; private attributes become names with two underscores; isEmpty can keep its name or follow Python's style as is_empty. The array and pointer can stay, or become a list with append and pop: both behave as a stack, last in, first out (lesson A3.2).

The Stack's array of 20 cells and its top pointer: empty with top = -1, after four pushes with top = 3, and after a pop with top = 20123419new()…top = -1four pushesforward 30right 20forward 15left 10…top = 3pop()returns left 10forward 30right 20forward 15left 10…top = 2still there, but above top
top always points at the last item pushed, and -1 means empty. A pop reads the item at top and moves top down; the old value stays in its cell, but the next push will write over it.

Writing pseudocode yourself, examiners do not deduct marks for small differences in syntax, as long as the logic is clear and unambiguous. They do deduct for logic that does not work: a loop that never ends, a variable used before it is given a value, a return missing on one path.

Task: there and back with a stack

Translate the Stack class above into Python, then use it to bring the robot home.

Write class Stack with:

  • __init__(self): an empty stack;
  • push(self, item): puts item on the top;
  • pop(self): removes and returns the top item;
  • is_empty(self): returns True if there are no items, otherwise False.

route is a list of moves in order. Each move is a tuple (direction, cm): direction is one of "forward", "backward", "left" or "right", and cm is a whole number of centimetres. Drive each move in order at speed 50, pushing it onto a stack after it is driven. The robot then reaches the charger: play a note and print arrived.

To come home, loop while not <stack>.is_empty(): pop a move, print undo <direction> <cm>, and drive the opposite direction (forward and backward are opposites, as are left and right) the same distance at speed 50. After the loop print home. Do not reverse the list yourself: the stack must do it.

# the two lines every program starts with: the commands, then the robot
from bugbot import *
connect()

route = [("forward", 30), ("right", 20), ("forward", 15), ("left", 10)]

Challenges

  1. Translate pop exactly as the pseudocode has it, with an array of 20 and a top pointer, and check the robot still comes home.
  2. Write push in AQA pseudo-code as a subroutine that takes the array, the pointer and the item, and returns the new pointer.
  3. The pseudocode's push does not check whether the array is full. Add the check in pseudocode, and say what should happen.