Menu

Algorithms

Trace Tables

Contents

  1. Trace Tables
  2. Trace Table Columns
  3. Completing a Trace Table
  4. Output in Trace Tables

A dry run means following an algorithm by hand, step by step, without running it on a computer, keeping track of the value held in every variable. A trace table records the dry run: each row shows the values reached at one step, so you can see exactly how the algorithm behaves.

Trace tables show what an algorithm does, what it outputs for given inputs, how many times a loop repeats, and where a logic error sits — a mistake in the algorithm's reasoning, which appears as a value you did not expect. They cannot help with syntax errors, because a program with one of those never runs. Follow the actual lines in order and write down what really happens, not what the program is meant to do.

word = input("Enter a word: ")
for letter in word:
    print(letter)
    if letter == "E":
        print("Cheer!")

Output when the user types BEES:

Enter a word: BEES
B
E
Cheer!
E
Cheer!
S

Here the input BEES arrives in word, and each pass of the loop adds a row showing the letter and the result of the test:

wordletterletter == 'E'Output
BEES
BFalseB
ETrueE, then Cheer!
ETrueE, then Cheer!
SFalseS

The loop repeats four times, once per letter, yet six lines are printed, because each true test prints a second line. The number of iterations and the number of output lines are not the same thing.

What a trace can reveal

  • Sequence, selection and iteration each appear as rows you work through in order, with a condition column recording each test as True or False.
  • Arithmetic with % (remainder) and // (integer division) is worked out fresh on every pass, not just once at the end.
  • A row holding a value you did not expect points at the line responsible; after you change that line, trace again to check the fix.

A trace table is only as useful as the columns you give it, so decide on the columns before you start filling in any values. Get them right and the table stays readable and records everything that matters.

What deserves a column

  • Variable columns — one for each variable that matters: a variable whose value changes, is tested in a condition, or is printed.
  • An output column — needed whenever the algorithm prints something, because the printed values are usually what you are asked for.
  • A condition column — worth adding when the same loop or selection condition is tested again and again, so you can record True or False each time it is checked.
  • A line number column — worth adding when the algorithm is long, or when the same variable is changed in several different places and you need to show which line did it.

Include only what the algorithm needs. A value that never changes, such as a fixed price used in a calculation, does not need its own column, and neither does a variable that is never changed, tested or printed. Extra columns add no information and make the table harder to read.

Order and labels

Label each column clearly with the variable name, or a short description of the test such as mark > 75, rather than a vague heading. Set the columns out in a clear order — often the order the variables appear in the algorithm — so a row can be read left to right and the values followed easily. Putting the output column at the end, after everything that feeds into it, is a sensible choice.

Choosing columns for a program

gold = 0
marks_sum = 0
judge = 1
while judge <= 3:
    mark = int(input("Mark: "))
    marks_sum = marks_sum + mark
    if mark > 75:
        gold = gold + 1
    judge = judge + 1
print("Total marks", marks_sum)
print("Gold awards", gold)

Output when the user types 82, 60, 91:

Mark: 82
Mark: 60
Mark: 91
Total marks 233
Gold awards 2

Three variables need tracking: marks_sum keeps a running total, gold keeps a count and judge counts the rounds, so each needs a column, and the two print lines mean you also need an output column. The mark typed in is used in the total and in the test mark > 75, so it earns a column too. The loop test judge <= 3 is checked before every pass of the loop, and mark > 75 is checked inside each pass, so both conditions are worth a column:

marks_sumgoldjudgejudge <= 3markmark > 75Output
running total of the marks enteredcount of marks above 75counts the rounds, 1 to 3True or Falsevalue typed inTrue or Falsetext printed to the screen

No line number column is needed here, because each variable is changed in only one place, so there is nothing to confuse. A long algorithm that added to marks_sum in three different places would be a different matter.

Completing a trace table means carrying on the record of an algorithm's run from the values already written down, filling in the rest one line at a time. Done carefully, it tells you exactly what the algorithm outputs and where a logic error hides.

Begin at the beginning

Every variable set before the first loop or selection gets its own row, in the order the algorithm sets it. If the table has a line-number column, a line that only assigns a value still gets a row to itself, so the order of events stays clear.

A partly filled table is always continued, never restarted. If the last completed row shows 3 in the turns column and 12 in the credits column, the next row you write works from those two values.

One line at a time

  • Take the lines in order and never skip one, even when the result looks obvious.
  • Write a variable's new value in the row where that line changes it, so every change is visible.
  • When a line asks for input, put the value you were given straight into the variable that receives it, then carry on from the next line.
  • When a condition is tested, use the values showing at that moment and write True or False in the condition column.

For example, once the variable skip holds 4 and limit holds 6, testing whether skip is less than limit records True in that row.

Worked continuation

A fairground ride uses 5 credits a go, and the programmer wants to count how many goes were taken.

credits = 15
turns = 0
reply = input('Go again? ')
while reply == 'yes':
    credits = credits - 5
    turns = turns + 1
    reply = input('Go again? ')
print(turns)

Output when the user types yes, yes, no:

Go again? yes
Go again? yes
Go again? no
2

The first six rows below were supplied, ending with 10 in the credits column and 1 in the turns column. The second yes was typed next, so carrying on from those values finishes the table.

replycreditsturnsreply == 'yes'output
15
0
yes
True
10
1
yes
True
5
2
no
False
2

An output column records what an algorithm actually displays on screen. Each time a line prints something, you write the result in the output column of the row where that print happens — going down the table in the same order the algorithm produces it.

Copy the screen exactly

Write the output as it would look on screen, not as code. Quotation marks around string literals are not printed, so print('Goals scored') has the output column entry Goals scored — no quotes.

Spacing matters too. A comma inside print() adds a single space between the items, so with points holding 4, print('Goals scored:', points) shows Goals scored: 4. If you join strings with +, nothing is added, so 'Goals scored:' + str(points) shows Goals scored:4 all squashed together. Both are correct for their own line, so check which method the code uses before you write anything down.

for temp in [16, 21, 27, 30]:
    if temp > 24:
        print('Hot day:', temp, 'degrees')

Output:

Hot day: 27 degrees
Hot day: 30 degrees

Four values go round the loop, but only two of them pass the test and reach a print(), so the output column receives just two entries — written on the rows where the printing actually happened, not squeezed onto the first two rows. The values 16 and 21 were checked and rejected, so they never appear in the output column at all. The commas matter here too: print('Hot day:', temp, 'degrees') puts a space after the colon, giving Hot day: 27 degrees.

Only what is printed

It is tempting to fill the output column with the last value of every variable. Only values that reach a print() belong there. A variable that is calculated, tested or updated but never printed stays in its own column and nowhere else.

Worked example: an algorithm sets cost = 12, then cost = cost * 3, then tests if cost > 30 and prints Over budget. The output column gets one entry, Over budget, on the row where the condition is true. The value 36 stays in the cost column — even though the condition compares cost with 30, that 30 is never displayed. If the condition were false and nothing was printed, the output column would simply be left blank.

Also useful