Build programs from sequence, selection and iteration in Python and Java, trace loops and nested loops, avoid infinite loops and deadlock, and split code into functions and modules with parameters, return values and local scope.
Each is in the Computer Science glossary, with every other term in the subject.
A variable that builds up a result, such as a running total or product, by being updated with each value processed inside a loop.
A value or expression supplied in a subprogram call, which is copied into the matching parameter.
A statement that ends the innermost loop immediately and continues with the first statement after the loop; the related continue statement skips the rest of the current pass and starts the next one.
A Boolean expression, evaluated while the program runs, whose true or false result controls a selection or a loop.
A loop that repeats its body for as long as a condition remains true (or until it becomes true), so the number of repetitions is not known when the loop starts.
A loop that repeats its body a number of times fixed before the loop starts, using a loop variable that steps through a range of values.
A variable that counts how many times something happens, usually starting at 0 and increased by 1 each time the event occurs.
A selection structure that tests a series of conditions in order and runs only the block belonging to the first condition that is true, with an optional final else block for when none is true.
Construct programs whose instructions run in the correct order, and explain how changing the order changes what a program does.
Explain how to avoid infinite loops, deadlock and incorrect output when designing a program.
Construct selection structures with if, else, else if (Java) and elif (Python), using relational and Boolean operators in their conditions.
Construct counted and conditional loops, and justify which type suits a given task.
Construct loops whose conditions combine relational and Boolean operators, including sentinel loops, validation loops and loops controlled by a flag.
Trace programs that contain selection, loops and nested loops with a trace table.
Construct functions (Python) and methods (Java) with parameters and return values, and explain the difference between local and global scope.
Explain the benefits of modularisation and apply it to split a program into reusable subprograms and modules.
Every program, from a calculator app to the software that runs a power grid, is built from three control structures: sequence (instructions run one after another), selection (a condition chooses which instructions run) and iteration (instructions repeat). Wrapping these structures into named, reusable subprograms and grouping the subprograms into modules lets a program grow to millions of lines and still be read, tested and changed by a team.
Small mistakes in these structures cause large failures. A single repeated line after an if statement switched off part of the certificate checking on iPhones, iPads and Macs in 2014, and a loop that could not end froze a whole model of music player on the last day of 2008. Understanding exactly how each construct runs is what lets a programmer predict a program's behaviour before running it, and find the fault when the behaviour is wrong. The Crash Course video on programming basics introduces statements, selection, loops and functions together, as a first view of the whole subtopic.
183 exam-style questions on this subtopic, written in the style of the IB papers. The first has its markscheme open. Counted on
A music streaming service checks whether a playlist contains the same song twice. Each song is identified by an integer ID, and a playlist is a list (Python) or array (Java) of IDs called ids.
def has_duplicate(ids):
n = len(ids)
for i in range(n - 1):
for j in range(i + 1, n):
if ids[i] == ids[j]:
return True
return Falsepublic static boolean hasDuplicate(int[] ids) {
int n ids.length;
( ; i < n - ; i++) {
( i + ; j < n; j++) {
(ids[i] == ids[j]) {
;
}
}
}
;
}One of 60 short multiple-choice questions on B2.3. Pick an answer to see why it's right or wrong.
Which values does take in the Python loop ?
The official deck for this part of the syllabus.
State the three control structures from which every program is built.
What is meant by the flow of control of a program?
With a free account, Augment remembers where you stopped and what you have practiced.
A Boolean variable that records whether an event has happened, set to an initial value before a loop and changed when the event occurs, so later code can test it.
A loop whose terminating condition is never met, so it repeats without end until the program is stopped from outside.
The control structure in which a block of instructions is repeated, either a set number of times or while a condition remains true.
A collection of pre-written, tested modules that programs can import to use their subprograms instead of writing the code themselves.
How easily a program can be understood, corrected, adapted and extended after it has been written, often by people other than its original author.
Designing a program as a set of separate, self-contained parts (subprograms and modules), each performing one well-defined task and communicating with the others only through parameters and return values.
A separate file of related subprograms, constants and classes that other programs can import and use.
A loop placed inside the body of another loop, so the inner loop runs through all of its passes for each pass of the outer loop.
A selection structure placed inside one of the blocks of another selection structure, so the inner condition is tested only when the outer branch has been taken.
A variable named in a subprogram's definition that receives a value when the subprogram is called, and exists only while the subprogram runs.
A way of passing arguments in which the subprogram receives a copy of each argument's value, so assigning a new value to a parameter does not change the caller's variable.
A conditional loop that tests its condition after each pass, so the body always runs at least once.
A conditional loop that tests its condition before each pass, so the body runs zero times if the condition is false at the start.
A fault in which the result of a program depends on the timing or order in which two or more processes or threads access shared data, so the same program can give different results on different runs.
The value that a subprogram sends back to the point where it was called, using a return statement, which also ends the subprogram.
The extent to which code, once written and tested, can be used again in other parts of the same program or in other programs without being rewritten.
The control structure in which a condition is tested and its result decides which block of instructions runs next.
A special input value, outside the range of valid data, that signals the end of the data and stops a loop.
The control structure in which instructions are carried out one after another, in the order in which they are written.
A named, self-contained block of code that performs one specific task and can be run from other parts of a program by using its name; called a function in Python and a method in Java.
A statement or expression that runs a subprogram by name, passing it any values it needs, after which control returns to the point just after the call.
An automatic check that input data is reasonable and follows set rules (for example present, of the correct type, within a range, or of the correct length or format) before a program uses it.
A subprogram that carries out an action but returns no value to its caller; in Java its return type is written void.
YouTubeA program is a list of instructions, but the processor does not always run them in the order they are written. The order in which statements execute is called the flow of control. A result from 1966 known as the structured program theorem shows that sequence, selection and iteration together are enough to express any algorithm, which is why every mainstream language provides all three.
Sequence is the default. Unless a selection or a loop changes the flow, the statement on line 5 runs after line 4 and before line 6, and every value it uses must already have been set by an earlier line.
Selection lets a program respond to its data: a ticket machine charges a child less than an adult, a thermostat switches the heating on only when the room is cold. Each run of the program follows one path through the selection and skips the others.
The three structures map directly onto flowchart symbols. Sequence is a column of process and input/output boxes joined by flowlines; selection is a decision symbol with two labelled exits; iteration is a decision whose flowline loops back to an earlier point.

All three structures depend on conditions. A condition is a Boolean expression: it evaluates to exactly one of two values, true or false.
Conditions are built from relational operators, which compare two values (<, <=, >, >=, ==, !=), and Boolean operators, which combine or invert conditions. The relational operators are written the same way in both course languages, but the Boolean operators are not.
Meaning | Python | Java | True when |
|---|---|---|---|
equal to |
|
| both sides have the same value |
not equal to |
|
| the values differ |
less than, less than or equal |
|
| the left value is smaller (or equal) |
greater than, greater than or equal |
|
| the left value is larger (or equal) |
AND |
|
| both conditions are true |
OR |
|
| at least one condition is true |
NOT |
|
| the condition is false |
In a sequence, each statement works on the state that the earlier statements left behind. Moving a statement up or down therefore changes which values it sees, and so changes the result, even though every individual line is still correct.
The simplest correct order is input → process → output: a value must be obtained before it is used, and a result must be calculated before it is displayed. The program marks follows that order, matching the sequence flowchart in the figure of the three control structures.
mark1 = 64
mark2 = 71
mark3 = 85
total = mark1 + mark2 + mark3
average = total / 3
print("Total:", total)
print("Average:", round(average, 1))public class Marks {
public static void main(String[] args) {
int mark1 = 64;
int mark2 = 71;
int mark3 = 85;
int total = mark1 + mark2 + mark3;
double average = total / 3.0;
System.out.println("Total: " + total);
System.out.println("Average: " + Math.round(average * 10) / 10.0);
}
}The program prints the total and the average rounded to one decimal place.
Total: 220
Average: 73.3The Java version divides by 3.0, not 3. Dividing two int values in Java performs integer division, so 220 / 3 would give 73; Python's / always gives a floating-point result. Placing average = total / 3 before the line that calculates total would fail completely: Python stops with a NameError because total does not exist yet, and the Java compiler refuses to compile a variable used before it is declared.
Some ordering faults produce no error message at all, which makes them harder to find. These are logic errors: the program runs and prints something, but the output is wrong. Three patterns cause most of them.
Overwriting a value before it has been used. Swapping two variables with a = b then b = a loses the original value of a, because the first assignment overwrites it.
Initialising in the wrong place. A running total set to 0 inside a loop is reset on every pass, so only the last value survives.
Outputting before processing. Printing a result before the line that updates it shows the old value.
The program swap shows the first pattern. Both halves contain the same three kinds of statement; only their order and the extra variable temp differ.
a = 5
b = 9
# Wrong order: the first assignment destroys the value of a
a = b
b = a
print(a, b)
a = 5
b = 9
# Correct: keep a copy of a first
temp = a
a = b
b = temp
print(a, b)public class Swap {
public static void main(String[] args) {
int a = 5;
int b = 9;
// Wrong order: the first assignment destroys the value of a
a = b;
b = a;
System.out.println(a + " " + b);
a = 5;
b = 9;
// Correct: keep a copy of a first
int temp = a;
a = b;
b = temp;
System.out.println(a + " " + b);
}
}A trace table of the correct swap records each variable after every line. The value 5 survives in temp while a is overwritten, so it can be copied into b at the end.
Line |
|
|
| Output |
|---|---|---|---|---|
| 5 | |||
| 5 | 9 | ||
| 5 | 9 | 5 | |
| 9 | 9 | 5 | |
| 9 | 5 | 5 | |
| 9 | 5 | 5 |
|
The wrong version prints 9 9. Python also allows a, b = b, a, which evaluates both values on the right before assigning either, so no temporary variable is needed; Java has no equivalent and always uses temp.
The program tax should add 20% tax to a price of 40 and print the total, but it prints 40 instead of 48.
price = 40
tax = 0
total = price + tax
tax = price * 0.2
print(total)Selection lets a program choose between blocks of code. In both course languages the chosen block is marked out clearly: Java wraps it in braces { }, and Python indents it under a line ending in a colon. Four shapes of selection appear in almost every program: single, two-way, multi-way and nested.
A single selection (if on its own) runs a block when the condition is true and does nothing otherwise. A two-way selection (if … else) always runs exactly one of two blocks. The program temperature check uses both: the fever warning appears only for high readings, while the second statement always prints one of two messages.
temperature = 38.4
if temperature >= 38.0:
print("Fever: see the school nurse")
if temperature >= 35.0 and temperature <= 37.5:
print("Normal")
else:
print("Outside the normal range")public class Temperature {
public static void main(String[] args) {
double temperature = 38.4;
if (temperature >= 38.0) {
System.out.println("Fever: see the school nurse");
}
if (temperature >= 35.0 && temperature <= 37.5) {
System.out.println("Normal");
} else {
System.out.println("Outside the normal range");
}
}
}For a reading of 38.4 the program prints two lines, Fever: see the school nurse and Outside the normal range. The second condition is a range check built from two relational comparisons joined by AND; Python also accepts the chained form 35.0 <= temperature <= 37.5, which Java does not.
Java needs brackets round every condition, and its blocks are only safe with braces. Without braces, a Java if controls just the one statement that follows it, whatever the indentation suggests. Python has no such trap, because its indentation is the block structure.
When there are more than two possible outcomes, a chain of conditions picks one of them. Python writes each extra test as elif; Java writes else if.
The function grade converts a mark out of 100 into a grade using a set of hypothetical school grade boundaries. Each test only runs if every test before it was false, so mark >= 68 effectively means "68 or more, and below 80".
def grade(mark):
if mark >= 80:
return 7
elif mark >= 68:
return 6
elif mark >= 55:
return 5
elif mark >= 42:
return 4
else:
return 3
for mark in [91, 80, 79, 55, 30]:
print(mark, grade(mark))public class Grades {
public static int grade(int mark) {
if (mark >= 80) {
return 7;
} else if (mark >= 68) {
return 6;
} else if (mark >= 55) {
return 5;
} else if (mark >= 42) {
return 4;
} else {
return 3;
}
}
public static void main(String[] args) {
int[] marks = {91, 80, 79, 55, 30};
for (int mark : marks) {
System.out.println(mark + " " + grade(mark));
}
}
}The test values were chosen as boundary data: 80 sits exactly on a boundary and 79 just below it, so they show whether >= or > was used correctly.
91 7
80 7
79 6
55 5
30 3The flowchart of the grade chain shows why the order of the tests matters: the flow leaves the chain at the first "Yes" and never reaches the later decisions.

If the same four tests are written from the lowest boundary upwards (mark >= 42 first), a mark of 91 makes the first condition true and is given grade 4: every mark of 42 or more gets a 4. The rule for ordering is to test the most restrictive condition first, or to write each condition as a full range (mark >= 68 and mark < 80) so that order no longer matters.
A selection inside another selection's block is nested. The inner test only runs when the outer test has led into its block, so nesting expresses decisions that depend on earlier decisions.
The function ticket_price charges a fixed child price, and only for older visitors does it go on to ask whether they are members.
def ticket_price(age, is_member):
if age < 12:
price = 4.00
else:
if is_member:
price = 6.50
else:
price = 9.00
return price
print(ticket_price(8, False))
print(ticket_price(15, True))
print(ticket_price(40, False))public class Tickets {
public static double ticketPrice(int age, boolean isMember) {
double price;
if (age < 12) {
price = 4.00;
} else {
if (isMember) {
price = 6.50;
} else {
price = 9.00;
}
}
return price;
}
public static void main(String[] args) {
System.out.println(ticketPrice(8, false));
System.out.println(ticketPrice(15, true));
System.out.println(ticketPrice(40, false));
}
}The calls print 4.0, 6.5 and 9.0. The same logic can be written without nesting as a three-way else-if chain (if age < 12:, then elif is_member:, then else:), because the elif is only reached when the age test has already failed; the flat chain is often easier to read. Deep nesting, three or more levels, is a sign that the logic should be simplified or split into a separate function.
CVE-2014-1266, fixed by Apple in February 2014, was a flaw in SecureTransport, the library that Safari and many other Apple apps used to check that an HTTPS server really owned the certificate it presented. Apple's security note described it in a single sentence, and programmers outside the company traced the cause in the published source code. In a C function called SSLVerifySignedServerKeyExchange, a line had been duplicated.
if ((err = SSLHashSHA1.update(&hashCtx, &signedParams)) != 0)
goto fail;
goto fail;
if ((err = SSLHashSHA1.final(&hashCtx, &hashOut)) != 0)
goto fail;Source: Apple's published source code, as quoted by Adam Langley, "Apple's SSL/TLS bug", ImperialViolet, 22 February 2014.
C, like Java, attaches only the first statement after an unbraced if to the condition. The first goto fail; was conditional; the second, despite its indentation, ran every time. It jumped to the end of the function with err still holding the "success" value from the previous step, so the final hash check and the signature check after it were never reached. Any server could send a valid certificate chain and sign the key exchange with the wrong private key, or not sign it at all, and the connection was still accepted. The flaw affected iOS before version 7.0.6 and OS X before 10.9.2.
The bug is a lesson in both sequence and selection. In sequence terms, an extra line inserted between two steps made every later step unreachable. In selection terms, the visible layout of the code (indentation) and its real structure (one statement per unbraced if) disagreed. The same trap exists in Java: the program Dangling sets cancelled to true even though there is enough money, because the second indented line is outside the if.
public class Dangling {
public static void main(String[] args) {
double balance = 20.00;
double price = 12.50;
boolean cancelled = false;
if (balance < price)
System.out.println("Not enough money");
cancelled = true; // indented, but NOT inside the if
System.out.println("Cancelled: " + cancelled);
cancelled = false;
if (balance < price) {
System.out.println("Not enough money");
cancelled = true;
}
System.out.println("Cancelled: " + cancelled);
}
}balance = 20.00
price = 12.50
cancelled = False
# In Python the indentation IS the block: this line is outside the if,
# and it looks outside the if.
if balance < price:
print("Not enough money")
cancelled = True
print("Cancelled:", cancelled)
cancelled = False
if balance < price:
print("Not enough money")
cancelled = True
print("Cancelled:", cancelled)Both versions report the order as cancelled after the first if and not cancelled after the second. Three habits prevent this class of error. Always using braces in Java, even round a single statement, makes every block explicit. Automatic code formatters re-indent code to match its real structure, so a misleading indent becomes visible. Compilers can also warn about unreachable code: the Clang compiler, with every warning switched on (-Weverything), reports statements that can never run, which would have pointed straight at the skipped hash check.
A loop repeats a block, called the body, and each repetition is one iteration or pass. The choice of loop depends on two facts about the task: whether the number of repetitions is known before the loop starts, and whether the body must run at least once.
When the number of repetitions is known in advance (10 students, every element of a list, the numbers 1 to n), a counted loop is the right choice.
Python's for i in range(start, stop, step) gives i the values from start up to, but not including, stop. Java's for (int i = start; i < stop; i += step) packs the same three parts (initialise, test, update) into the loop header.
Python | Java | Values of |
|---|---|---|
|
| 0, 1, 2, 3 |
|
| 2, 3, 4, 5, 6 |
|
| 10, 7, 4, 1 |
|
| 1 to n |
A counted loop over a collection can skip the index altogether: Python's for score in scores: and Java's enhanced for (int score : scores) give each element in turn. That form is shorter and avoids index mistakes, but it gives no position and cannot change the elements of a Java array.
Loops are often used to build up a result. Two kinds of variable appear in nearly every loop that processes data.
The program sum to n adds the numbers 1 to 5, printing the loop variable and the accumulator on each pass.
n = 5
total = 0
for i in range(1, n + 1):
total = total + i
print(i, total)
print("Sum of 1 to", n, "is", total)public class SumTo {
public static void main(String[] args) {
int n = 5;
int total = 0;
for (int i = 1; i <= n; i++) {
total = total + i;
System.out.println(i + " " + total);
}
System.out.println("Sum of 1 to " + n + " is " + total);
}
}The trace table records the state at the end of each pass. The final total, 15, matches the formula , a useful check.
Pass |
|
| Output |
|---|---|---|---|
before loop | 0 | ||
1 | 1 | 1 |
|
2 | 2 | 3 |
|
3 | 3 | 6 |
|
4 | 4 | 10 |
|
5 | 5 | 15 |
|
after loop | 15 |
|
A counter is a special accumulator that always adds 1. Both must be initialised before the loop: a total set to 0 inside the body is reset on every pass. For the scores 12, 7, 9 and 15, a total reset inside the loop ends as 15 (only the last score) instead of 43.
When the number of repetitions depends on what happens while the program runs (a user keeps entering data, a search continues until it finds a match), the loop must test a condition instead of counting.
Both languages provide a while loop. Its condition is tested before each pass, which makes it a pre-condition loop.
Java also has a do … while loop, whose condition comes after the body.
The flowcharts of the two loop types place the decision at different points. In the pre-condition loop the input appears twice: once before the loop (so the first test has a value to check) and once at the end of the body. In the post-condition loop the input appears once, inside the body.

The rating program asks for a value from 1 to 5 and keeps asking until it gets one. Python has no do … while, so the post-condition form is written as while True: with a break once the value is valid.
rating = int(input("Rating (1-5): "))
while rating < 1 or rating > 5:
print("Out of range")
rating = int(input("Rating (1-5): "))
print("Thank you:", rating)
# Post-condition version: Python has no do...while
while True:
rating = int(input("Rating (1-5): "))
if rating >= 1 and rating <= 5:
break
print("Thank you:", rating)import java.util.Scanner;
public class Rating {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
System.out.print("Rating (1-5): ");
int rating = input.nextInt();
while (rating < 1 || rating > 5) {
System.out.println("Out of range");
System.out.print("Rating (1-5): ");
rating = input.nextInt();
}
System.out.println("Thank you: " + rating);
// Post-condition version
do {
System.out.print("Rating (1-5): ");
rating = input.nextInt();
} while (rating < 1 || rating > 5);
System.out.println("Thank you: " + rating);
}
}With the inputs 0, 9 and 4, each version rejects the first two and accepts 4. The pre-condition version prints Out of range twice; the post-condition version simply asks again. The do … while condition describes when to repeat (the value is invalid), which is the opposite of the condition in the Python if that leaves the loop (the value is valid): one is the NOT of the other, rewritten with De Morgan's laws.
Feature | Counted loop | Pre-condition loop | Post-condition loop |
|---|---|---|---|
Python |
|
|
|
Java |
|
|
|
Repetitions known in advance? | Yes | No | No |
Minimum passes | 0 (an empty range) | 0 | 1 |
Typical use | every element of a list; a fixed number of turns | sentinel input; searching until found | menus; validated input that must be asked once |
A common way to end a conditional loop that reads data is to agree on a special value that cannot be real data. When the program reads that value, it stops.
The program average with sentinel reads marks until −1 and prints their average. It reads the first mark before the loop and the next mark as the last line of the body, so the sentinel is tested before it can be added to the total. It also guards against dividing by zero when the first input is the sentinel.
total = 0
count = 0
mark = int(input("Mark (-1 to stop): "))
while mark != -1:
total = total + mark
count = count + 1
mark = int(input("Mark (-1 to stop): "))
if count > 0:
print("Average:", total / count)
else:
print("No marks entered")import java.util.Scanner;
public class Average {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
int total = 0;
int count = 0;
System.out.print("Mark (-1 to stop): ");
int mark = input.nextInt();
while (mark != -1) {
total = total + mark;
count = count + 1;
System.out.print("Mark (-1 to stop): ");
mark = input.nextInt();
}
if (count > 0) {
System.out.println("Average: " + (double) total / count);
} else {
System.out.println("No marks entered");
}
}
}A loop condition can combine several tests with Boolean operators, so the loop stops for whichever reason comes first. The program find negative searches a list of sensor readings for the first negative value; the loop continues while there are readings left and no negative value has been found.
readings = [4.2, 3.9, -1.0, 5.1, 4.4]
i = 0
found = False
while i < len(readings) and not found:
if readings[i] < 0:
found = True
else:
i = i + 1
if found:
print("First negative reading at index", i)
else:
print("No negative readings")public class FindNegative {
public static void main(String[] args) {
double[] readings = {4.2, 3.9, -1.0, 5.1, 4.4};
int i = 0;
boolean found = false;
while (i < readings.length && !found) {
if (readings[i] < 0) {
found = true;
} else {
i = i + 1;
}
}
if (found) {
System.out.println("First negative reading at index " + i);
} else {
System.out.println("No negative readings");
}
}
}The trace table includes a column for each part of the condition, which shows exactly which part ends the loop.
|
|
|
| Condition | Action |
|---|---|---|---|---|---|
0 | 4.2 | True | True | True |
|
1 | 3.9 | True | True | True |
|
2 | −1.0 | True | True | True |
|
2 | −1.0 | True | False | False | loop ends |
The output is First negative reading at index 2. This shape is the basis of linear search. The order of the two tests matters. Python's and and Java's && use short-circuit evaluation: if the left side is false, the right side is not evaluated at all. Putting i < len(readings) first means that when i reaches 5 the condition stops before readings[5] is read; written the other way round, a list with no negative values makes the program crash with an IndexError (Java: ArrayIndexOutOfBoundsException).
The same task can be written with a for loop and a break statement, which leaves the loop immediately.
readings = [4.2, 3.9, -1.0, 5.1, 4.4]
position = -1
for i in range(len(readings)):
if readings[i] < 0:
position = i
break
print("First negative reading at index", position)
total = 0
for value in readings:
if value < 0:
continue
total = total + value
print("Total of valid readings:", round(total, 1))public class BreakContinue {
public static void main(String[] args) {
double[] readings = {4.2, 3.9, -1.0, 5.1, 4.4};
int position = -1;
for (int i = 0; i < readings.length; i++) {
if (readings[i] < 0) {
position = i;
break;
}
}
System.out.println("First negative reading at index " + position);
double total = 0;
for (double value : readings) {
if (value < 0) {
continue;
}
total = total + value;
}
System.out.println("Total of valid readings: " + Math.round(total * 10) / 10.0);
}
}The program prints First negative reading at index 2 and Total of valid readings: 17.6, because continue skips −1.0 and adds the other four readings (4.2 + 3.9 + 5.1 + 4.4). break and continue make short loops concise, but a loop with several exits is harder to trace, because the reason for stopping is hidden in the body instead of stated in the condition. For anything longer than a few lines, a flag in the loop condition is usually clearer.
A program that accepts input from people must assume that some of it will be wrong. Checking input before using it, and asking again until it is acceptable, is one of the most common uses of a conditional loop.
The function read_age combines three checks. A presence check rejects empty input; a type check uses exception handling to catch text that is not a whole number; a range check rejects numbers outside 11 to 19. The loop only ends through the return, once all three checks pass.
def read_age():
while True:
text = input("Age (11-19): ")
if text == "":
print("Presence check failed: enter a value")
else:
try:
age = int(text)
if age >= 11 and age <= 19:
return age
print("Range check failed: 11 to 19 only")
except ValueError:
print("Type check failed: whole numbers only")
age = read_age()
print("Accepted:", age)import java.util.Scanner;
public class ReadAge {
static Scanner input = new Scanner(System.in);
public static int readAge() {
while (true) {
System.out.print("Age (11-19): ");
String text = input.nextLine();
if (text.equals("")) {
System.out.println("Presence check failed: enter a value");
} else {
try {
int age = Integer.parseInt(text);
if (age >= 11 && age <= 19) {
return age;
}
System.out.println("Range check failed: 11 to 19 only");
} catch (NumberFormatException e) {
System.out.println("Type check failed: whole numbers only");
}
}
}
}
public static void main(String[] args) {
int age = readAge();
System.out.println("Accepted: " + age);
}
}Testing the function with one input of each kind (an empty line, fifteen, 23, then 16) exercises every branch. The run shows each check failing in turn before the valid value is accepted.
Age (11-19): Presence check failed: enter a value
Age (11-19): Type check failed: whole numbers only
Age (11-19): Range check failed: 11 to 19 only
Age (11-19): Accepted: 16Validation reduces errors but has limits. It cannot detect a value that is valid but wrong (a student typing 15 instead of 16), so data that must be exact is also checked by verification, such as typing a password twice. Validation also protects security: unchecked input passed straight into a database query is how SQL injection attacks work, a topic for HL students in subtopic A2.4, Network security.
A loop inside the body of another loop runs completely for every single pass of the outer loop. Nested loops process two-dimensional data (rows and columns of a 2D array, every pair of items, a times table).
The program triangle prints a triangle of products: row 1 has one value, row 2 two, row 3 three, because the inner loop's range depends on the outer loop variable.
for row in range(1, 4):
line = ""
for col in range(1, row + 1):
line = line + str(row * col) + " "
print(line)public class Nested {
public static void main(String[] args) {
for (int row = 1; row <= 3; row++) {
String line = "";
for (int col = 1; col <= row; col++) {
line = line + (row * col) + " ";
}
System.out.println(line);
}
}
}The number of passes in nested loops grows quickly. Two loops that each run n times execute the inner body times, so doubling the data makes the work four times larger; subtopic B2.4, Programming algorithms, measures this with Big O notation. Repetition can also be written without a loop, as recursion (a subprogram that calls itself); the Computerphile video on loops and recursion sets the two approaches side by side.
YouTubePrograms that compile and run can still fail in three ways related to the order and control of their instructions: they never finish, they stop making progress while waiting for each other, or they finish with the wrong answer.
A loop ends only when its condition changes. If nothing in the body can make the condition false, the loop runs for ever.
Three causes account for most infinite loops: the loop variable is never updated; it is updated in the wrong direction (count = count - 1 in a loop waiting for count > 10); or the condition tests for an exact value that the variable jumps over. Deliberate infinite loops do exist (a server or a game waits for events in while True:), but they always contain a break or return that ends them.
The program odd numbers should print the odd numbers below 10, but it never stops.
x = 1
while x != 10:
print(x)
x = x + 2A real infinite loop stopped thousands of devices at once. On 31 December 2008, many first-generation Microsoft Zune 30 music players froze; Microsoft blamed the clock driver supplied by Freescale and its handling of leap years, and the players recovered by themselves the next day. Analysis of the published driver code showed a year-counting loop that could not finish on the 366th day of a leap year.
Sources: Microsoft's statement as reported in "Zune", Wikipedia; Dr. Drang, "Leap year and the Zune", And now it's all this, January 2009.
The function year_from_day is a simplified Python version of that loop. It counts days from 1 January 1980 (day 1) and subtracts a year's worth of days at a time until fewer than a year's worth remain.
def is_leap_year(year):
return (year % 4 == 0 and year % 100 != 0) or year % 400 == 0
def year_from_day(days):
year = 1980
while days > 365:
if is_leap_year(year):
if days > 366:
days = days - 366
year = year + 1
else:
days = days - 365
year = year + 1
return year
print(year_from_day(10592))public class Zune {
public static boolean isLeapYear(int year) {
return (year % 4 == 0 && year % 100 != 0) || year % 400 == 0;
}
public static int yearFromDay(int days) {
int year = 1980;
while (days > 365) {
if (isLeapYear(year)) {
if (days > 366) {
days = days - 366;
year = year + 1;
}
} else {
days = days - 365;
year = year + 1;
}
}
return year;
}
public static void main(String[] args) {
System.out.println(yearFromDay(10592));
}
}Day 10592 is 30 December 2008, and the call prints 2008. Day 10593, 31 December 2008, never returns.
A corrected function makes every pass subtract a year, and compares days with the length of the current year in the loop condition itself.
def days_in_year(year):
if (year % 4 == 0 and year % 100 != 0) or year % 400 == 0:
return 366
else:
return 365
def year_from_day(days):
year = 1980
while days > days_in_year(year):
days = days - days_in_year(year)
year = year + 1
return year
for day in [1, 366, 367, 10592, 10593, 10594]:
print(day, year_from_day(day))public class ZuneFixed {
public static int daysInYear(int year) {
if ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0) {
return 366;
} else {
return 365;
}
}
public static int yearFromDay(int days) {
int year = 1980;
while (days > daysInYear(year)) {
days = days - daysInYear(year);
year = year + 1;
}
return year;
}
public static void main(String[] args) {
int[] tests = {1, 366, 367, 10592, 10593, 10594};
for (int day : tests) {
System.out.println(day + " " + yearFromDay(day));
}
}
}The test days are chosen at the boundaries: the first and last days of 1980 (a leap year), the first day of 1981, and the last days of 2008 and first of 2009.
1 1980
366 1980
367 1981
10592 2008
10593 2008
10594 2009Deadlock arises when programs share resources such as files, printers or database records. A program that needs two resources usually takes, or locks, them one at a time so that no other program can change them while it works. If two programs lock the same two resources in opposite orders, each can end up holding one and waiting for the other.
The deadlock diagram shows a booking app and a report app sharing a seat file and a payment file. The booking app has locked the seat file and is waiting for the payment file; the report app has locked the payment file and is waiting for the seat file. Neither will release what it holds until it gets what it is waiting for, so both wait for ever.

A deadlock differs from an infinite loop. In an infinite loop the program is busy doing the same work again and again; in a deadlock the programs are idle, each blocked and waiting, and the processor may have nothing to do. Deadlock is also different from a fault in one program: each program on its own is correct, and the error only appears when their steps happen in a particular order.
Ordering is the most common way to prevent deadlock. If every program that needs both files agrees to lock the seat file first and the payment file second, the cycle in the diagram cannot form: whichever program gets the seat file first will also get the payment file, finish, and release both. Other approaches are to request all resources at once, to give up held resources after waiting for a set time (a timeout) and try again later, and to hold locks for as short a time as possible.
A related fault is the race condition, in which nothing stops, but the result depends on timing.
Two tills selling the last ticket for a concert show the problem. Each till reads the number of tickets left, subtracts one and writes the new value back. If both tills read before either writes, both sell the same ticket.
Step | Till 1 | Till 2 | Tickets left (stored) |
|---|---|---|---|
1 | reads 1 | 1 | |
2 | reads 1 | 1 | |
3 | sells ticket, writes 0 | 0 | |
4 | sells ticket, writes 0 | 0 |
The stored value ends at 0, but two tickets have been sold. On 14 August 2003 a race condition in General Electric's XA/21 energy management system stalled the alarm system in FirstEnergy's control room for over an hour; the operators lost both the audio and the visual alerts that should have warned them of changes in the grid, and the blackout that followed affected about 55 million people in eight US states and Ontario. The usual fix uses the same locks that make deadlock possible: each till locks the stored value before reading it and releases the lock after writing, so the read–update–write sequence acts as a single step that the other till cannot interrupt.
Source: "Northeast blackout of 2003", Wikipedia.
Most incorrect output comes from logic errors that a careful order of design steps would catch. Common sources are statements in the wrong order, conditions using < where <= is needed, uninitialised or wrongly initialised variables, and output placed inside a loop instead of after it (or the reverse). A short design routine prevents most of these faults:
Plan before coding. Write the steps as a flowchart or numbered list, and check that every value is set before it is used.
Initialise before use. Set accumulators, counters and flags on the line before the loop that updates them.
Make every loop progress. Check that each path through a loop body changes the value its condition depends on.
Trace by hand. Follow the code with a trace table for a small input, recording each change.
Test with planned data. Use normal, boundary and erroneous data, and compare the actual output with the expected output worked out beforehand.
As programs grow, the same steps are needed in several places: reading a validated number, calculating an average, printing a heading. Copying those lines each time makes the program longer and creates several copies to fix whenever a fault is found. Subprograms solve this by giving a block of code a name, so it is written once and called wherever it is needed.
A subprogram has two parts: its definition, which states its name, its inputs and the code it runs, and the places where it is called. Defining a subprogram does not run it; the code inside runs only when it is called.
A subprogram becomes reusable when it works on different values each time it is called. The values are passed in through parameters.
A subprogram can send one result back to the caller with a return statement. The call then acts as an expression whose value is the result, so it can be stored, printed or used in a calculation.
The program rooms defines one subprogram that returns a value and one that only performs an action.
def rectangle_area(length, width):
area = length * width
return area
def print_banner(title):
print("=" * len(title))
print(title)
print("=" * len(title))
floor = rectangle_area(4.5, 3)
wall = rectangle_area(4.5, 2.4)
print_banner("Paint order")
print("Floor:", floor, "m2")
print("Wall:", round(wall, 2), "m2")public class Rooms {
public static double rectangleArea(double length, double width) {
double area = length * width;
return area;
}
public static void printBanner(String title) {
System.out.println("=".repeat(title.length()));
System.out.println(title);
System.out.println("=".repeat(title.length()));
}
public static void main(String[] args) {
double floor = rectangleArea(4.5, 3);
double wall = rectangleArea(4.5, 2.4);
printBanner("Paint order");
System.out.println("Floor: " + floor + " m2");
System.out.println("Wall: " + Math.round(wall * 100) / 100.0 + " m2");
}
}Both versions print the same report.
===========
Paint order
===========
Floor: 13.5 m2
Wall: 10.8 m2The wall area is rounded because is stored as 10.799999999999999 in floating point. The subprogram call diagram follows the first call step by step.

The two languages differ in how much they make explicit. A Java method must sit inside a class, declares the data type of every parameter, and declares its return type before its name (double rectangleArea(...)); programs without objects mark their methods static. A Python function declares no types, and if it reaches the end without a return it returns the special value None. A Python function can also return several values at once as a tuple (return low, high); a Java method returns exactly one value.
Older terminology calls a subprogram that returns a value a function and one that does not a procedure. In Python both are written with def, and in Java both are methods, distinguished only by whether the return type is void.
When a subprogram is called, each argument is copied into its parameter. The parameter is a separate variable, so changing it inside the subprogram does not change the caller's variable.
The program bonus shows both sides of this rule. Adding 10 to the parameter score has no effect on mark outside, but changing the elements of a list or array passed in does change the caller's list, because the copy is a reference to the same list.
def add_bonus(score):
score = score + 10
print("Inside add_bonus:", score)
def add_bonus_to_all(scores):
for i in range(len(scores)):
scores[i] = scores[i] + 10
mark = 50
add_bonus(mark)
print("After add_bonus:", mark)
marks = [50, 60]
add_bonus_to_all(marks)
print("After add_bonus_to_all:", marks)import java.util.Arrays;
public class Bonus {
public static void addBonus(int score) {
score = score + 10;
System.out.println("Inside addBonus: " + score);
}
public static void addBonusToAll(int[] scores) {
for (int i = 0; i < scores.length; i++) {
scores[i] = scores[i] + 10;
}
}
public static void main(String[] args) {
int mark = 50;
addBonus(mark);
System.out.println("After addBonus: " + mark);
int[] marks = {50, 60};
addBonusToAll(marks);
System.out.println("After addBonusToAll: " + Arrays.toString(marks));
}
}The output confirms that mark is unchanged while the list's elements have changed.
Inside add_bonus: 60
After add_bonus: 50
After add_bonus_to_all: [60, 70]Java always passes by value: a primitive such as int is copied, and for an array, ArrayList or other object the reference is copied, so the method and the caller share one object. Python passes a reference to every object; because integers and strings are immutable, "changing" one inside a function creates a new object and the caller's variable is untouched, while a list is mutable and can be changed in place. In practice the two languages behave the same way. Some other languages, such as C++, also offer pass by reference, in which the parameter becomes another name for the caller's variable; neither course language has it, so a subprogram that must give back a new number or string returns it.
Every variable has a scope: the part of the program in which it can be used. Parameters and variables created inside a subprogram are local variables: they are created when the subprogram is called and destroyed when it returns, and no other subprogram can see them. Variables created outside every subprogram are global variables, visible throughout the program.
visits = 0 # global variable
def record_visit():
global visits
visits = visits + 1
def show_message():
visits = 99 # a new local variable, not the global one
print("Local visits:", visits)
record_visit()
record_visit()
show_message()
print("Global visits:", visits)public class Visits {
static int visits = 0; // class-level (static) variable: Java's "global"
public static void recordVisit() {
visits = visits + 1;
}
public static void showMessage() {
int visits = 99; // a new local variable, not the static one
System.out.println("Local visits: " + visits);
}
public static void main(String[] args) {
recordVisit();
recordVisit();
showMessage();
System.out.println("Global visits: " + visits);
}
}The program prints Local visits: 99 and then Global visits: 2. Python needs the keyword global before a function can assign to a global variable; without it, visits = visits + 1 creates a local visits and fails with UnboundLocalError, because the local variable is read before it has a value. Java has no true global variables: the nearest equivalent is a static variable declared in the class, outside every method. In both languages, the local visits in show_message hides the global one of the same name, which is shadowing.
Scope differs inside loops too. A Java variable declared inside a loop or if block exists only within that block's braces, so it cannot be used after the loop. A Python variable created inside a loop is local to the whole function and still exists after the loop ends.
Global variables are convenient but make programs harder to maintain. Any subprogram can change a global, so when its value is wrong, every subprogram is a suspect; a subprogram that relies on a global also cannot be reused in another program without bringing the global with it. Passing values in as arguments and sending results back with return keeps each subprogram self-contained. Constants, values that never change, such as PASS_MARK = 42, are the accepted exception, because no subprogram is meant to change them. Java enforces this with final; Python relies on the convention that a name in capitals is not reassigned.
The program points uses the same name for a global variable and a local one.
total = 5
def add_points(points):
total = points * 2
return total
result = add_points(4)
print(result, total)Writing a subprogram to a specification follows a fixed routine: decide its inputs (the parameters), its output (the return value, or void), and the steps between them; then test it with calls that cover normal, boundary and erroneous cases. Selection, a loop, a flag and a return value combine in a short password checker.
Splitting a program into subprograms is the first step of a wider idea: organising the whole program as separate, independent parts.
Groups of related subprograms are stored together in a module, which other programs can then load.
The module structure diagram shows two programs sharing one module of mark-processing functions, while one of them also uses the standard maths library.

The module grade_tools holds the reusable code; the main program report imports it and calls its functions through the module's name.
# grade_tools.py: a module of reusable functions for marks
PASS_MARK = 42
def average(marks):
total = 0
for mark in marks:
total = total + mark
return total / len(marks)
def count_passes(marks):
count = 0
for mark in marks:
if mark >= PASS_MARK:
count = count + 1
return count// GradeTools.java: a class of reusable static methods for marks
public class GradeTools {
public static final int PASS_MARK = 42;
public static double average(int[] marks) {
int total = 0;
for (int mark : marks) {
total = total + mark;
}
return (double) total / marks.length;
}
public static int countPasses(int[] marks) {
int count = 0;
for (int mark : marks) {
if (mark >= PASS_MARK) {
count = count + 1;
}
}
return count;
}
}The main program contains no calculation of its own, only calls. Python names a function from a module as module.function; Java names a static method as Class.method.
# report.py: the main program imports the module and calls its functions
import math
import grade_tools
class_marks = [35, 58, 72, 41, 90]
mean = grade_tools.average(class_marks)
print("Average:", mean)
print("Rounded up:", math.ceil(mean))
print("Passes:", grade_tools.count_passes(class_marks))// Report.java: the main program calls methods of GradeTools and Math
public class Report {
public static void main(String[] args) {
int[] classMarks = {35, 58, 72, 41, 90};
double mean = GradeTools.average(classMarks);
System.out.println("Average: " + mean);
System.out.println("Rounded up: " + (int) Math.ceil(mean));
System.out.println("Passes: " + GradeTools.countPasses(classMarks));
}
}The program prints Average: 59.2, Rounded up: 60 and Passes: 3 (58, 72 and 90 reach the pass mark; 41 misses it by one).
Modular programs are easier to build and to keep working, and two qualities sum up why.
The benefits depend on the scenario.
Benefit | How modularisation provides it | Scenario |
|---|---|---|
Reuse | a subprogram is written once and called many times, or imported by other programs | a school's report program and its email program share |
Easier testing | each subprogram can be tested on its own with chosen arguments before it is combined with the rest (unit testing) |
|
Easier debugging | a fault is narrowed down to one subprogram whose inputs and outputs can be checked | a wrong average is traced to |
Teamwork | different programmers write different modules at the same time, agreeing only on names, parameters and return values | one developer builds the payment module while another builds the booking module |
Readability | the main program reads like a summary of the steps, with descriptive subprogram names |
|
Single point of change | a rule held in one place is changed once | the pass mark changes from 42 to 45 by editing one constant |
Modularisation has costs. Designing the interfaces between modules takes time, a very small program gains little from being split up, and calling a subprogram has a small overhead compared with running the same lines in place. Its benefits all concern writing, testing and maintaining the program, while running speed stays the same or becomes very slightly worse.
Programming constructs are examined in Paper 2, in the language of your paper (Python or Java), and they underpin almost every question on it. The statements use the command term construct, so expect to write working code: a selection that classifies values, a loop that reads data until a sentinel, a validation loop, or a complete function with parameters and a return value, usually for 3–6 marks. Trace questions (2–6 marks) give code with selection, loops or nested loops and ask for a trace table or the output; identify and explain questions ask why a loop never terminates, why a condition gives the wrong result, or why one loop type suits a task better than another. Questions may forbid built-in functions such as len, max or sum, so practise the hand-written loop versions. The no-code algorithmic-thinking question may present the same constructs as a flowchart to trace.
The code for the exam-style question finds the best day and counts the days with at least 10,000 steps in a week of step counts.
steps = [8200, 11500, 9900, 12000, 7600]
best = steps[0]
days_over = 0
for i in range(1, len(steps)):
if steps[i] > best:
best = steps[i]
if steps[i] >= 10000:
days_over = days_over + 1
print(best, days_over)public class Steps {
public static void main(String[] args) {
int[] steps = {8200, 11500, 9900, 12000, 7600};
int best = steps[0];
int daysOver = 0;
for (int i = 1; i < steps.length; i++) {
if (steps[i] > best) {
best = steps[i];
}
if (steps[i] >= 10000) {
daysOver = daysOver + 1;
}
}
System.out.println(best + " " + daysOver);
}
}A construct answer is marked on features of the code, not on perfect syntax: the correct initialisation, loop bounds, condition, update and return or output each earn a mark. A missing colon or semicolon is usually not penalised if the logic is clear, but a wrong index, a wrong comparison (> for >=) or an accumulator reset inside the loop loses the mark for that feature.
Explain questions on loops reward a reason tied to the task. To answer "why is a while loop more appropriate than a for loop here?", state that the number of repetitions is not known in advance, then name what controls the loop in this program (the sentinel, a valid input, finding the item).
State the three control structures from which every program can be built. [1]
Distinguish between a parameter and an argument. [2]
Outline the difference between a pre-condition loop and a post-condition loop, giving one situation suited to each. [3]
Identify the output of for i in range(3, 12, 4): print(i) (Java: for (int i = 3; i < 12; i += 4) System.out.println(i);). [1]
A program uses if mark >= 50: result = "Pass" followed by if mark >= 80: result = "Distinction" and else: result = "Fail" (the else belongs to the second if). Explain why a mark of 60 is given "Fail", and construct a corrected selection. [4]
Construct a program that reads temperatures until the sentinel 999 is entered, then outputs the highest temperature entered, or "No data" if none were entered. Do not use the built-in max. [6]
Trace the following code and state its output. [4]
count = 0
for a in range(1, 4):
for b in range(a, 4):
count = count + 1
print(count)Explain how a deadlock can occur between two programs that each need the same two files, and outline one way to prevent it. [4]
Explain two benefits of modularisation for a team developing a school timetable system. [4]
Explain why the following Python function causes an error when called, and suggest two ways to fix it. [3]
score = 0
def add_point():
score = score + 1Sequence, selection and iteration.
A parameter is the variable named in the subprogram's definition [1]; an argument is the actual value passed to it in a call, which is copied into the parameter [1].
A pre-condition loop tests its condition before each pass, so the body may run zero times; a post-condition loop tests after the body, so it runs at least once [1]. Pre-condition: reading marks until a sentinel, where the first input could be the sentinel [1]. Post-condition: showing a menu and reading a choice, which must happen at least once [1].
3, 7, 11 (each on its own line).
The two if statements are independent [1]. For 60, the first sets "Pass", but the second condition (60 ≥ 80) is false, so its else runs and overwrites the result with "Fail" [1]. Corrected (Python), award [2] for a chain in the right order:
if mark >= 80:
result = "Distinction"
elif mark >= 50:
result = "Pass"
else:
result = "Fail"Java: the same with else if and braces.
Award [1] each: read the first value before the loop; output "No data" when the first value is the sentinel (or use a flag or counter to detect that no data was entered); start the highest at the first value, not at 0; loop while the value is not 999, comparing each value with the highest so far and updating it; read the next value at the end of the body; output the highest after the loop.
temp = int(input("Temperature: "))
if temp == 999:
print("No data")
else:
highest = temp
while temp != 999:
if temp > highest:
highest = temp
temp = int(input("Temperature: "))
print(highest)Java: the same structure with a Scanner, nextInt() and while (temp != 999).
a = 1: b = 1, 2, 3 (count 1, 2, 3); a = 2: b = 2, 3 (count 4, 5); a = 3: b = 3 (count 6). Output 6. Award [1] per value of a traced correctly and [1] for the output.
Program A locks file 1 and program B locks file 2 [1]; A then waits for file 2 and B waits for file 1 [1]; neither releases what it holds, so both wait for ever [1]. Prevention: both programs lock the files in the same order / request both files at once / release held files after a timeout [1].
Award [1] for each benefit and [1] for its application, for example: different programmers can write the room-booking, teacher and student modules at the same time, agreeing only on subprogram names and parameters; each module (for example the clash-checking function) can be tested separately with chosen data before being combined, so faults are easier to locate; a rule such as the number of periods per day is held in one place and changed once.
Assigning to score inside the function makes it a local variable, so score + 1 reads the local before it has a value and Python raises UnboundLocalError [1]. Fixes: add global score as the first line of the function [1]; OR better, pass the score in as a parameter and return the new value: def add_point(score): return score + 1, called as score = add_point(score) [1].
Every program is built from sequence, selection and iteration; a condition is a Boolean expression built from relational operators (<, <=, >, >=, ==, !=) and Boolean operators (and/&&, or/||, not/!).
Instruction order decides the result: values must be set before they are used, accumulators initialised before the loop, and outputs placed after the processing they report.
Selection can be single (if), two-way (if–else), multi-way (elif in Python, else if in Java; only the first true branch runs, so the most restrictive test goes first) or nested; Java blocks need braces to avoid statements falling outside the if, as in Apple's goto fail bug.
A counted loop (for) repeats a known number of times; a conditional loop (while) repeats while a condition holds. A pre-condition loop may run zero times; a post-condition loop (Java do … while; Python while True with break) runs at least once.
Loops use accumulators, counters, flags and sentinel values; validation loops repeat until input passes presence, type and range checks; nested loops run the inner loop fully for each outer pass.
An infinite loop happens when no path through the body makes the condition false; deadlock happens when programs each hold a resource another needs; a race condition makes results depend on timing. Planning, tracing, consistent lock ordering and boundary testing prevent them.
A subprogram (Python function, Java method) receives arguments in its parameters and may send back a return value; a void method returns nothing. Arguments are passed by value, but a list or array passed in can have its elements changed.
Parameters and variables created in a subprogram are local; globals (Python global, Java static fields) are visible everywhere but harm maintainability.
Modularisation splits a program into subprograms and modules, giving reuse, easier testing and debugging, teamwork, readability and maintainability, but not faster execution.
I can identify sequence, selection and iteration in code and in a flowchart.
I can explain how moving one line (an initialisation, a calculation or an output) changes a program's result.
I can swap two variables correctly in Python and Java.
I can write a condition using relational and Boolean operators in both languages, including a range check.
I can construct an if–elif–else (Java if–else if–else) chain and order its conditions correctly.
I can trace a nested selection for given values, including values on a boundary.
I can choose between a counted, a pre-condition and a post-condition loop and justify the choice.
I can write the Python range and the Java for header for any start, stop and step.
I can construct a sentinel loop and a validation loop that use a counter, an accumulator or a flag.
I can trace a loop and a nested loop with a trace table, one row per pass.
I can identify why a loop never terminates and correct it.
I can explain deadlock and a race condition with an example, and give a way to prevent each.
I can construct a function or method with parameters and a return value, and say when a void method is appropriate.
I can predict the output of a program in which a local variable has the same name as a global one.
I can explain the benefits of modularisation in a given scenario, without claiming it makes programs faster.
State the value returned when ids holds [12, 7, 33, 7].
1 mark
True / true;
Calculate the number of times the comparison ids[i] == ids[j] is made, in the worst case, for a playlist of 6 songs.
2 marks
Award [1] for the method and [1] for the answer.
/ ;
15;
Note: Award [2] for 15 with no working.
Deduce the worst-case time complexity of has_duplicate / hasDuplicate, explaining your answer.
3 marks
Award [1] per point, up to [3 max].
In the worst case (no duplicates) every pair is compared once;
the number of comparisons is /
Describe the best case for this function/method and state its time complexity.
2 marks
Award [1] for the description and [1] for the complexity.
The first two songs (ids[0] and ids[1]) are the same, so it returns after one comparison;
;
The service now keeps every playlist sorted by ID.
Construct, in Python or Java, a function/method has_duplicate_sorted / hasDuplicateSorted that returns whether a sorted playlist contains a repeated ID, using a single loop. For example, [7, 12, 12, 33] returns true and [7, 12, 33] returns false.
4 marks
Award [1] per point, up to [4 max].
header with a list/array parameter (and boolean return type in Java);
loop over the positions from the first to the second-last element;
compares each element with the next (adjacent) element;
returns true as soon as two adjacent elements are equal;
returns false after the loop has finished;
Note: Accept a loop from 1 to n − 1 that compares with the previous element. Do not award the bounds mark if the code reads past the end of the list/array.
Example answer (Python):
def has_duplicate_sorted(ids):
for i in range(len(ids) - 1):
if ids[i] == ids[i + 1]:
return True
return FalseExample answer (Java):
public static {
( ; i < ids.length - ; i++) {
(ids[i] == ids[i + ]) {
;
}
}
;
}State the time complexity of your solution to part (e) and outline why it scales better than has_duplicate / hasDuplicate for long playlists.
2 marks
Award [1] for the complexity and [1] for the outline.
;
because equal IDs are next to each other in a sorted list, each element is compared once with its neighbour rather than with every other element, so the work grows linearly instead of with ;
Note: Allow FT from part (e).
A data-compression library contains the function/method tally below.
def tally(n):
count = 0
for i in range(n):
j = 1
while j < n:
j = j * 2
count = count + 1
return countpublic static int tally(int n) {
int count = 0;
for (int i = 0; i < n; i++) {
int j = 1;
while (j < n) {
j = j * 2;
count = count + 1;
}
}
return count;
}State the value returned by tally(8) and by tally(10).
2 marks
Deduce the time complexity of tally, explaining your answer.
3 marks
A weather station takes one wind-speed reading every minute. The function/method analyse prints the mean reading and counts the pairs of readings that differ by more than limit.
def analyse(readings, limit):
total = 0
for r in readings:
total = total + r
print(total / len(readings))
jumps = 0
for i in range(len(readings)):
for j in range(i + 1, len(readings)):
if abs(readings[i] - readings[j]) > limit:
jumps = jumps + 1
print(jumps)public static void analyse(int[] readings, int limit) {
int total = 0;
for (int r : readings) {
total = total + r;
}
System.out.println((double) total / readings.length);
int jumps = 0;
for (int i = 0; i < readings.length; i++) {
for (int j = i + 1; j < readings.length; j++) {
if (Math.abs(readings[i] - readings[j]) > limit) {
jumps = jumps + 1;
}
}
}
System.out.println(jumps);
}State the output when analyse is called with the readings [12, 15, 11, 19, 14] and a limit of 3.
2 marks
State the time complexity of the first loop and of the nested loops.
2 marks
Explain why the overall time complexity of analyse is rather than
Note: Award [1 max] for with no explanation.
2 marks
Analysing one day of data (1440 readings) takes 0.5 seconds. Calculate the approximate time needed to analyse one week of data (10 080 readings).
2 marks
State the space complexity of analyse.
1 mark
The meteorologist decides that only consecutive readings matter.
Construct, in Python or Java, a function/method count_steps / countSteps that takes readings and limit and returns the number of consecutive pairs of readings that differ by more than limit. For example, for [12, 15, 11, 19, 14] and a limit of 3 it returns 3.
4 marks