1.2 Designing algorithms

This chapter introduces the fundamental concepts of algorithm development. It explains what algorithms are, how sequence, selection, and iteration organize their control flow, and how pseudocode, flowcharts, and decision tables represent them. A sandwich-making example then develops these ideas progressively, beginning with a simple sequence and adding decisions, repetition, and modular structure.

1.2.1 What is an algorithm?

An algorithm is a finite and explicit procedure for completing a task or solving a problem. It receives permitted inputs, follows stated instructions and decisions, and produces outputs that satisfy the problem’s specification. Finite means that the procedure reaches an end after a limited number of steps for every permitted input. Explicit means that its instructions are precise enough for the intended executor, whether a person or a computer, to carry them out.

Algorithms are used in data processing, artificial intelligence, machine learning, and many other fields. They are essential for developing software applications, analyzing data, and solving complex problems. When several algorithms solve the same problem correctly, they can also be compared by the time, memory, or other resources they require.

Figure 1 shows an incomplete algorithm for making a sandwich. Some required actions and decisions are missing, so the intended executor cannot reliably obtain the required result. At the chosen level of detail, every required action and decision must be stated precisely enough for the intended executor to follow it.

Figure 1: An incomplete sandwich-making algorithm. Missing actions and decisions prevent an executor from obtaining a reliable result.

1.2.2 Control structures: sequence, selection, and iteration

Algorithms are designed using common control-flow building blocks. These building blocks form the basis of the structured imperative algorithms used throughout this course: algorithms written as explicit commands organized into clear control-flow structures.

There are three basic building blocks to consider:

  • Sequence carries out instructions1 in a stated order.
  • Selection chooses a path according to the result of a condition. A condition is a question or statement that the algorithm evaluates as true or false.
  • Iteration/Repetition carries out a group of instructions more than once.

There are two types of iteration:

  • Definite iteration (also known as count-controlled iteration) repeats a known number of times or once for every item in a bounded collection.
  • Indefinite iteration (also known as condition-controlled iteration) continues while or until a condition has a stated result.

Structured imperative algorithms use one or more of these constructs. Longer and more complex algorithms may use these constructs repeatedly.

Selection sort

CASE STUDY

Motivation. A sorting algorithm must work for every permitted arrangement of its input values. Selection sort gives a small example of how sequence, selection, and iteration combine in one complete procedure.

Start with the cards [5, 3, 4, 1, 2]. A pass is one complete scan of the remaining cards. The unsorted region contains cards whose final positions are still unknown. Its left edge is the boundary. To swap 2 cards means to exchange their positions.

During the first pass, scan the complete row and remember the smallest value seen so far. The remembered value changes from 5 to 3 and then to 1. Swap 1 with the first card. The row becomes [1, 3, 4, 5, 2], and the first position is complete. Scan only the remaining cards, select 2, and swap it into the second position. Continue until no unsorted positions remain. This is the standard selection-sort strategy of repeatedly placing the least remaining item in its final position (NIST Dictionary of Algorithms and Data Structures).

The design can be stated as a repeated procedure:

  1. scan the unsorted region;
  2. remember the position of its smallest card;
  3. swap that card with the first card in the unsorted region; and
  4. move the boundary of the sorted region one position to the right.

Figure 2 records every pass. The card values are the input. The ordered row is the output. The boundary and remembered minimum are the changing state. The procedure stops after every position has joined the sorted region.

The name selection sort refers to selecting the least remaining item. The procedure uses iteration to scan the unsorted region and conditional selection to update the remembered minimum.

The first pass scans 5, 3, 4, 1, 2 and updates the remembered minimum from 5 to 3 to 1. Curved arrows swap 1 and 5. The result 1, 3, 4, 5, 2 marks the sorted boundary. A table shows the results of the later passes.
Figure 2: Selection sort places the smallest remaining card into the next open position during each pass.
TipTransfer question

What must change in the procedure to sort the same cards from largest to smallest?

1.2.3 Algorithm representation

Pseudocode

Pseudocode is a detailed yet informal description of an algorithm that uses structured natural language to describe the steps involved in solving a problem. Pseudocode is not a programming language; it expresses an algorithm’s logic without requiring the syntax of a particular programming language.

Pseudocode has no universal syntax, so this book uses one consistent convention. A complete listing begins with Input: and Output: to state what the algorithm receives and produces. Start and End mark its boundaries. Indentation shows which instructions belong inside a selection or repetition. Words such as If, While, and Set describe control flow and state changes in plain English; they are not commands from a particular programming language.

NoteHow algorithms are numbered

Algorithms written as pseudocode appear as numbered listings. The first algorithm below is Listing 1, and later listings follow in order.

Listing 1 uses this convention to classify an integer as even or odd. The Input: line states that the algorithm receives an integer called \(n\), and the Output: line states the two permitted results. Between Start and End, If introduces a condition. The indented instruction below the condition applies when the answer is Yes; Else introduces the alternative for a No answer.

Listing 1: Classify an Integer as Even or Odd
Input: Integer n
Output: Classification (Even or Odd)
Start
   If dividing n by 2 leaves no remainder
      Output Even
   Else
      Output Odd
   End If
End

For example, dividing 8 by 2 leaves no remainder, so the algorithm outputs Even. Dividing 7 by 2 leaves a remainder, so the algorithm follows the Else alternative and outputs Odd. The wording is deliberately independent of any programming language.

Flowcharts

A flowchart is a visual tool that represents the steps of a process or algorithm. It uses symbols and arrows to illustrate the flow of control within a procedure. Flowcharts and pseudocode are alternative representations of an algorithm: a flowchart emphasizes visual paths, whereas pseudocode expresses the same logic as structured text.

In a flowchart, the shape of an element signals the kind of information it contains. This chapter uses the following seven elements consistently:

  • Start/End (terminator): Marks where the algorithm begins or ends. It may be drawn as an oval or a rounded rectangle; this book uses rounded rectangles.
  • Input/Output: Shows information entering or leaving the algorithm, using a parallelogram.
  • Process: Contains an action or calculation, using a rectangle.
  • Decision: Contains a condition whose result selects the next path, using a diamond.
  • Flow line: Connects one element directly to the next. Its arrowhead shows the direction of control flow.
  • On-page connector: Shows that flow continues at a matching labeled circle elsewhere on the same page. It can replace a long or crossing flow line.
  • Predefined process (module): Calls a named procedure defined separately, using a rectangle with one vertical line near each side. A procedure is a bounded set of instructions with one specific responsibility.

Figure 3 shows both the conventional shape and a short example for each element. Its panels show the terminator, input/output, process, and decision symbols in Figure 3 (a), Figure 3 (b), Figure 3 (c), and Figure 3 (d). The remaining panels show the flow line, on-page connector, and predefined process in Figure 3 (e), Figure 3 (f), and Figure 3 (g).2

A rounded terminator shape containing Start marks an algorithm boundary.
(a) Terminator: a rounded shape marks where an algorithm starts or ends.
A parallelogram containing Input integer n represents information entering the algorithm.
(b) Input/Output: a parallelogram shows information entering or leaving an algorithm.
A rectangle containing Add 1 to count represents an action or calculation.
(c) Process: a rectangle contains an action or calculation.
A diamond containing Is n even represents a condition that selects the next path.
(d) Decision: a diamond contains a condition whose result selects a path.
A line ending in a right-pointing arrowhead shows the direction from one step to the next.
(e) Flow line: an arrow connects one element directly to the next and shows the direction to follow.
Two circles labeled A show that flow continues between matching locations on the same page.
(f) On-page connector: matching labeled circles continue the same flow elsewhere on one page.
A rectangle with one vertical line near each side contains Validate order and calls a separately defined procedure.
(g) Predefined process or module: a rectangle with internal side lines calls a procedure defined elsewhere.
Figure 3: Seven flowchart elements used in this book. Each panel pairs a conventional symbol with an example and states how to interpret it.

To read a flowchart, begin at Start and follow the arrowheads. At a decision diamond, evaluate its condition and follow the branch labeled with the matching result, such as Yes or No. Continue until you reach End.

The flowchart in Figure 4 represents the same algorithm as the pseudocode in Listing 1. Start at the top, read the integer \(n\), and evaluate the condition in the diamond. A Yes result leads to Output Even; a No result leads to Output Odd. The two paths then meet at End. The arrows show the order in which to visit the elements; they are flow lines, not on-page connectors.

graph TD
    accTitle: Classify an integer as even or odd
    accDescr: Start, input integer n, test whether dividing n by 2 leaves no remainder, output Even on the Yes path or Odd on the No path, and then end.
    Start(("Start")) --> Input[/"Input integer n"/]
    Input --> IsEven{"Does dividing n by 2<br>leave no remainder?"}
    IsEven -- "Yes" --> Even[/"Output Even"/]
    IsEven -- "No" --> Odd[/"Output Odd"/]
    Even --> End(("End"))
    Odd --> End
Figure 4: Flowchart for classifying an integer as even or odd. The condition selects exactly one of two output paths.

An on-page connector becomes useful when a direct return line would be long or would cross other paths. In Figure 5, the No branch requests a correction and enters the lower connector labeled A. Control resumes at the matching A beside the input step, so the algorithm can read the corrected order without drawing a line around the whole diagram. The connector does not perform an action; it only continues an existing path.

graph TD
    accTitle: Order validation with matching on-page connectors
    accDescr: Start, input an order, and test whether it is valid. A valid order is accepted and ends. When the order is invalid, the algorithm requests a correction and enters connector A. Flow resumes at the matching connector A before the input step.
    Start(("Start")) --> Input[/"Input order"/]
    Resume(("A")) --> Input
    Input --> IsValid{"Is the order valid?"}
    IsValid -- "Yes" --> Accept["Accept order"]
    Accept --> End(("End"))
    IsValid -- "No" --> Correct["Request correction"]
    Correct --> Continue(("A"))
Figure 5: Order-validation flowchart using matching on-page connectors to avoid a long return line.
TipUse connectors sparingly

Prefer a direct flow line when it fits without crossing another path. Use an on-page connector only when both matching symbols remain easy to find and the connector removes a long or crossing line. For a responsive web diagram, rearranging the flowchart is often clearer; connectors are most useful in dense layouts and fixed-page print or PDF output.

Decision tables

A decision rule describes one complete case. If all of its conditions hold, the algorithm produces the stated result. A decision table places several rules side by side so their conditions and results can be compared. The layout makes missing, overlapping, and conflicting cases easier to find.

Start with one rule

The pseudocode in Listing 1 and the flowchart in Figure 4 distinguish two cases. If dividing \(n\) by 2 leaves no remainder, the result is Even. If division leaves a remainder, the result is Odd. Table 1 places these two rules side by side.

Table 1: Decision rules that classify any integer as even or odd.
Question or result Each column is one rule. Read downward.
Rule 1 Rule 2
IF: conditions
Does dividing integer n by 2 leave no remainder? Yes No
THEN: result
Classification Even Odd
Every integer matches exactly one of the two rules.

Read Rule 1 downward. Its condition entry is Yes, so its result is Even. The input 8 matches Rule 1. Rule 2 requires No and produces Odd, so the input 7 matches Rule 2.

How to read the book’s tables

Each numbered column is one complete rule. Read the column from the IF: conditions group to the THEN: result group. A condition entry gives the answer required by one rule. The result row gives the outcome when every condition entry in that column matches.

Rule numbers identify columns. They indicate priority only when the policy says so.

NoteTable orientation

This book places rules in columns. Some decision-table systems place rules in rows. In either orientation, one rule connects its complete set of conditions to one result.3

When to use a decision table

Use a decision table when several conditions can interact and you need to compare the result for each combination. Use pseudocode for ordered instructions and a flowchart for paths and loop-backs.

When conditions interact

The next decision is whether a traveler should take an umbrella. Rain matters only when the journey includes time outdoors. Rain and outdoor travel each have 2 permitted answers, so Table 2 contains four rules.

Table 2: Complete umbrella-choice rules for all combinations of rain and outdoor travel.
Question or result Each column is one rule. Read downward.
Rule 1 Rule 2 Rule 3 Rule 4
IF: conditions
Is rain forecast? Yes Yes No No
Will the journey include time outdoors? Yes No Yes No
THEN: result
Umbrella decision Take an umbrella Leave the umbrella behind Leave the umbrella behind Leave the umbrella behind
The four columns contain all four combinations of the two Yes/No conditions.

Rule 1 says that if rain is forecast and the journey includes time outdoors, then take an umbrella. Rule 2 says that if rain is forecast and the journey stays indoors, then leave the umbrella behind. Rules 3 and 4 give the same result when rain is not forecast. For example, No rain and Yes outdoor travel matches Rule 3.

Check coverage

The input domain contains every value or situation permitted by the problem. The umbrella inputs form the pairs (Yes, Yes), (Yes, No), (No, Yes), and (No, No). Each pair appears once in Table 2. The table therefore has no gap and no overlap.

A complete table gives every permitted input at least one matching rule. Non-overlapping rules give every permitted input at most one match. A complete table with a unique hit policy gives every permitted input exactly one match.4

Test a decision table with at least one input for each rule. Include boundary and unusual permitted values. Suitable even-or-odd checks include 8, 7, 0, and a negative integer. 1.3.1 Why algorithms need to be tested shows how expected and observed results turn these checks into test evidence.

A full table for \(n\) Yes/No conditions contains \(2^n\) raw combinations. Constraints can make some combinations impossible. Remove the impossible combinations to obtain the feasible rules.5

Simplify rules with Any

Rules 3 and 4 in Table 2 both produce Leave the umbrella behind. Their only difference is the outdoor condition. Table 3 combines those columns.

Table 3: Minimized umbrella-choice rules after combining the two no-rain cases.
Question or result Each column is one rule. Read downward.
Rule 1 Rule 2 Rule 3
IF: conditions
Is rain forecast? Yes Yes No
Will the journey include time outdoors? Yes No Any
THEN: result
Umbrella decision Take an umbrella Leave the umbrella behind Leave the umbrella behind
Any means either permitted value. It does not mean unknown or missing.

Any means either permitted value for that condition, here Yes or No. It does not mean unknown or missing. Rule 3 in Table 3 expands to (No, Yes) and (No, No). The rule says that if rain is not forecast, then leave the umbrella behind whether outdoor travel is Yes or No. The three columns therefore represent four situations and produce the same results as the complete table.

A library loan requires a valid library card, an available item, and a clear borrower account. The policy reports the first failed prerequisite:

  1. Refuse the loan if the library card is invalid.
  2. Otherwise, refuse the loan if the item is unavailable.
  3. Otherwise, refuse the loan if the borrower account has a problem.
  4. Otherwise, approve the loan.

Table 4 records this priority.

Table 4: Library-loan outcomes under a policy that reports the first failed prerequisite.
Question or result Each column is one rule. Read downward.
Rule 1 Rule 2 Rule 3 Rule 4
IF: conditions
Does the borrower have a valid library card? No Yes Yes Yes
Is the requested item available? Any No Yes Yes
Is the borrower's account clear? Any Any No Yes
THEN: result
Loan outcome Refuse: invalid card Refuse: item unavailable Refuse: account problem Approve the loan
The conditions in each rule encode the policy's first-failure priority.

Rule 1 says that an invalid card produces Refuse: invalid card, regardless of the later conditions. Rule 2 requires a valid card and an unavailable item. Rule 3 requires a valid card, an available item, and an account problem. Rule 4 requires all three prerequisites and approves the loan.

The input (No, No, No) matches Rule 1. The input (Yes, No, No) matches Rule 2. In both rules, each Any entry marks a lower-priority condition that cannot change the result. The conditions in each column encode the priority, so the columns do not need to be evaluated in numerical order.

Rule 1 represents 4 raw combinations, Rule 2 represents 2, and Rules 3 and 4 represent 1 each. The four rules therefore cover \(4 + 2 + 1 + 1 = 8\) raw combinations without overlap.

The examples use a limited-entry decision table, where each condition has a small set of permitted entries.

Build a decision table

Build a decision table in this order:

  1. State the decision, permitted inputs, and required results.
  2. Write the condition questions and their permitted entries.
  3. Create one rule for each feasible combination and assign its result.
  4. Combine equal-result rules with Any only when the combined rule preserves the policy.
  5. Test every rule, then check coverage and overlap.

1.2.4 Example: Sandwich-making algorithm

The following sections develop one peanut butter and jelly sandwich algorithm through five versions. The process begins with a simple sequence and then gains complexity and structure.

The examples use pseudocode for structured steps and flowcharts for paths and loop-backs. Decision tables appear where comparing local rules adds useful information.

Version 1. Making a PB&J sandwich (sequence)

Read the fixed sequence in Listing 2 from its inputs to its output.

Listing 2: Make a PB&J Sandwich
Input: Two Bread Slices, Peanut Butter, Jelly
Output: PB&J Sandwich
Start
   Take 1st bread slice
   Spread peanut butter on it
   Spread jelly on it
   Take 2nd bread slice
   Put 2nd slice on top of the 1st
   Output PB&J Sandwich
End

Figure 6 translates the pseudocode in Listing 2 into a flowchart, preserving the same sequence from inputs to the completed sandwich.

graph TD
    accTitle: PB and J sandwich Version 1 sequence
    accDescr: The flow proceeds from ingredients through spreading peanut butter and jelly, adding the second bread slice, and outputting the sandwich.
    A((Start)) --> B[/Two Bread Slices, Peanut Butter, Jelly/]
    B --> C[Take 1st bread slice]
    C --> D[Spread peanut butter on it]
    D --> E[Spread jelly on it]
    E --> F[Take 2nd bread slice]
    F --> G[Put 2nd slice on top of the 1st]
    G --> H[/PB&J Sandwich/]
    H --> I((End))
Figure 6: Flowchart for making a PB&J sandwich.

Version 1 contains one fixed sequence. The pseudocode states its instructions, and the flowchart shows their order.

Version 2. Toast the bread? (selection)

Listing 2 can be improved by adding a decision point to check if the bread should be toasted before making the sandwich. If the bread is to be toasted, the algorithm will include the toasting step before proceeding to the next steps. Otherwise, the algorithm will skip the toasting step and proceed directly to making the sandwich. Listing 3 shows the resulting selection.

Listing 3: Make a PB&J Sandwich (with Toast Option)
Input: Two Bread Slices, Peanut Butter,
       Jelly, Toast Preference (Yes/No)
Output: PB&J Sandwich
Start
   If Toast Preference is Yes
      Toast the slices of bread
   End If
   Take 1st bread slice
   Spread peanut butter on it
   Spread jelly on it
   Take 2nd bread slice
   Put 2nd slice on top of the 1st
   Output PB&J Sandwich
End

Figure 7 translates Listing 3 into a flowchart and makes the new toasting decision and its two paths explicit.

graph TD
    accTitle: PB and J sandwich Version 2 with optional toasting
    accDescr: A yes or no decision determines whether the bread is toasted before the sandwich-making sequence continues.
    A((Start)) --> B[/Two Bread Slices, Peanut Butter,<br>Jelly, Toast Preference/]
    B --> C{Toast Bread?}
    C -- Yes --> D[Toast the slices of bread]
    C -- No --> E[Take 1st bread slice]
    D --> E
    E --> F[Spread peanut butter on it]
    F --> G[Spread jelly on it]
    G --> H[Take 2nd bread slice]
    H --> I[Put 2nd slice on top of the 1st]
    I --> J[/PB&J Sandwich/]
    J --> K((End))
Figure 7: Flowchart for making a PB&J sandwich with an optional toasting step.

The new decision is whether the algorithm should toast the bread. Toast Preference is restricted to Yes or No, so Table 5 contains 2 complete, non-overlapping rules.

Table 5: Decision rules that determine whether to toast the bread from a Yes/No preference.
Question or result Each column is one rule. Read downward.
Rule 1 Rule 2
IF: conditions
Is Toast Preference Yes? Yes No
THEN: result
Next step Toast both bread slices Continue without toasting
Toast Preference has two permitted values: Yes and No.

Rule 1 says that if Toast Preference is Yes, then toast both bread slices. Rule 2 says that if Toast Preference is No, then continue without toasting. For example, Toast Preference = Yes matches Rule 1. The table gives the local result. The pseudocode and flowchart show where the decision occurs in the full sequence.

Version 3. Keeping an even spread (condition-controlled repetition)

Listing 3 can be improved by adding a decision point to check if the spread is even on the bread slices. While the spread is not even (i.e., the ingredient is distributed unevenly across the bread’s surface), the algorithm will correct it before proceeding to the next step. Therefore, this correction step is condition-controlled, being repeated until the spread is even. The repeating section is called a loop. Each pass through that section is one iteration. This version assumes that each correction improves the spread and that repeated corrections eventually make it even. Without that progress assumption, the repetition might never stop. Listing 4 shows both spread checks and their repeated correction steps.

Listing 4: Make a PB&J Sandwich (with Toast and Even-Spread Repetition)
Input: Two Bread Slices, Peanut Butter, Jelly,
       Toast Preference (Yes/No)
Output: PB&J Sandwich
Start
   If Toast Preference is Yes
      Toast the slices of bread
   End If
   Take 1st bread slice
   Spread peanut butter on it
   While the peanut-butter spread is uneven
      Correct the peanut-butter spread
   End While
   Spread jelly on it
   While the jelly spread is uneven
      Correct the jelly spread
   End While
   Take 2nd bread slice
   Put 2nd slice on top of the 1st
   Output PB&J Sandwich
End

Figure 8 translates Listing 4 into a flowchart and shows how each correction returns to the corresponding evenness check.

graph TD
    accTitle: PB and J sandwich Version 3 with even-spread repetition
    accDescr: Optional toasting is followed by peanut-butter and jelly spreading loops that repeat corrections until each spread is even.
    A((Start)) --> IN[/Two Bread Slices, Peanut Butter,<br>Jelly, Toast Preference/]
    IN --> B{Toast Bread?}
    B -- Yes --> C[Toast the slices of bread]
    B -- No --> D[Take 1st bread slice]
    C --> D
    D --> E[Spread peanut butter on it]
    E --> F{Is the PB<br>spread evenly?}
    F -- No --> G[Correct the peanut<br>butter spread]
    G --> F
    F -- Yes --> H[Spread jelly<br>on it]
    H --> I{Is the jelly<br>spread evenly?}
    I -- No --> J[Correct the<br>jelly spread]
    J --> I
    I -- Yes --> K[Take 2nd bread slice]
    K --> L[Put 2nd slice on top of the 1st]
    L --> OUT[/PB&J Sandwich/]
    OUT --> M((End))
Figure 8: Flowchart for Making a PB&J Sandwich with Toasting Option and Evenly Spread Ingredients. A correction step is repeated until the spread is even.

Version 3 retains the toast decision already shown in Table 5, so it is not repeated. It adds two local spread decisions. Table 6 answers the first question: Should the algorithm correct the peanut-butter spread?

Table 6: Decision rules that determine whether to correct an uneven peanut-butter spread.
Question or result Each column is one rule. Read downward.
Rule 1 Rule 2
IF: conditions
Is the peanut butter spread even? Yes No
THEN: result
Next step Continue to jelly Correct the peanut-butter spread once
The pseudocode and flowchart show the recheck that follows a correction.

Rule 1 says that if the peanut-butter spread is even, then continue to jelly. Rule 2 says that if the spread is uneven, then correct it once. An uneven spread therefore matches Rule 2. The pseudocode and flowchart return from the correction to another evaluation of the condition.

Table 7 answers the second question: Should the algorithm correct the jelly spread? Before reading the result row, predict the result for each condition entry.

Table 7: Decision rules that determine whether to correct an uneven jelly spread.
Question or result Each column is one rule. Read downward.
Rule 1 Rule 2
IF: conditions
Is the jelly spread even? Yes No
THEN: result
Next step Continue to the second bread slice Correct the jelly spread once
The pseudocode and flowchart show the recheck that follows a correction.

Rule 1 says that if the jelly spread is even, then continue to the second bread slice. Rule 2 says that if the jelly spread is uneven, then correct it once. An even jelly spread matches Rule 1. The separate tables show that the peanut-butter and jelly checks occur independently. The loop-backs remain in the pseudocode in Listing 4 and the flowchart in Figure 8.

Version 4. Making multiple sandwiches (definite iteration)

Listing 4 can be further enhanced by introducing definite iteration, allowing the algorithm to create multiple sandwiches based on the user’s input. Instead of making just one sandwich, the algorithm will now repeat the process for the number of sandwiches specified by the user. This involves repeating the operations a fixed number of times, which is known as definite iteration.

In this version, the input will include the number of sandwiches to be made, and the entire sandwich-making process will be repeated until the specified number of sandwiches is created. The algorithm will ensure that each sandwich is made according to the steps in Version 3, including checking if the spread is even and toasting the bread if desired.

For Versions 4 and 5, Bread means a supply containing at least two slices for every requested sandwich, and the supply of peanut butter and jelly is assumed to be sufficient. The progress assumption from Version 3 also continues to apply: each correction must move the spread toward an even result.

Listing 5 adds the sandwich count and its stopping condition to the previous version.

Listing 5: Make Multiple PB&J Sandwiches (with Toast Option and Definite Iteration)
Input: Bread, Peanut Butter, Jelly,
       Toast Preference (Yes/No),
       Number of Sandwiches (non-negative whole number)
Output: Specified Number of PB&J Sandwiches
Start
   Set Sandwich Count to 0
   While Sandwich Count < Number of Sandwiches
      If Toast Preference is Yes
         Toast the slices of bread
      End If
      Take 1st bread slice
      Spread peanut butter on it
      While the peanut-butter spread is uneven
         Correct the peanut-butter spread
      End While
      Spread jelly on it
      While the jelly spread is uneven
         Correct the jelly spread
      End While
      Take 2nd bread slice
      Put 2nd slice on top of the 1st
      Increment Sandwich Count by 1
   End While
   Output PB&J Sandwiches
End

Figure 9 translates Listing 5 into a flowchart and shows the definite iteration that repeats until the requested number of sandwiches is complete.

graph TD
    accTitle: PB and J sandwich Version 4 with definite iteration
    accDescr: The complete sandwich procedure repeats while the sandwich count is lower than the requested non-negative number of sandwiches.
    A((Start)) --> IN[/Bread, Peanut Butter,<br>Jelly, Toast Preference,<br>Number of Sandwiches/]
    IN --> B[Set <b>Sandwich Count</b> to 0]
    B --> C{Is <b>Sandwich Count</b><br>lower than<br><b>Number of Sandwiches</b>?}
    C -- Yes --> D{Toast Bread?}
    D -- Yes --> E[Toast the slices of bread]
    E --> F
    D -- No --> F[Take 1st bread slice]
    F --> G[Spread peanut butter on it]
    G --> H{Is the PB<br>spread evenly?}
    H -- No --> I[Correct the peanut<br>butter spread]
    I --> H
    H -- Yes --> J[Spread jelly<br>on it]
    J --> K{Is the jelly<br>spread evenly?}
    K -- No --> L[Correct the<br>jelly spread]
    L --> K
    K -- Yes --> M[Take 2nd bread slice]
    M --> N[Put 2nd slice on top of the 1st]
    N --> O[Increment <b>Sandwich Count</b> by 1]
    O --> C
    C -- No --> OUT[/PB&J Sandwiches/]
    OUT --> P((End))
Figure 9: Flowchart for Making Multiple PB&J Sandwiches with Toasting Option and Evenly Spread Ingredients. The process is repeated until the desired number of sandwiches is created.

The condition Sandwich Count < Number of Sandwiches controls the repetition. The pseudocode and flowchart show when another sandwich starts, when the count changes, and when the algorithm stops.

Version 5. Refactoring with modular algorithms

Listing 5 can be further refined by refactoring the algorithm into modular components. Refactoring involves restructuring the algorithm without changing its intended behavior to improve readability and maintainability. It does not necessarily improve execution efficiency. We can introduce separate algorithms for spreading an ingredient, making a single sandwich, and making multiple sandwiches. This modular approach allows the same procedure to be reused, simplifies maintenance, and makes the overall algorithm more structured and easier to understand.

A procedure is a named, bounded algorithm with a specific responsibility and explicit inputs and outputs. One procedure can call another and use its output.

In this version, the Spread Ingredient algorithm (Listing 6) is responsible for evenly spreading a given ingredient (e.g., peanut butter, jelly) on a single slice of bread. The Make a Sandwich algorithm (Listing 7) uses the Spread Ingredient algorithm to create a single PB&J sandwich. Finally, the Make Multiple Sandwiches algorithm (Listing 8) calls the Make a Sandwich algorithm repeatedly to create the desired number of sandwiches.

This modular design allows us to focus on specific tasks within the sandwich-making process, making the algorithm more flexible and maintainable. Completed Sandwiches is a collection: one value that groups the sandwiches already produced. The Spread Ingredient procedure uses the same progress assumption as Versions 3 and 4, so repeated corrections eventually stop.

Listing 6: Spread Ingredient
Input: Bread Slice, Ingredient
Output: Bread Slice with Evenly Spread Ingredient
Start
   Apply the ingredient to the bread slice
   While the ingredient is not evenly spread
      Correct the spread
   End While
   Output Bread Slice with Evenly Spread Ingredient
End
Listing 7: Make a Sandwich
Input: Two Bread Slices, Peanut Butter, Jelly,
       Toast Preference (Yes/No)
Output: PB&J Sandwich
Start
   If Toast Preference is Yes
      Toast the slices of bread
   End If
   Take 1st bread slice
   Set 1st bread slice to output of Call "Spread Ingredient"
      with 1st bread slice and Peanut Butter
   Set 1st bread slice to output of Call "Spread Ingredient"
      with 1st bread slice and Jelly
   Take 2nd bread slice
   Place the second slice on top of the first slice
   Output PB&J Sandwich
End
Listing 8: Make Multiple PB&J Sandwiches
Input: Bread, Peanut Butter, Jelly,
       Toast Preference (Yes/No),
       Number of Sandwiches (non-negative whole number)
Output: Specified Number of PB&J Sandwiches
Start
   Set Sandwich Count to 0
   Set Completed Sandwiches to an empty collection
   While Sandwich Count < Number of Sandwiches
      Take Two Bread Slices from Bread
      Set Sandwich to output of Call "Make a Sandwich" with
         Two Bread Slices, Peanut Butter, Jelly, and Toast Preference
      Add Sandwich to Completed Sandwiches
      Increment Sandwich Count by 1
   End While
   Output Completed Sandwiches
End

Figure 10 combines Listing 6, Listing 7, and Listing 8 in one flowchart, making the reusable calls between the three algorithms explicit.

graph TD
    accTitle: Modular PB and J sandwich Version 5
    accDescr: Make Multiple Sandwiches calls Make a Sandwich, which calls Spread Ingredient twice, while completed sandwiches are collected until the requested count is reached.
    A((Start)) --> IN[/Bread, Peanut Butter,<br>Jelly, Toast Preference,<br>Number of Sandwiches/]
    IN --> B[Set <b>Sandwich Count</b> to 0]
    B --> BC[Set <b>Completed Sandwiches</b><br>to an empty collection]
    BC --> C{Is <b>Sandwich Count</b><br>lower than<br><b>Number of Sandwiches</b>?}
    C -- Yes --> TS[Take Two Bread Slices<br>from Bread]
    TS --> J[[Set <b>Sandwich</b> to output of Call<br><b>Make a Sandwich</b> with Two Bread Slices,<br>PB, Jelly, Toast Preference]]
    J --> L[Add <b>Sandwich</b> to<br><b>Completed Sandwiches</b>]
    L --> K[Increment Sandwich Count by 1]
    K --> C
    C -- No --> OUT[/Completed Sandwiches/]
    OUT --> M((End))

    %% Keep the three reusable algorithms stacked vertically. These invisible
    %% links constrain layout only; the algorithm calls above remain the
    %% semantic connections between the modules.
    M ~~~ A1
    MS8 ~~~ A2

    subgraph "Spread Ingredient"
        A2((Start)) --> IN2
        IN2[/Bread Slice, Ingredient/] --> S1
        S1[Apply the ingredient<br>to the bread slice] --> S2{Is the spread even?}
        S2 -- No --> S3[Correct the spread]
        S3 --> S2
        S2 -- Yes --> OUT2[/Bread Slice with<br>Evenly Spread Ingredient/]
        OUT2 --> S4((End))
    end

    subgraph "Make a Sandwich"
        A1((Start)) --> IN1
        IN1[/Two Bread Slices, Peanut Butter,<br>Jelly, Toast Preference/] --> MS1{Toast Bread?}
        MS1 -- Yes --> MS2[Toast the slices<br>of bread]
        MS2 --> MS3[Take 1st bread slice]
        MS1 -- No --> MS3
        MS3 --> MS4[[Set 1st Bread Slice to output of Call<br><b>Spread Ingredient</b> with 1st Bread Slice and PB]]
        MS4 --> MS5[[Set 1st Bread Slice to output of Call<br><b>Spread Ingredient</b> with prepared 1st Bread Slice and Jelly]]
        MS5 --> MS6[Take 2nd bread slice]
        MS6 --> MS7[Put 2nd slice on top of the 1st]
        MS7 --> OUT1[/PB&J Sandwich/]
        OUT1 --> MS8((End))
    end
Figure 10: Modular PB&J sandwich algorithm with optional toasting and reusable spreading.

In the modular version, each decision remains inside the procedure responsible for evaluating it. The listings and Figure 10 show the procedure calls, returns, and repetition.

Algorithms describe procedures independently of a programming language. Their control flow can be organized using sequence, selection, and iteration. A program may implement one or more algorithms while also specifying data, input and output, and interactions with a computing environment.

Module 3 later explains how algorithms are expressed and executed as programs.

Evaluate an algorithm by stating the required result for a chosen input, following the instructions, and comparing the result produced. 1.3.1 Why algorithms need to be tested applies this process to the decisions and repetition introduced in this chapter.

1.2.5 Exercises

1.2.Q1 Choosing an outfit based on weather

Imagine you are getting dressed in the morning, and you decide what to wear (raincoat, jacket, t-shirt) based on the weather (raining, cold, sunny). Write an algorithm that describes this decision-making process.

Listing 9 tests rain before temperature so that each input pair produces one outfit.

Listing 9: Choose an outfit based on the weather.
Input: Raining (Yes/No), Cold (Yes/No)
Output: Outfit (Raincoat, Jacket, or T-shirt)
Start
   If Raining is Yes
      Output Raincoat
   Else If Cold is Yes
      Output Jacket
   Else
      Output T-shirt
   End If
End

Following the pseudocode solution, Figure 11 expresses the same weather decisions as a flowchart.

graph TD
    A((Start)) --> IN[/weather/]
    IN --> B{Is it raining?}
    B -- Yes --> C[/raincoat/]
    B -- No --> D{Is it cold?}
    D -- Yes --> E[/jacket/]
    D -- No --> F[/t-shirt/]
    C --> G((End))
    E --> G
    F --> G
Figure 11: Choosing an outfit based on the weather.

1.2.Q2 Formulate a bottle-filling problem

Write an algorithm for filling a water bottle with cups of water. The algorithm should determine how many cupfuls are needed and explain how to pour the water into the bottle.

Choose the bottle and cup capacities, then create a formulation before writing pseudocode. State:

  1. the inputs and required outputs;
  2. the state that changes while the bottle is being filled;
  3. the rule for each pour, including the final pour; and
  4. the stopping condition and any assumptions needed to prevent overflow and ensure that the algorithm stops.

Use your model to write pseudocode. Give the final number of cupfuls for the capacities you chose.

Decide what happens when the remaining space in the bottle is smaller than the cup capacity.

Many formulations are valid. One model treats the bottle and cup capacities as positive whole-number inputs. Bottle Volume and Cupfuls form the changing state. Each round fills a cup and pours only the amount that still fits. A partly poured final cup counts as one cupful.

Listing 10 gives pseudocode for this model.

Listing 10: Fill a bottle using a learner-defined capacity model.
Input: Bottle Capacity, Cup Capacity
Output: Bottle Volume, Cupfuls
Start
   Set Bottle Volume to 0
   Set Cupfuls to 0
   While Bottle Volume < Bottle Capacity
      Fill the cup with water
      Set Amount to Pour to minimum(Cup Capacity,
         Bottle Capacity - Bottle Volume)
      Pour Amount to Pour into the bottle
      Set Bottle Volume to Bottle Volume + Amount to Pour
      Set Cupfuls to Cupfuls + 1
   End While
   Output Bottle Volume, Cupfuls
End

For example, a 1,000 mL bottle and a 300 mL cup require 4 cupfuls. The final pour adds 100 mL to the bottle.

1.2.Q3 Fill a bottle by iteration

The previous exercise asked you to choose a model. Use the specified values and rules below for this exercise.

Scenario. A 750-milliliter bottle is filled using a 200-milliliter cup. Each round fills the cup, pours only the amount still needed into the bottle, and counts that cupful. Any water left in the final cup remains in the cup.

Inputs. bottle_capacity = 750 mL and cup_capacity = 200 mL.

Rules and notation. Start with bottle_volume = 0 and cupfuls = 0. In each round, pour minimum(cup_capacity, bottle_capacity - bottle_volume) milliliters and then increase cupfuls by 1. Here, minimum(a, b) means the smaller of a and b.

Assumptions. Capacities are positive whole numbers. No water leaks from the bottle. A partly used final cup still counts as one cupful.

Deliverable. Write pseudocode with a stopping condition. State the final values of bottle_volume and cupfuls, and how much water remains in the final cup. The solution includes a round-by-round trace. 1.3.1 Why algorithms need to be tested uses the same problem to show why the choice of test inputs matters.

Success criteria. The algorithm is designed to stop with exactly 750 mL in the bottle, never overfill it, and count four cupfuls.

The final round is different: only 150 mL is still needed.

Listing 11 implements the specified capacities and stopping rule.

Listing 11: Fill a bottle without exceeding its capacity.
Input: Bottle Capacity, Cup Capacity
Output: Bottle Volume, Cupfuls, Water Remaining in Final Cup
Start
   Set Bottle Volume to 0
   Set Cupfuls to 0
   Set Water Remaining in Final Cup to 0
   While Bottle Volume < Bottle Capacity
      Set Amount to Pour to minimum(Cup Capacity,
         Bottle Capacity - Bottle Volume)
      Set Bottle Volume to Bottle Volume + Amount to Pour
      Set Cupfuls to Cupfuls + 1
      Set Water Remaining in Final Cup to Cup Capacity - Amount to Pour
   End While
   Output Bottle Volume, Cupfuls, Water Remaining in Final Cup
End

Table 8 records the state after each pass through Listing 11.

Table 8: Bottle volume and cupful count after each round for a 750 mL bottle and a 200 mL cup.
Round Amount poured (mL) Bottle volume (mL) Cupfuls
start N/A 0 0
1 200 200 1
2 200 400 2
3 200 600 3
4 150 750 4

The final cup contains 50 mL after 150 mL is poured. Because a positive amount is added whenever the bottle is not full, the loop makes progress and reaches its stopping condition.

1.2.Q4 Count rules for three Yes/No conditions

Scenario. A bicycle-sharing service checks three things before unlocking a bicycle:

  • Does the rider have a valid pass? Yes or No
  • Is a bicycle available? Yes or No
  • Is the station open? Yes or No

Every combination of answers is possible. For example, a rider may have a valid pass even when no bicycle is available.

A raw combination contains one answer for every condition. A full decision table begins with one decision rule for each raw combination. How many rules are needed before cases with the same result are combined?

  • 6 rules
  • 8 rules
  • 9 rules
  • 16 rules

Answer: 8 rules.

Count the combinations one condition at a time:

  1. The valid-pass condition has 2 possible answers.

  2. For each of those answers, bicycle availability has 2 possible answers.

  3. For each of those combinations, station status has 2 possible answers.

  4. Multiply the numbers of answers:

    \[ 2 \times 2 \times 2 = 8 \]

The calculation can also be written as \(2^3=8\): two possible answers for each of three conditions.

All 8 raw combinations are feasible cases because the scenario rules out nothing. A full table therefore begins with 8 rules. The results are not given, so the minimum number of rules after equal-result cases are combined is unknown.

1.2.Q5 Count rules when conditions have different numbers of options

Scenario. A parcel desk records three pieces of information for each parcel:

  • Destination: Local, National, or International
  • Delivery speed: Standard or Express
  • Fragile: Yes or No

Every destination can use either delivery speed, and every parcel can be fragile or not fragile.

A raw combination contains one option for every condition. For example, Local, Express, and Yes form one raw combination. A full decision table begins with one decision rule for each raw combination. How many rules are needed before cases with the same result are combined?

  • 7 rules
  • 8 rules
  • 12 rules
  • 24 rules

Answer: 12 rules.

Count the available options for each condition:

  1. Destination has 3 options.

  2. Delivery speed has 2 options.

  3. Fragile status has 2 options.

  4. Choose one option from each condition, so multiply the three numbers:

    \[ 3 \times 2 \times 2 = 12 \]

Multiplying the numbers of options is called the product rule for counting.

All 12 raw combinations are feasible cases because the scenario rules out nothing. A full table therefore begins with 12 rules. The results are not given, so the minimum number of rules after equal-result cases are combined is unknown.

1.2.Q6 Count only the rules allowed by the scenario

Scenario. A cafeteria records a meal category and whether the meal contains meat or dairy. Use the category supplied by the cafeteria; do not try to infer the category from the ingredients.

The cafeteria allows these combinations:

  • A Standard meal may contain meat or not and may contain dairy or not.
  • A Vegetarian meal contains no meat but may contain dairy.
  • A Vegan meal contains neither meat nor dairy.

A raw combination allowed by these requirements is a feasible case. How many feasible cases are there?

  • 4 cases
  • 7 cases
  • 9 cases
  • 12 cases

Answer: 7 feasible cases.

Count the allowed combinations within each meal category:

  1. For Standard, meat has 2 possible answers and dairy has 2 possible answers:

    \[ 2 \times 2 = 4 \]

  2. For Vegetarian, meat must be No, while dairy may be Yes or No:

    \[ 1 \times 2 = 2 \]

  3. For Vegan, both meat and dairy must be No:

    \[ 1 \times 1 = 1 \]

  4. Add the allowed combinations:

    \[ 4 + 2 + 1 = 7 \]

If the category restrictions were ignored, there would be \(3 \times 2 \times 2=12\) raw combinations. Five of those combinations are not allowed, leaving 7 feasible cases. A full decision table begins with one decision rule for each feasible case, so it begins with 7 rules. The results are not given, so the minimum number of rules after equal-result cases are combined is unknown.

1.2.Q7 Convert a color rule into an algorithm

Table 9 defines the result of combining two different colors. Each input is Red, Yellow, or Blue. Input order does not change the result.

Table 9: Results defined by the color-combination rule.
First color Second color Result
Red Yellow Orange
Yellow Blue Green
Blue Red Purple

The algorithm receives color_1 and color_2. Capitalization has already been normalized. A pair is valid when it contains two different listed colors and matches one table row in either order. For a repeated color or any other word, output Invalid combination.

Write pseudocode for the rule. Then give the outputs for (Yellow, Red), (Blue, Yellow), (Red, Red), and (Green, Blue).

Each table row represents two possible input orders.

Listing 12 checks both input orders for each row in Table 9.

Listing 12: Apply the color-combination rule in either input order.
Input: Color 1, Color 2
Output: Combined Color or Invalid combination
Start
   If (Color 1 is Red and Color 2 is Yellow) or
      (Color 1 is Yellow and Color 2 is Red)
      Output Orange
   Else If (Color 1 is Yellow and Color 2 is Blue) or
      (Color 1 is Blue and Color 2 is Yellow)
      Output Green
   Else If (Color 1 is Blue and Color 2 is Red) or
      (Color 1 is Red and Color 2 is Blue)
      Output Purple
   Else
      Output Invalid combination
   End If
End

The requested outputs are Orange, Green, Invalid combination, and Invalid combination. The final Else covers every remaining input.

1.2.Q8 Bulk or cut decision-making

Motivation. In fitness and bodybuilding, deciding whether to bulk (gain muscle) or cut (lose fat) is crucial. This decision is based on several factors, including body fat (BF) percentage, muscle mass (MM), and fitness goals. There are many strategies to help individuals make this decision.

For example, according to “Should You Bulk or Cut?”, the decision-making process involves the following rules:

  1. For Men:
    • Cut if body fat percentage is above 20%.
    • Bulk if body fat percentage is below 15%.
    • If body fat percentage is between 15% and 20%:
      • Bulk if muscle mass is low.
      • Cut if muscle mass is high.
      • Maintain if muscle mass is moderate.
  2. For Women:
    • Cut if body fat percentage is above 30%.
    • Bulk if body fat percentage is below 25%.
    • If body fat percentage is between 25% and 30%:
      • Bulk if muscle mass is low.
      • Cut if muscle mass is high.
      • Maintain if muscle mass is moderate.

Problem. Write an algorithm that uses these guidelines to determine whether an individual should bulk or cut. The algorithm takes a person’s gender, body fat percentage, and muscle mass level (low, high, and moderate) as input and determines whether they should bulk, cut, or maintain.

Example Scenarios:

  1. Input: Male, 22% body fat, moderate muscle mass Output: Cut Explanation: For men, body fat above 20% suggests cutting.

  2. Input: Female, 28% body fat, low muscle mass Output: Bulk Explanation: For women with body fat between 25% and 30%, and low muscle mass, bulking is recommended.

  3. Input: Male, 14% body fat, high muscle mass Output: Bulk Explanation: For men, body fat below 15% suggests bulking.

  4. Input: Female, 32% body fat, high muscle mass Output: Cut Explanation: For women, body fat above 30% suggests cutting.

  5. Input: Male, 16% body fat, moderate muscle mass Output: Maintain Explanation: For men, body fat between 15% and 20% and moderate muscle mass suggest maintaining.

  6. Input: Female, 26% body fat, moderate muscle mass Output: Maintain Explanation: For women, body fat between 25% and 30% and moderate muscle mass suggest maintaining.

Listing 13 applies the stated thresholds separately for men and women.

Listing 13: Choose a bulk, cut, or maintain recommendation.
Input: Gender, Body Fat Percentage, Muscle Mass Level
Output: Recommendation (Bulk, Cut, or Maintain)
Start
   If Gender is Male
      If Body Fat Percentage > 20
         Output Cut
      Else If Body Fat Percentage < 15
         Output Bulk
      Else
         If Muscle Mass Level is Low
            Output Bulk
         Else If Muscle Mass Level is High
            Output Cut
         Else
            Output Maintain
         End If
      End If
   Else
      If Body Fat Percentage > 30
         Output Cut
      Else If Body Fat Percentage < 25
         Output Bulk
      Else
         If Muscle Mass Level is Low
            Output Bulk
         Else If Muscle Mass Level is High
            Output Cut
         Else
            Output Maintain
         End If
      End If
   End If
End

Following the pseudocode solution, Figure 12 expresses the same body-composition decisions as a flowchart.

graph TD
    A((Start)) --> IN[/"<b>gender</b>,<br><b>BF</b> (bodyFatPercentage),<br><b>MM</b> (muscleMassLevel)"/]
    IN --> B{Is<br><b>gender</b><br>`male`?}
    B -->|Yes| C{Is<br><b>BF</b> > 20%?}
    C ---->|Yes| W[/`Cut`/]
    C -->|No| E{Is<br><b>BF</b> < 15%?}
    E ---->|Yes| F[/`Bulk`/]
    E -->|No| H{Is<br><b>MM</b><br>`low`?}
    H ---->|Yes| F
    H -->|No| J{Is<br><b>MM</b><br>`high`?}
    J ---->|Yes| W
    J ---->|No| L[/`Maintain`/]
    B -->|No| O{Is<br><b>BF</b> > 30%?}
    O -->|Yes| W
    O -->|No| Q{Is<br><b>BF</b> < 25%?}
    Q ---->|Yes| F
    Q -->|No| H
    F ----> Z((End))
    L ----> Z
    W ----> Z
    linkStyle 2,3,4,5,6 stroke:blue
    linkStyle 11,12,13,14,15 stroke:magenta
Figure 12: Choosing among bulk, cut, and maintain recommendations.

1.2.Q9 Warehouse operation management

Motivation. A warehouse team uses a traffic-light model to turn two dashboard percentages—occupancy rate and fill rate—into a status and a response. For this exercise, treat both rates as supplied inputs; you do not need to calculate them.

The model categorizes the warehouse’s status into four levels:

  • Green,
  • Orange,
  • Red, and
  • Black.

Evaluate the rows of Table 10 from top to bottom and use the first matching row. This priority rule resolves cases that satisfy more than one condition. Values exactly equal to 85% occupancy or 30% fill do not exceed those thresholds and are therefore Green unless a higher-priority row matches.

Table 10: Ordered traffic-light rules and responses for supplied warehouse occupancy and fill rates.
Scenario Metrics Action to be taken
Black Occupancy rate > 90% AND Fill rate > 35% Refuse deliveries
Red Occupancy rate > 85% AND Fill rate > 30% Review inbound plans daily and reduce inbound volume if needed
Orange Occupancy rate > 85% OR Fill rate > 30% Check the cause and consider moving or consolidating stock
Green Occupancy rate <= 85% AND Fill rate <= 30% No action needed
Note

The Traffic Light Model is used in practice by a large e-commerce company. See details at Beekman, Yorick (2023). Accuracy improvement of warehouse capacity calculation using the bin packing problem.

Problem. Write an algorithm that takes the supplied occupancy rate (OR) and fill rate (FR) as input and returns the first matching traffic-light color from Table 10.

Examples:

  1. Input: Occupancy Rate: 92%, Fill Rate: 36% Output: Black Explanation: Both the occupancy rate and fill rate exceed the thresholds for the Black scenario, indicating the most critical state.

  2. Input: Occupancy Rate: 87%, Fill Rate: 32% Output: Red Explanation: Both the occupancy rate and fill rate exceed the thresholds for the Red scenario, requiring several corrective actions.

  3. Input: Occupancy Rate: 88%, Fill Rate: 28% Output: Orange Explanation: The occupancy rate exceeds 85%, falling into the Orange category, which triggers preventive measures.

  4. Input: Occupancy Rate: 80%, Fill Rate: 25% Output: Green Explanation: Both the occupancy rate and fill rate are within the acceptable range, indicating normal operations with no need for intervention.

  5. Input: Occupancy Rate: 85%, Fill Rate: 30% Output: Green Explanation: Equal values do not satisfy the strict greater-than tests.

Listing 14 applies the four outcomes in priority order, which lets you check that each operating condition receives one color.

Listing 14: Classify supplied warehouse occupancy and fill rates.
Input: Occupancy Rate, Fill Rate
Output: Traffic-Light Color
Start
   If Occupancy Rate > 90% and Fill Rate > 35%
      Output Black
   Else If Occupancy Rate > 85% and Fill Rate > 30%
      Output Red
   Else If Occupancy Rate > 85% or Fill Rate > 30%
      Output Orange
   Else
      Output Green
   End If
End

Following the pseudocode solution, Figure 13 expresses the occupancy- and fill-rate decisions as a flowchart.

graph TD
    accTitle: Warehouse traffic-light classification
    accDescr: The flowchart checks Black, Red, Orange, and Green conditions in priority order for supplied occupancy and fill rates.
    A((Start)) --> IN[/"<b>occupancyRate (OR)</b>, <b>fillRate (FR)</b>"/]
    IN --> B{<b>OR</b> > 90%<br>and<br><b>FR</b> > 35%?}
    B -->|Yes| C[/`Black`/]
    B -->|No| D{<b>OR</b> > 85%<br>and<br><b>FR</b> > 30%?}
    D -->|Yes| E[/`Red`/]
    D -->|No| F{<b>OR</b> > 85%<br>or<br><b>FR</b> > 30%?}
    F -->|Yes| G[/`Orange`/]
    F -->|No| H[/`Green`/]
    C --> I((End))
    E --> I
    G --> I
    H --> I
Figure 13: Classifying warehouse operating conditions.

1.2.Q10 Represent a personal social-media policy

Scenario. A company wants to reduce personal social-media use during working hours without restricting work-related use or use during authorized breaks. An employee uses the policy as a self-check before opening a social-media app.

Inputs. within_working_hours, work_related, and on_authorized_break, each either Yes or No.

Rules and notation. Apply exactly one of these outcomes:

  1. outside working hours, output Policy does not apply;
  2. during working hours, output Continue work-related use when the purpose is work-related;
  3. for personal use during an authorized break, output Personal use allowed during break; and
  4. for personal use during working time outside an authorized break, output Postpone personal use until a break or the end of work.

Assumptions. The three inputs are valid and already known. The procedure does not monitor activity, inspect content, or impose a penalty. It only represents the stated policy as a decision.

Deliverable. Write pseudocode and a complete, non-overlapping decision table. Explain how the table covers all 8 raw combinations of the three Yes/No inputs, even if equivalent combinations are combined using Any.

Success criteria. Every valid input combination matches exactly one rule, work-related use and authorized breaks remain permitted, and the pseudocode and decision table produce the same outcome.

Test whether the policy applies before testing the purpose of the use. Any can combine condition values that do not change an outcome.

Listing 15 tests the policy conditions in an order that assigns one outcome to every permitted input.

Listing 15: Pseudocode for applying the personal social-media policy.
Input: Within Working Hours, Work Related, On Authorized Break
Output: Policy Outcome
Start
   If Within Working Hours is No
      Output Policy does not apply
   Else If Work Related is Yes
      Output Continue work-related use
   Else If On Authorized Break is Yes
      Output Personal use allowed during break
   Else
      Output Postpone personal use until a break or the end of work
   End If
End

The ordered selections first determine whether the policy applies, then separate work-related from personal use, and finally distinguish break time from active working time.

The decision is which policy outcome applies to the three inputs. Table 11 gives the complete set of rules.

Table 11: Complete, non-overlapping rules for applying the personal social-media policy.
Question or result Each column is one rule. Read downward.
Rule 1 Rule 2 Rule 3 Rule 4
IF: conditions
Within working hours? No Yes Yes Yes
Work-related use? Any Yes No No
On an authorized break? Any Any Yes No
THEN: result
Policy outcome Policy does not apply Continue work-related use Personal use allowed during break Postpone personal use until a break or the end of work
The four rules represent 4 + 2 + 1 + 1 = 8 concrete input combinations.

Rule 3 says that if the employee is within working hours, the use is personal, and the employee is on an authorized break, then personal use is allowed during the break. The input (Yes, No, Yes) therefore matches Rule 3.

Any means that either Yes or No matches that condition. It does not mean unknown or missing. Rule 1 uses Any twice because neither purpose nor break status changes the outcome outside working hours. Rule 2 uses Any once because break status does not change the outcome for work-related use.

Rule 1 represents four raw combinations because the other two inputs do not change the outcome outside working hours. Rule 2 represents two combinations because break status does not change work-related use. Rules 3 and 4 each represent one combination. The rules therefore cover \(4 + 2 + 1 + 1 = 8\) combinations, and every valid input matches exactly one rule. The table and pseudocode produce the same policy outcome for all 8 combinations.

1.2.Q11 Design a bounded number-guessing game

Scenario. A classroom game asks a player to guess a hidden whole number from 1 through 100.

Inputs. A valid hidden secret from 1 through 100 and one player entry in each round. The player may make at most seven entries. An entry is valid when it is a whole number from 1 through 100.

Rules and notation. Every entry consumes one round, including an invalid entry. After each entry:

  • output Invalid entry when it is outside the permitted domain;
  • otherwise output Higher when the entry is below the secret;
  • output Lower when the entry is above the secret; or
  • output Correct in n rounds when it equals the secret, where n includes the successful round.

After seven unsuccessful rounds, output No more attempts and stop.

Assumptions. The secret is supplied by the exercise system and is not changed during play. No random-number algorithm is required.

Deliverable. Write modular pseudocode with a visible stopping condition. State the messages for secret 42 and entries 20, 60, 42.

Success criteria. A correct guess is included in the round count, no more than seven entries are read, every entry produces one message, and the stopping condition is explicit.

Increase the round count immediately after reading an entry. The number of rounds remaining then decreases on every iteration.

Listing 16 defines the reusable procedure for evaluating one entry.

Listing 16: Evaluate one entry in the number-guessing game.
Input: Entry, Secret
Output: Result (Invalid entry, Higher, Lower, or Correct)
Start
   If Entry is not a whole number from 1 through 100
      Output Invalid entry
   Else If Entry < Secret
      Output Higher
   Else If Entry > Secret
      Output Lower
   Else
      Output Correct
   End If
End

Listing 17 calls the procedure after every entry and stops after a correct entry or 7 rounds.

Listing 17: Play a bounded number-guessing game.
Input: Secret, Player Entries
Output: Feedback Messages
Start
   Set Rounds Used to 0
   Set Solved to No
   While Rounds Used < 7 and Solved is No
      Read Entry
      Increment Rounds Used by 1
      Set Result to output of Call "Evaluate Guess" with Entry and Secret
      If Result is Correct
         Output Correct in Rounds Used Rounds
         Set Solved to Yes
      Else
         Output Result
      End If
   End While
   If Solved is No
      Output No more attempts
   End If
End

For secret 42, the messages are Higher, Lower, and Correct in 3 rounds. The number of rounds remaining starts at seven and decreases by one after every entry, so the loop performs at most seven iterations.

The flowchart in Figure 14 represents the main procedure. Evaluate Guess applies the entry rules in Listing 16, and the main procedure follows Listing 17.

graph TD
    A(("Start")) --> B[/"Input <b>secret</b>"/]
    B --> C["Set <b>rounds used</b> to 0"]
    C --> D{"Are fewer than 7 rounds used?"}
    D -- "Yes" --> E[/"Input <b>entry</b>"/]
    E --> F["Increase <b>rounds used</b> by 1"]
    F --> G[["Call Evaluate Guess with <b>entry</b> and <b>secret</b>"]]
    G --> H{"Is the result Correct?"}
    H -- "Yes" --> I[/"Output Correct in <b>rounds used</b> rounds"/]
    H -- "No" --> J[/"Output result"/]
    J --> D
    D -- "No" --> K[/"Output No more attempts"/]
    I --> L(("End"))
    K --> L
Figure 14: A bounded number-guessing game that gives feedback and stops after at most seven entries.
NoteNotation used in these exercises

A list is an ordered collection of values. L[i] means the value stored at position i in list L. These exercises number positions from 0, so L[0] is the first value. The length of L is its number of values.

1.2.M1 Pass or fail algorithm

Which of the following correctly represents an algorithm that outputs “Pass” if a student’s score—labeled score—is 50 or above, and “Fail” otherwise? (Note: More than one flowchart may be correct.)

Select the correct flowchart(s) from the options below:

Figure 15 groups the five candidate flowcharts for comparison.

graph LR
    accTitle: Pass-or-fail candidate A
    accDescr: Scores at least 50 follow the Pass branch; lower scores follow the Fail branch.
    A((Start)) --> B[/score/]
    B --> C{"Is score >= 50?"}
    C -- Yes --> D[/Pass/]
    C -- No --> E[/Fail/]
    D --> F((End))
    E --> F
(a) Candidate A passes scores greater than or equal to 50.
graph LR
    accTitle: Pass-or-fail candidate B
    accDescr: Scores greater than 50 follow the Pass branch; a score of exactly 50 follows the Fail branch.
    A((Start)) --> B[/score/]
    B --> C{"Is score > 50?"}
    C -- Yes --> D[/Pass/]
    C -- No --> E[/Fail/]
    D --> F((End))
    E --> F
(b) Candidate B passes only scores greater than 50.
graph LR
    accTitle: Pass-or-fail candidate C
    accDescr: Scores below 50 follow the Fail branch; scores of 50 or more follow the Pass branch.
    A((Start)) --> B[/score/]
    B --> C{"Is score < 50?"}
    C -- Yes --> D[/Fail/]
    C -- No --> E[/Pass/]
    D --> F((End))
    E --> F
(c) Candidate C fails scores below 50 and passes all other scores.
graph LR
    accTitle: Pass-or-fail candidate D
    accDescr: Only a score equal to 50 follows the Pass branch; every other score follows the Fail branch.
    A((Start)) --> B[/score/]
    B --> C{"Is score = 50?"}
    C -- Yes --> D[/Pass/]
    C -- No --> E[/Fail/]
    D --> F((End))
    E --> F
(d) Candidate D passes only a score equal to 50.
graph LR
    accTitle: Pass-or-fail candidate E
    accDescr: Scores at least 50 incorrectly follow the Fail branch, while lower scores follow the Pass branch.
    A((Start)) --> B[/score/]
    B --> C{"Is score >= 50?"}
    C -- No --> D[/Pass/]
    C -- Yes --> E[/Fail/]
    D --> F((End))
    E --> F
(e) Candidate E reverses the branches after testing whether a score is at least 50.
Figure 15: Pass or Fail Algorithm (Question 1.2.M1 Pass or fail algorithm).

Answer: Flowcharts in Figure 15 (a) and Figure 15 (c).

In the pass or fail algorithm, we check if a student’s score is 50 or above to determine if they pass or fail. Or, equivalently, we can check if the score is less than 50 to determine if the student fails. Therefore, options A and C are correct representations of the algorithm.

1.2.M3 Finding the max. value in a list

Which of the following flowcharts correctly represents an algorithm for finding the maximum value—labeled max—in a list L? (Note: More than one flowchart may be correct.)

For example:

  • if L = [1, 2, 3, 4, 5], the algorithm should output 5.
  • if L = [5, 4, 3, 2, 1], the algorithm should output 5.
  • if L = [1, 3, 2, 5, 4], the algorithm should output 5.
  • if L = [5, 6], the algorithm should output 6.

You can consider that the list L:

  • Is non-empty and contains at least two elements.
  • Is indexed starting from 0.

Choose the correct flowchart from the options below:

Figure 17 groups the five candidate flowcharts for comparison.

graph LR
    accTitle: Maximum-value candidate A
    accDescr: The maximum starts at the first list value, the index starts at one, and larger later values replace the maximum.
    A((Start)) --> IN[/L/]
    IN --> B[Set max to<br>first element]
    B --> C[Set i to 1]
    C --> D{"Is i<br>less than<br>L length?"}
    D -- No --> E[/Output max/]
    D -- Yes --> F{"Is L[i]<br>greater<br>than max?"}
    F -- Yes --> G["Set max<br>to L[i]"]
    F -- No --> H[Increment i by 1]
    G --> H
    H --> D
    E --> I((End))
(a) Candidate A starts with the first value as the maximum and compares from the second value onward.
graph LR
    accTitle: Maximum-value candidate B
    accDescr: The maximum starts at the first list value, the index starts at zero, and each larger value replaces the maximum.
    A((Start)) --> IN[/L/]
    IN --> B[Set max to<br>first element]
    B --> C[Set i to 0]
    C --> D{"Is i<br>less than<br>L length?"}
    D -- No --> E[/Output max/]
    D -- Yes --> F{"Is L[i]<br>greater<br>than max?"}
    F -- Yes --> G["Set max<br>to L[i]"]
    F -- No --> H[Increment i by 1]
    G --> H
    H --> D
    E --> I((End))
(b) Candidate B starts with the first value as the maximum and redundantly compares it again.
graph LR
    accTitle: Maximum-value candidate C
    accDescr: The maximum starts at zero and the loop continues while the index is not greater than the list length, which can access a position beyond the list.
    A((Start)) --> IN[/L/]
    IN --> B[Set max to 0]
    B --> C[Set i to 1]
    C --> D{"Is i<br>greater than<br>L length?"}
    D -- Yes --> E[/Output max/]
    D -- No --> F{"Is L[i]<br>greater<br>than max?"}
    F -- Yes --> G["Set max<br>to L[i]"]
    F -- No --> H[Increment i by 1]
    G --> H
    H --> D
    E --> I((End))
(c) Candidate C starts the maximum at zero and uses an unsafe list-boundary test.
graph LR
    accTitle: Maximum-value candidate D
    accDescr: The maximum starts at zero and is replaced when a list value is smaller, so the logic does not find the greatest value.
    A((Start)) --> IN[/L/]
    IN --> B[Set max to 0]
    B --> C[Set i to 0]
    C --> D{"Is i<br>less than<br>L length?"}
    D -- No --> E[/Output max/]
    D -- Yes --> F{"Is L[i]<br>less than<br>max?"}
    F -- Yes --> G["Set max to L[i]"]
    F -- No --> H[Increment i by 1]
    G --> H
    H --> D
    E --> I((End))
(d) Candidate D updates the maximum when a smaller value is found.
graph LR
    accTitle: Maximum-value candidate E
    accDescr: The maximum starts at the first list value but is replaced by smaller values, so it can finish with a value that is not the maximum.
    A((Start)) --> IN[/L/]
    IN --> B[Set max to<br>first element]
    B --> C[Set i to 1]
    C --> D{"Is i<br>equal to<br>L length?"}
    D -- Yes --> E[/Output max/]
    D -- No --> F{"Is L[i]<br>less than<br>max?"}
    F -- Yes --> G["Set max<br>to L[i]"]
    F -- No --> H[Increment i by 1]
    G --> H
    H --> D
    E --> I((End))
(e) Candidate E replaces the maximum when a smaller later value is found.
Figure 17: Finding the Maximum Value in a List (Question 1.2.M3 Finding the max. value in a list).

Answer: Flowchart in Figure 17 (a) and Figure 17 (b).

In the linear search algorithm for finding the maximum value in a list, we iterate through each element of the list and compare it with the current maximum value. If the element is greater than the current maximum, we update the maximum value.

Here’s a step-by-step breakdown of the algorithm using an example list L = [1, 5, 3].

Considering Option A

If we consider the flowchart in option A, i is initialized to 1, and max (i.e., the first element of the list, L[0]) is set as the initial maximum value. Then, in iteration 1, we compare L[1] (i.e., 5) with max=L[0] (i.e., 1) and update max if L[1] is greater.

Use Table 13 to compare step, l, n, and related results for finding the max. value in a list.

Table 13: Trace of maximum-value Algorithm A for L = [1, 5, 3].
Step L n (L Length) i L[i] max i < n? L[i] > max?
1 1,5,3 3 1 5 1 1 < 3? Yes! 5 > 1? Yes!
2 1,5,3 3 2 3 5 2 < 3? Yes! 3 > 5? No!
3 1,5,3 3 3 Not evaluated 5 3 < 3? No! Not evaluated

Considering Option B

If we consider flowchart B, the algorithm starts with i = 0 and max is set to the first element of the list. Then, max is equal to L[i]=L[0]=1.

Notice that the first comparison in this case is redundant (comparing L[0] with max=L[0]), but it doesn’t affect the final result.

Option B therefore performs three loop iterations and four condition checks. Option A avoids the redundant comparison, so it performs two loop iterations and three condition checks.

Table 14 organizes the loop state so you can compare Algorithm B’s redundant first-value check with Algorithm A.

Table 14: Trace of maximum-value Algorithm B for L = [1, 5, 3].
Step L n (L Length) i L[i] max i < n? L[i] > max?
1 1,5,3 3 0 1 1 0 < 3? Yes! 1 > 1? No!
2 1,5,3 3 1 5 1 1 < 3? Yes! 5 > 1? Yes!
3 1,5,3 3 2 3 5 2 < 3? Yes! 3 > 5? No!
4 1,5,3 3 3 Not evaluated 5 3 < 3? No! Not evaluated
TipFurther Analysis
  • Do A and B algorithms work if the list is empty?
  • Do A and B algorithms work if the list has only one element?

1.2.M4 Iterative sum algorithm

Figure 18 represents the iterative sum and shows which values change the accumulator. What will be the output if the input—labeled number—is 4?

graph LR
    accTitle: Iterative sum of even numbers
    accDescr: Starting at one, the algorithm adds even values to the sum, skips odd values, and stops after the supplied number.
    A((Start)) --> B[/number/]
    B --> C[Set sum to 0]
    C --> D[Set i to 1]
    D --> E{"Is i<br>less than or<br>equal to<br>number?"}
    E -- Yes --> F{"Is i<br>an even<br>number?"}
    F -- Yes --> G[Add i<br>to the sum]
    F -- No --> H[Keep sum the same]
    G --> I[Increase i by one]
    E -- No --> J[/sum/]
    H --> I
    I --> E
    J --> K((End))
Figure 18: Flowchart that adds each even whole number from 1 through the supplied number.

Choose the correct output:

  • 4
  • 6
  • 8
  • 10
  • 12

Answer: The output is 6.

In the iterative sum algorithm, we calculate the sum of all even numbers up to a given number. Here’s a step-by-step breakdown of the algorithm using an input of 4:

Use Table 15 to compare iteration, i, i <= 4?, and related results for iterative sum algorithm.

Table 15: Trace of the iterative-sum algorithm for input number = 4.
Iteration i i <= 4? i even? Sum
1 1 Yes No 0
2 2 Yes Yes 2
3 3 Yes No 2
4 4 Yes Yes 6
5 5 No - 6

The table shows the complete trace. Only the even values 2 and 4 change the sum, so the final output is 2 + 4 = 6.

1.2.M5 Algorithm X

Figure 19 represents Algorithm X and makes the loop state visible for tracing. What will be the output if the input—labeled number—is 6?

graph TD
    accTitle: Fibonacci value at a zero-based position
    accDescr: Positions zero and one return directly; later positions repeatedly add the two previous Fibonacci values until reaching the requested position.
    A((Start)) --> B[/number/]
    B --> C{"Is number<br>less than or<br>equal to 1?"}
    C -- Yes --> D[/Return number/]
    C -- No --> E[Initialize<br>a to 0]
    E --> F[Initialize<br>b to 1]
    F --> S[Initialize<br>sum to 0]
    S --> G[Set i to 2]
    G --> H{Is i<br>less than or<br>equal to<br>number?}
    H -- Yes --> I[Set sum to<br>a + b]
    I --> J[Set a to b]
    J --> K[Set b to sum]
    K --> L[Increase i by 1]
    L --> H
    H -- No --> M[/b/]
    D --> N((End))
    M --> N
Figure 19: Flowchart that returns the Fibonacci value at a zero-based position.

Choose the correct output:

  • 5
  • 8
  • 13
  • 21
  • 34

Answer: B) 8

Algorithm X returns the Fibonacci number at position number when positions start at 0: positions 0 and 1 contain 0 and 1. Therefore, position 6 contains 8. Here’s a step-by-step breakdown of the algorithm using an input of 6:

Use Table 16 to compare iteration, number, a, and related results for algorithm x.

Table 16: Trace of Algorithm X for input number = 6.
Iteration number a b i i <= number? sum (a + b) a (updated) b (updated)
1 6 0 1 2 yes 1 1 1
2 6 1 1 3 yes 2 1 2
3 6 1 2 4 yes 3 2 3
4 6 2 3 5 yes 5 3 5
5 6 3 5 6 yes 8 5 8
6 6 5 8 7 no - - -

  1. An instruction states an action for an executor to perform. The executor may be a person or a computer, and a high-level instruction may later be decomposed into more detailed operations.↩︎

  2. ISO 5807:1985 defines symbols and conventions for program and system flowcharts and remains the current confirmed ISO standard. The common names and uses shown here also follow Microsoft’s Basic Flowchart Shapes guidance. Exact drawing styles vary, so a flowchart should use shapes consistently and label every decision branch.↩︎

  3. The conditions-in-rows and rules-in-columns structure follows ISTQB, Certified Tester Foundation Level Syllabus 4.0.1, Section 4.2.3. IBM’s decision-table column guidance shows the alternative rules-in-rows orientation. Camunda’s rule documentation and the Object Management Group’s Decision Model and Notation 1.5 define rules through condition or input entries and result or output entries. Captions, explicit headers, and associated explanations follow the W3C guidance for captions and summaries and the Australian Government Style Manual guidance for tables.↩︎

  4. IBM’s guidance on decision-table errors and warnings distinguishes gaps, where no rule matches, from overlaps, where more than one rule matches.↩︎

  5. ISTQB’s Certified Tester Foundation Level Syllabus 4.0.1, Section 4.2.3 describes a full decision table as covering every combination of condition entries and distinguishes simplification and minimization. The Object Management Group’s Decision Model and Notation 1.5, Section 8 defines a complete table as containing all possible combinations of input values.↩︎