Trace tables

Following an algorithm line by line, and tracing to find a logic error.

F5.4AlgorithmsGCSE15 min

Covers OCR J277 2.1.2 Designing, creating and refining algorithms · AQA 8525 3.1.1 Representing algorithms · Edexcel 1CP2 1.2.4 The output of an algorithm

Do this lesson in the simulator

A program that runs without an error can still be wrong. To find out what an algorithm really does, programmers trace it: follow it line by line, by hand, writing down the value of every variable each time it changes. A trace table is where you write it down. It is how you check an algorithm before trusting it, and how exams test whether you understand one.

A first trace

total = 0
for i in range(1, 5):
    total = total + i * 2
print(total)

One column per variable, plus a column for output. A new row every time something changes:

i total output
0
1 2
2 6
3 12
4 20
20

Work through it yourself on paper first, then run the program to check:

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

total = 0
for i in range(1, 5):
    total = total + i * 2
print(total)

Run this in the simulator

Let the program trace itself

Adding a print inside the loop makes the program write its own trace table. This is exactly how programmers debug:

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

x = 1
y = 10
print("x", "y")
while x < y:
    x = x * 2
    y = y - 1
    print(x, y)
print("finished with x =", x)

Run this in the simulator

Before you run it, trace it on paper. When does the loop stop, and why? Then run it and compare row by row. The first row where your table and the program disagree is where your understanding and the algorithm part company.

The Debug button does the same job on screen: it stops at each line and shows the variables as they change.

You do not even need the print. trace() fills in the table for you: name the variables, in quotes, and it writes a new row every time one of them changes, with the number of the line that changed it. Here it is on the program at the top of the page:

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

# watch i and total: a new row every time one of them changes
trace("i", "total")
total = 0
for i in range(1, 5):
    total = total + i * 2
print(total)

Run this in the simulator

Line 8 is the for line, where i changes, and line 9 is where total changes, so each time round the loop takes two rows. The table at the top of the page puts both on one row. The values are the same and in the same order, and either layout earns the marks when it matches the table the question gives you. Use trace() to check your own tables, after you have done them by hand.

The rows trace() writes for the first program: line 7 sets total, then lines 8 and 9 take a row each time round, and each pair makes one row of the hand tabletrace() writesthe hand tablelineitotal70819282968391284920itotal01226312420the startone time round
The same values in the same order. trace() gives the for line (8) and the line that adds to total (9) a row each, so each time round is two rows. The hand table at the top of the page puts each pair on one row.

Tracing to find a bug

This program should give the average of five distance readings, 40, 35, 30, 25 and 20, which is 30. It prints something else:

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

readings = [40, 35, 30, 25, 20]
for i in range(len(readings)):
    total = 0
    total = total + readings[i]
print("average:", total / len(readings))

Run this in the simulator

It prints average: 4.0. No error message, so this is a logic error. A trace shows it straight away:

i readings[i] total
0 40 40
1 35 35
2 30 30

total never grows. It goes back to 0 every time round, because total = 0 is inside the loop. By the end, total holds only the last reading, 20, and 20 divided by 5 is 4.0.

The value of total after each line of the buggy loop: it goes back to 0 every time round, so it never grows02040total4035302520i = 0i = 1i = 2i = 3i = 4back to 0ends at 20: 20 / 5 = 4.0
Each time round, total = 0 wipes out what was there, then one reading is added. The red drops are the bug: the total never builds up, and the last reading is all that is left at the end.

Tracing a robot

The robot's position can go in a trace table too. Predict where this program leaves the robot, then run it:

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

side = 10
for i in range(3):
    forward(60, distance=side)
    right(60, distance=side)
    side = side + 5
print("at", position())

Run this in the simulator

i side before the drives moved up moved right
0 10 10 10
1 15 15 15
2 20 20 20

So it should end 45 cm up and 45 cm right. The robot's own report will be close but not exact, because a real (or simulated) robot drifts a little.

The robot's path: up 10 and right 10, up 15 and right 15, up 20 and right 20, ending 45 cm up and 45 cm right101015152020startend: 45 right, 45 up
Each time round the robot goes up by side, then right by side, and side grows by 5, so the steps get bigger. Adding the rows of the table gives 10 + 15 + 20 = 45 each way.

Task: trace and fix

Fix the average program so it prints average: 30.0. Keep a trace: inside the loop, print a line i=<i> total=<total> each time round, so the program shows its own trace table.

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

readings = [40, 35, 30, 25, 20]
for i in range(len(readings)):
    total = 0
    total = total + readings[i]
print("average:", total / len(readings))

Challenges

  1. Trace n = 27 then while n != 1: if n is even, n = n // 2, else n = 3 * n + 1 for the first six rows. Then run it to see how long it really takes.
  2. Write a trace table for the parking sensor's loop, with the distance, the gap and the beep count.
  3. Swap the two lines inside the x and y loop above. Trace it again before running. Does it still stop?

Past paper questions on this

Real exam questions that test this, each worked through with a program you can run.