7.9 Writing and amending algorithms

← Topic 7.8 Identifying errors in algorithmsComputer Science contentsTopic 8.1 Programming concepts →
Chapter 7 · Algorithm design and problem solving

7.9 Writing and amending algorithms

This topic brings the whole chapter together. You need to turn a clearly stated problem into a readable algorithm, choose suitable methods, test it with appropriate data, identify errors and amend the solution until it works correctly.

Problem specificationDecompositionFlowchartsPseudocodeTestingAmending

A structured method for producing an algorithm

The textbook gives a sequence of stages that should be followed when producing an algorithm for a problem. The order matters because a good solution starts with understanding the problem before any pseudocode or flowchart is written.

StageWhat you should do
1Specify the problem clearly. State the purpose of the algorithm and the tasks it must complete.
2Decompose the problem. Break it into smaller sub-problems. Typical parts include setup, input, processing, permanent storage if required, and output.
3Plan the data. Decide how data will be obtained and stored, what processing will happen to it, and how the results will be displayed.
4Design the structure. A structure diagram can show the system and its sub-problems clearly.
5Choose the representation. Construct the algorithm as a flowchart or as pseudocode, unless the question specifies which one to use.
6Write it precisely and readably. Use meaningful identifiers and exact conditions. For example, Counter >= 10 is precise; a vague phrase such as “Counter ten or over” is not suitable pseudocode.
7Test the algorithm. Use suitable normal, abnormal and boundary data. Dry run it and record results in trace tables where appropriate.
8Correct and retest. If testing reveals an error, amend the algorithm and repeat the testing process until the solution behaves as required.
Exam habit: do not jump straight into code. A clear specification, sensible decomposition and planned data handling make the final algorithm easier to construct and easier to test.
Can you put the development stages in context?

Making an algorithm easy to understand

The source revisits the algorithm that selects the largest and smallest values from ten numbers. It shows the same idea using a structure diagram and a more readable flowchart.

Figure 7.18 structure chart for finding maximum and minimum values
Figure 7.18 — Structure chart for Max and Min

The structure chart separates the overall task into entering values, checking all values, checking for the maximum, checking for the minimum, and outputting the results.

Figure 7.19 readable flowchart for maximum and minimum values
Figure 7.19 — A more easily understandable flowchart for Max and Min

The flowchart is more detailed. It reads the first number, stores it as both Highest and Lowest, then reads the remaining values. Each new number is compared with the current highest and lowest. After all ten values have been handled, the two results are output.

Readability matters: meaningful names such as Highest, Lowest and Number make the purpose of the algorithm easier to recognise than single-letter names.

Worked example 1: concert ticket cost

Tickets cost $20 each. Buying 10 or more tickets gives a 10% discount; buying 20 or more gives a 20% discount. A single transaction can contain no more than 25 tickets.

A suitable pseudocode solution first validates the quantity, then selects the correct discount, calculates the final cost and outputs the result:

REPEAT
  OUTPUT "How many tickets would you like to buy?"
  INPUT NumberOfTickets
UNTIL NumberOfTickets > 0 AND NumberOfTickets < 26

IF NumberOfTickets < 10
  THEN
    Discount ← 0
  ELSE
    IF NumberOfTickets < 20
      THEN
        Discount ← 0.1
      ELSE
        Discount ← 0.2
    ENDIF
ENDIF

Cost ← NumberOfTickets * 20 * (1 - Discount)
OUTPUT "Your tickets cost ", Cost

Testing the ticket algorithm

Test valuesWhy they matterExpected result
0, 26Outside the permitted rangeRejected
1, 25Lowest and highest accepted quantities$20 and $400
9, 10Either side of the 10-ticket discount boundary$180 and $180
19, 20Either side of the 20-ticket discount boundary$342 and $320

Notice that the most useful tests are not just random numbers. They deliberately check the permitted limits and the exact points where the discount rule changes.

Test the ticket solution.

Worked example 2: processing school test marks

A school has 600 students and four tests: Maths, Science, English and IT. Each test is marked out of 100. The required output is the highest, lowest and average mark for each subject and also the highest, lowest and average across all four tests.

This problem needs nested loops: the outer loop handles the four subjects and the inner loop handles all 600 students for the current subject. Separate subject totals and limits are reset for each subject, while the overall totals and limits continue across all 2400 marks.

// initialise overall values
OverallHighest ← 0
OverallLowest ← 100
OverallTotal ← 0

FOR Test ← 1 TO 4
  // initialise values for the current subject
  SubjectHighest ← 0
  SubjectLowest ← 100
  SubjectTotal ← 0

  CASE OF Test
    1 : SubjectName ← "Maths"
    2 : SubjectName ← "Science"
    3 : SubjectName ← "English"
    4 : SubjectName ← "IT"
  ENDCASE

  FOR StudentNumber ← 1 TO 600
    REPEAT
      OUTPUT "Enter Student ", StudentNumber,
             " mark for ", SubjectName
      INPUT Mark
    UNTIL Mark < 101 AND Mark > -1

    IF Mark < OverallLowest THEN OverallLowest ← Mark
    IF Mark < SubjectLowest THEN SubjectLowest ← Mark
    IF Mark > OverallHighest THEN OverallHighest ← Mark
    IF Mark > SubjectHighest THEN SubjectHighest ← Mark

    OverallTotal ← OverallTotal + Mark
    SubjectTotal ← SubjectTotal + Mark
  NEXT StudentNumber

  SubjectAverage ← SubjectTotal / 600
  OUTPUT SubjectName
  OUTPUT "Average mark is ", SubjectAverage
  OUTPUT "Highest mark is ", SubjectHighest
  OUTPUT "Lowest mark is ", SubjectLowest
NEXT Test

OverallAverage ← OverallTotal / 2400
OUTPUT "Overall average is ", OverallAverage
OUTPUT "Overall highest mark is ", OverallHighest
OUTPUT "Overall lowest mark is ", OverallLowest

How to test such a large algorithm

Dry running all 2400 inputs would be impractical. The textbook recommends reducing the scale for testing — for example, use 5 students and 2 subjects. The loop limits and average divisors must be changed consistently, then a small set of carefully chosen marks can be traced by hand and the expected results compared with the actual results.

Why comments help: comments such as “initialise overall values” and “inner loop for students” make a long algorithm easier to follow without changing what the algorithm does.
Check your understanding of the nested-loop example.

Choosing loop structures when writing algorithms

The chapter ends its core algorithm-writing practice by asking for two closely related solutions:

TaskSuitable loop ideaReason
Input exactly ten positive numbers, then find the total and average.FOR ... TO ... NEXTThe number of repetitions is known in advance.
Input any number of positive numbers, stopping when the user enters -1.REPEAT ... UNTIL or another condition-controlled loopThe number of values is not known before input begins; a sentinel value ends the sequence.

For the second task, the sentinel -1 tells the algorithm that input has finished. It must not be included in the total or count. The algorithm also needs a counter so that the average can be calculated from Total / Count.

Which loop should you choose?

Extension: Abstract Data Types, stacks and queues

The textbook includes an extension for students considering further study. An Abstract Data Type (ADT) is a collection of data together with a defined set of operations that can be performed on that data.

Two important examples are stacks and queues:

ADTPrincipleAdd operationRemove operation
StackLIFO — Last In, First OutPushPop
QueueFIFO — First In, First OutEnqueueDequeue
Figure 7.20 example stack and queue with pointers
Figure 7.20 — Example stack and queue

Stack pointers and operations

A stack has a Base Pointer and a Top Pointer. In the example, the Base Pointer remains at the base while the Top Pointer changes when items are pushed or popped.

Figure 7.21 stack before and after pop and push operations
Figure 7.21 — Stack operations

A pop removes the item currently at the top. A push adds a new item at the top. Because the last item placed on the stack is the first one removed, a stack follows LIFO.

Queue pointers and operations

A queue uses a Front Pointer and an End Pointer. In the source example, both pointers can change during queue operations.

Figure 7.22 queue before and after dequeue and enqueue operations
Figure 7.22 — Queue operations

A dequeue removes the item at the front. An enqueue adds a new item at the end. The first item added is therefore the first item removed, which is FIFO.

Try the extension concepts.

Topic 7.9 revision checklist

State the main stages used to produce an algorithm from a problem specification.
Break a problem into setup, input, processing, storage and output where appropriate.
Use structure diagrams to show decomposition.
Write algorithms using flowcharts or pseudocode and use meaningful identifiers.
Use precise conditions for selection and loops.
Use normal, abnormal and boundary data to test an algorithm.
Amend an algorithm when testing reveals an error and then retest it.
Explain the Max/Min structure chart and flowchart.
Apply validation and nested selection to the concert-ticket problem.
Understand the nested-loop school-marks example and why its scale can be reduced for a dry run.
Select a suitable loop when the number of repetitions is known or unknown.
Extension: distinguish stack/LIFO/push/pop from queue/FIFO/enqueue/dequeue and explain their pointers.
Ready for a mixed Topic 7.9 check?
← Topic 7.8 Identifying errors in algorithmsComputer Science contentsTopic 8.1 Programming concepts →