Algorithms
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:
| word | letter | letter == 'E' | Output |
|---|---|---|---|
| BEES | |||
| B | False | B | |
| E | True | E, then Cheer! | |
| E | True | E, then Cheer! | |
| S | False | S |
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.
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.
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.
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.
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_sum | gold | judge | judge <= 3 | mark | mark > 75 | Output |
|---|---|---|---|---|---|---|
| running total of the marks entered | count of marks above 75 | counts the rounds, 1 to 3 | True or False | value typed in | True or False | text 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.
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.
For example, once the variable skip holds 4 and limit holds 6, testing whether skip is less than limit records True in that row.
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
2The 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.
| reply | credits | turns | reply == '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.
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.
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.