This reading copy is protected. Use the official PDF download for offline access.
FUL BookBank
Browse Materials
Success BlogStudy strategy, exam preparation, academic recovery, fieldwork and career guides.
AchieversStudent excellence stories and academic success interviews.
Computing ₦100.00 PDF download
Download
COS 102
PROBLEM SOLVING
Course Code: COS 102
Course Title: Problem Solving
Published by: Book Bank Team
Material: Book Bank Material

CHAPTER ONE

Introduction to Computing and Problem Solving

Computing is fundamentally concerned with solving problems. Although computers are capable of performing enormous numbers of operations rapidly, the usefulness of a computer depends on the quality of the instructions and methods used to direct those operations. A computer does not independently understand a human problem merely because the problem has been presented to it. The problem must first be understood, represented in an appropriate form, and transformed into a sequence of operations that a computing system can perform.

Consider a university that wants to determine the academic standing of every student at the end of a semester. The available information may include course units, grades, grade points and institutional rules. The task is not simply to "use a computer." Someone must first determine what data are required, how the grade point average will be calculated, what rules determine academic standing, how invalid data will be handled and how the final results will be presented. Only after these issues have been clearly defined can a reliable computer-based solution be developed.

Problem solving therefore comes before programming. Programming is one means of implementing a solution, but a poorly understood problem will usually lead to a poorly designed program. For this reason, the study of problem solving develops ways of thinking that are useful before a student begins writing substantial computer programs.

Central Idea

A computer program is normally the implementation of a solution that has already been conceived and organized. Effective programmers therefore learn to think about the problem before concentrating on programming syntax.

1.2 Meaning of Computing

Definition of Computing

Computing is the study and practice of using computational processes and systems to represent, store, process, communicate and transform information and to solve problems.

Computing is broader than the act of operating a computer. It includes the principles, techniques and technologies involved in designing algorithms, developing software, processing data, constructing computer systems, managing information, communicating through networks and applying computational methods to real-world problems.

For example, when a bank processes a transfer, several computing activities may occur. The system receives transaction data, validates account information, checks relevant conditions, updates stored records, communicates with other systems where necessary and reports the result to the customer. These activities involve data, algorithms, software, hardware, networks and security working together.

1.3 Core Concepts of Computing

Before studying problem solving in detail, it is useful to understand several fundamental ideas that occur repeatedly in computing.

Data:

Data are representations of facts, observations, measurements or symbols that can be stored and processed. Examples include a student's matriculation number, a temperature reading, an examination score and a digital image.

Information:

Information is data that have been processed, organized or interpreted in a way that gives them meaning or usefulness in a particular context.

Data and Information

The values 72, 65, 81, 58 and 74 may be raw examination scores. If they are processed to determine that the average score is 70, the calculated average provides useful information about the group represented by those scores.

Processing:

Processing refers to operations performed on data in order to transform them, analyse them or produce useful results. Examples include sorting names, calculating totals, comparing values and searching a database.

Algorithm:

An algorithm is a finite and well-defined sequence of steps for solving a problem or accomplishing a task. Algorithms will be examined in detail in later chapters because they form a central bridge between problem analysis and programming.

Program:

A program is a set of instructions expressed in a form that can be executed by a computer. A program may implement one or more algorithms.

Input, Processing and Output:

Many elementary computing tasks can be understood using the input-process-output model.

Input → Processing → Output

Input is the data supplied to the system. Processing consists of the operations performed on that data. Output is the information or result produced.

Example: Calculating the Area of a Rectangle

Input: Length = 8 m; Width = 5 m.

Processing: Area = Length × Width = 8 × 5.

Output: Area = 40 m².

Not every computing system can be completely described by a single simple input-process-output sequence. Interactive systems may repeatedly receive input and produce output, while control systems may operate continuously. Nevertheless, the model provides a useful starting point for analysing many introductory problems.

1.4 Meaning of a Problem

Definition of a Problem

A problem is a situation in which there is a difference between a present or given state and a desired state, and a method is required to move from the given state to the desired state.

A problem normally contains something that is known and something that must be determined, achieved or changed. In mathematics, a problem may provide values and ask for an unknown quantity. In business, a problem may involve finding an efficient method of allocating limited resources. In computing, a problem may require the transformation of given data into a specified output.

Simple Example

A lecturer has the scores of 250 students and wants them arranged from the highest score to the lowest. The current state is an unordered collection of scores. The desired state is the same collection arranged in descending order. The problem is to determine and apply a reliable method of obtaining the desired arrangement.

1.5 Problems in Computing

A computing problem is a problem for which computation forms an important part of the solution. Such problems may involve numerical calculation, searching, sorting, decision-making, data transformation, scheduling, simulation, communication or control.

Examples include:

  • calculating students' grade point averages;
  • determining whether a customer has sufficient account balance for a withdrawal;
  • finding a particular record in a database;
  • arranging examination scores in order;
  • determining the shortest or most appropriate route between locations;
  • checking whether login credentials satisfy authentication requirements;
  • calculating an employee's pay from hours worked and applicable rates;
  • determining whether a number is prime;
  • processing registration information;
  • generating reports from stored records.

The important point is that a real-world request must usually be converted into a more precise computational problem before a program can be written.

1.6 Meaning of Problem Solving

Problem Solving

Problem solving is the systematic process of understanding a problem, identifying relevant information and constraints, developing possible solutions, selecting and implementing an appropriate solution, and evaluating whether the solution achieves the required result.

Problem solving is therefore both a thinking process and an action process. It requires reasoning about what is wrong or what is required, followed by the development and evaluation of a solution.

For a simple problem, the solution may be obvious. For a more complex problem, several possible approaches may exist. The problem solver must then compare alternatives and determine which method is suitable under the given conditions.

Illustration

Suppose a department wants to identify the student with the highest examination score. One possible method is to compare every score manually. A computer-based method can instead read the scores one after another, retain the largest value encountered and update that value whenever a higher score is found. Both approaches address the same problem, but the computational approach is more suitable when a large number of records must be processed repeatedly.

1.7 Computational Problem Solving

Computational Problem Solving

Computational problem solving is the process of formulating a problem and developing a solution that can be carried out, wholly or partly, through computational methods.

Computational problem solving requires precision. A human being may understand an instruction such as "give excellent students special recognition" because the surrounding context may explain what "excellent" means. A computer cannot reliably execute such an instruction until the criterion has been stated precisely.

For example, the rule might be defined as:

Making a Rule Precise

If a student's score is greater than or equal to 70, classify the performance as an A grade.

The precise condition can then be represented algorithmically and eventually translated into a programming language.

1.8 Elements of a Computing Problem

Many computing problems become easier to understand when they are broken into identifiable elements.

Inputs:

Inputs are the data required before the problem can be solved.

Outputs:

Outputs are the results that the solution is expected to produce.

Processing Requirements:

These are the operations or transformations that must be performed on the inputs to obtain the outputs.

Constraints:

Constraints are conditions or restrictions that limit acceptable solutions. A constraint may concern time, memory, cost, available data, permitted values, security or rules imposed by the problem.

Conditions:

Some problems require different actions depending on whether particular conditions are true or false.

Example: Simple Withdrawal Problem

Problem: Determine whether a requested withdrawal can be completed.

Input: Available balance and withdrawal amount.

Condition: The withdrawal amount must not exceed the amount available for withdrawal under the stated rules.

Processing: Compare the requested amount with the available amount.

Output: Approve the transaction or report that the transaction cannot proceed.

1.9 From Problem to Solution

A useful introductory view of computational problem solving is:

Understand → Analyse → Design → Implement → Test → Refine

Understand the Problem:

Determine what is actually being requested. Ambiguous terms should be clarified before solution development begins.

Analyse the Problem:

Identify the inputs, required outputs, relationships, rules and constraints.

Design the Solution:

Develop a logical procedure for obtaining the required output. The solution may later be represented using an algorithm, flowchart, pseudocode, decision table or another suitable method.

Implement the Solution:

Translate the designed solution into an operational form. In computing, this frequently involves writing a program.

Test and Evaluate:

Use appropriate test cases to determine whether the solution behaves as expected.

Refine:

Correct defects and improve the solution where necessary. The complete general problem-solving process will be developed more fully in a later chapter.

1.10 Characteristics of Effective Problem Solving

Effective problem solving in computing exhibits several important qualities.

Clarity:

The problem and its requirements should be stated clearly enough to avoid conflicting interpretations.

Correctness:

The proposed solution should produce the required result for the cases it is intended to handle.

Logical Consistency:

The steps of the solution should follow a coherent order without contradiction.

Efficiency:

Where alternatives exist, the use of time, memory and other resources may be considered. Efficiency becomes increasingly important as the size of a problem grows.

Generality:

A useful solution should normally solve the intended class of problems rather than only one example.

Specific Answer versus General Solution

If the task is to calculate the area of any rectangle, writing “8 × 5 = 40” solves only one instance. A general solution accepts a length and width and calculates:

Area = length × width

The same procedure can then be applied to many valid pairs of dimensions.

1.11 Problem-Solving Skills

Problem-solving ability is developed through several complementary intellectual skills.

Analytical Thinking:

Analytical thinking involves breaking a situation into smaller components and examining their relationships.

Logical Reasoning:

Logical reasoning involves drawing conclusions according to valid relationships and stated conditions.

Pattern Recognition:

Recognizing similarities between a new problem and previously solved problems can suggest useful solution strategies.

Abstraction:

Abstraction involves concentrating on the information that is relevant to a problem while temporarily ignoring unnecessary detail.

Decomposition:

Decomposition divides a complex problem into smaller and more manageable subproblems.

Evaluation:

Evaluation involves determining whether a proposed solution satisfies the requirements and identifying weaknesses that require correction.

Example: Student Registration System

Designing an entire student registration system as one undivided task would be difficult. The problem can be decomposed into smaller areas such as account creation, student-data collection, course selection, validation, storage and confirmation. Each component can then be analysed before the complete system is assembled.

1.12 Computers as Tools for Problem Solving

Computers are valuable problem-solving tools because they can execute clearly specified instructions rapidly and consistently. They can process large amounts of data, store information, perform repetitive calculations and communicate results over networks.

Computers are particularly useful when a problem involves:

  • large quantities of data;
  • repeated operations;
  • complex calculations;
  • high-speed processing;
  • accurate storage and retrieval;
  • automation;
  • simulation;
  • communication between systems.

However, the presence of a computer does not automatically make a solution correct. A computer can execute an incorrect algorithm accurately and repeatedly. The quality of the output therefore depends on the quality of the data, rules, algorithm, implementation and testing.

1.13 Human and Computer Roles in Problem Solving

Humans and computers contribute different capabilities to problem solving.

Human Contribution Computer Contribution
Understanding goals and context Executing specified instructions
Defining and interpreting problems Performing calculations rapidly
Choosing relevant assumptions Processing large quantities of data
Designing solution strategies Repeating operations consistently
Evaluating whether results are meaningful Storing and retrieving information
Considering ethical and contextual consequences Automating formally specified procedures

Effective computational problem solving therefore depends on combining human reasoning with computational execution.

1.14 Practical Examples of Computing Problems

Example 1: Average of Three Scores:

Suppose a program must calculate the average of three examination scores.

Problem Analysis

Input: Three scores: 65, 72 and 83.

Required: Their arithmetic mean.

Processing: Add the scores and divide by the number of scores.

Calculation: (65 + 72 + 83) ÷ 3 = 220 ÷ 3 = 73.33 approximately.

Output: Average score = 73.33.

Example 2: Determine Whether a Number Is Even:

A whole number is even if it is divisible by 2 without a remainder.

Problem Analysis

Input: A whole number.

Processing: Determine the remainder when the number is divided by 2.

Decision: If the remainder is 0, the number is even; otherwise, it is odd.

Example: 26 ÷ 2 leaves remainder 0; therefore, 26 is even.

Example 3: Find the Larger of Two Numbers:

Problem Analysis

Input: Two numbers, A and B.

Processing: Compare A with B.

Output: Report A if A > B, report B if B > A, or report that they are equal if A = B.

This example demonstrates an important point: a careful solution must account for equality rather than assuming that one value must always be greater than the other.

Example 4: Calculate a Simple Student Grade:

Suppose a simplified grading rule states:

  • 70–100: A
  • 60–69: B
  • 50–59: C
  • 45–49: D
  • 40–44: E
  • 0–39: F

For an input score of 67, the solution compares the score with the defined ranges. Since 67 lies between 60 and 69 inclusive, the output is B.

This is more complex than a simple calculation because the solution must select an output according to conditions. Later chapters will show how such decisions are represented using algorithms, flowcharts, pseudocode and programming statements.

1.15 Importance of Problem Solving in Computing

Problem solving is central to nearly every area of computing. Software developers solve problems by designing applications. Network professionals solve communication and connectivity problems. Data specialists solve problems involving the organization and interpretation of data. Cybersecurity professionals solve problems involving threats, vulnerabilities and protection. Artificial intelligence specialists develop computational approaches to problems involving prediction, classification, perception and decision support.

For an undergraduate computing student, learning problem solving provides a foundation for programming because it shifts attention from memorizing language syntax to understanding how solutions are constructed.

Chapter Summary
  • Computing involves the use of computational processes and systems to represent, process, store and communicate information and solve problems.
  • A problem exists when a method is required to move from a given state to a desired state.
  • Computing problems often involve transforming specified inputs into required outputs according to defined rules and constraints.
  • Problem solving involves understanding, analysing, designing, implementing, testing and refining solutions.
  • Computational problem solving formulates solutions in ways that can be carried out wholly or partly through computation.
  • Inputs, outputs, processing requirements, conditions and constraints are important elements in the analysis of computing problems.
  • Effective solutions should be clear, logically consistent and correct for the class of problems they are designed to solve.
  • Important problem-solving abilities include analytical thinking, logical reasoning, abstraction, decomposition, pattern recognition and evaluation.
  • Computers execute formally specified procedures rapidly and consistently, but they do not guarantee that the underlying solution is correct.
  • Programming is an implementation activity within the wider process of computational problem solving.

CHAPTER TWO

Problem Identification and Classification

The first major challenge in problem solving is not necessarily finding a solution. It is determining precisely what problem must be solved. A solution to the wrong problem may be technically impressive but practically useless.

In computing, this principle is especially important because computers require precise instructions. If the requirements supplied to a software developer are incomplete or ambiguous, the resulting program may behave exactly as programmed while still failing to satisfy the user's actual need.

Illustration

A school asks a programmer to develop a system that will “show the best student.” Before programming begins, several questions arise. Does “best” mean the highest score in one course, the highest average for a semester, or the highest cumulative grade point average? Should students with incomplete results be considered? What happens if two students have the same value? Until these questions are resolved, the problem has not been defined adequately.

2.2 Problem Identification

Problem Identification

Problem identification is the process of recognizing, describing and establishing the actual issue, need or objective that requires a solution.

Problem identification asks a fundamental question: What exactly needs to be solved?

A reported symptom should not automatically be treated as the underlying problem. For example, users may report that an online application is "too slow." The observed slowness is real, but its cause could be inefficient software, an overloaded server, a slow database query, poor network connectivity, very large files or another factor. Effective problem solving distinguishes the observed effect from the underlying cause where that distinction matters.

Questions Used in Problem Identification:

Useful questions include:

  • What is happening now?
  • What should be happening?
  • Who or what is affected?
  • When does the problem occur?
  • What evidence shows that a problem exists?
  • What result is expected?
  • What conditions must a successful solution satisfy?

2.3 Defining a Problem Correctly

After identifying the general issue, it must be defined with sufficient precision. A useful problem definition establishes the scope and expected outcome without prematurely assuming a particular implementation.

Weak and Improved Problem Definitions
Weak Statement Improved Statement
Calculate students. Calculate each student's weighted grade point average from valid course grades and course units.
Find the biggest number. Given a non-empty collection of numeric values, determine the largest value.
Make registration better. Develop a process that records required student registration data, validates mandatory fields and confirms successful registration.

The improved statements are more useful because they specify what information is involved and what outcome is required.

2.4 The Problem Statement

Problem Statement

A problem statement is a clear and concise description of the problem to be solved, including the required outcome and, where relevant, the important conditions under which the solution must operate.

A good computational problem statement should make it possible to answer questions such as:

  • What data will be provided?
  • What result must be produced?
  • What rules determine that result?
  • What values are valid?
  • Are there exceptional cases?
Example Problem Statement

Given the radius of a circle as a positive real number, calculate and display the area of the circle using the formula A = πr².

This statement identifies the input, establishes a validity condition, specifies the required output and gives the mathematical relationship needed to produce the result.

2.5 Problem Analysis

Problem Analysis

Problem analysis is the systematic examination of a problem in order to determine its inputs, outputs, rules, relationships, constraints, assumptions and special cases before a solution is designed.

Problem analysis answers the question: What must be understood before the solution can be constructed?

For many introductory computational problems, analysis can begin with four questions:

  1. What information is available?
  2. What result is required?
  3. What relationships connect the available information to the required result?
  4. What restrictions or special cases must be considered?

Worked Analysis: Celsius to Fahrenheit Conversion:

Problem Analysis

Problem: Convert a temperature from degrees Celsius to degrees Fahrenheit.

Input: Temperature C in degrees Celsius.

Output: Corresponding temperature F in degrees Fahrenheit.

Relationship: F = (9/5)C + 32.

Example: If C = 30°C:

F = (9/5 × 30) + 32 = 54 + 32 = 86°F.

Required output: 86°F.

Notice that the analysis is performed before any Python or C statement is written. Once the relationship has been understood, implementing it in a programming language becomes comparatively straightforward.

2.6 Identifying Inputs and Outputs

One of the simplest and most useful ways to analyse a computational problem is to identify its inputs and outputs explicitly.

Input:

Input is the data supplied to a solution or system for processing.

Output:

Output is the result produced after processing.

Example: Simple Interest

Suppose the task is to calculate simple interest using:

I = PRT / 100

Inputs: Principal P, annual rate R expressed as a percentage, and time T in years.

Processing: Multiply P, R and T and divide by 100.

Output: Simple interest I.

If P = ₦50,000, R = 8 and T = 2 years:

I = (50,000 × 8 × 2) / 100 = ₦8,000.

Derived Values:

Some values are neither original inputs nor final outputs. They are calculated during processing and used to obtain the final result. Such values may be called intermediate or derived values.

Example

To calculate the average of five scores, the five scores are inputs. Their total is an intermediate value. The average obtained by dividing the total by five is the required output.

2.7 Requirements and Constraints

Requirements:

Requirement

A requirement is a condition, capability or result that a proposed solution is expected to satisfy.

For example, a program designed to process examination scores may be required to accept valid scores, calculate grades and display results.

Constraints:

Constraint

A constraint is a restriction or boundary that limits the values, methods, resources or conditions under which a solution may operate.

Examples of constraints include:

  • a score must lie between 0 and 100;
  • a PIN must contain exactly four digits;
  • a transaction cannot exceed an applicable limit;
  • a system may have limited memory;
  • a result may be required within a specified period;
  • only authorized users may access particular information.

Why Constraints Matter:

Ignoring constraints can produce a solution that works for ideal examples but fails in real use.

Example: Examination Score

If a program simply accepts any numeric value as an examination score, it might accept 135 or -20. If the valid score range is 0 to 100 inclusive, the solution should recognize values outside this range as invalid rather than assigning them ordinary grades.

2.8 Assumptions in Problem Solving

Assumption

An assumption is a condition accepted as true for the purpose of analysing or solving a problem when that condition has not been established directly by the problem statement.

Assumptions are sometimes necessary, but they should be reasonable and explicit. Hidden assumptions can cause errors.

Example

If a problem says, “Find the average age of the students,” a solver should not silently assume that the list is non-empty if the program may receive no student records. The empty case matters because dividing a total by zero students is not a valid average calculation.

Good problem analysis therefore distinguishes facts supplied by the problem from assumptions introduced by the solver.

2.9 Problem Decomposition

Problem Decomposition

Problem decomposition is the process of dividing a complex problem into smaller, more manageable subproblems that can be understood and solved separately before being combined.

Large computing systems are rarely designed as one indivisible task. Breaking them into components reduces complexity and makes analysis, implementation and testing more manageable.

Example: Library Management Problem

A library-management system may initially appear to be one problem. It can instead be decomposed into smaller problems such as:

  • registering library users;
  • adding books to the catalogue;
  • searching for books;
  • recording borrowed books;
  • recording returned books;
  • determining overdue items;
  • generating reports.

Each subproblem can be analysed individually while remaining part of the overall system.

2.10 Types of Problems

Problems can be classified in several ways. In this course, an especially important distinction is between routine and non-routine problems. Another useful distinction is between well-defined and ill-defined problems.

These classifications are not absolute descriptions of difficulty. A problem that is routine for an experienced programmer may be non-routine for a beginner because the experienced programmer already knows an established method.

2.11 Routine Problems

Routine Problem

A routine problem is a problem for which the solver already knows, or can directly apply, an established method or procedure for obtaining the solution.

Routine problems usually involve familiar structures and known solution methods.

Examples:

  • calculating the area of a rectangle when length and width are known;
  • converting Celsius temperature to Fahrenheit using a given formula;
  • calculating the average of a known collection of scores;
  • calculating simple interest from principal, rate and time;
  • determining whether a number is divisible by another number.
Routine Problem Example

Problem: Find the area of a rectangle with length 12 cm and width 7 cm.

Known rule: Area = length × width.

Application: Area = 12 × 7 = 84 cm².

The problem is routine because a standard formula can be applied directly once the required values are known.

2.12 Non-Routine Problems

Non-Routine Problem

A non-routine problem is a problem for which an immediately applicable solution procedure is not already apparent to the solver, requiring exploration, reasoning, adaptation or development of a strategy.

Non-routine problems require more than substituting values into a familiar formula. The solver may need to discover relationships, combine several techniques, compare alternative approaches or reformulate the problem.

Example

A university wants to produce an examination timetable for hundreds of courses while ensuring that students taking common courses do not have clashes, available halls are not exceeded, appropriate time periods are used and several institutional restrictions are satisfied. There is no single arithmetic formula into which the university can simply substitute values. The problem requires modelling, constraints and a suitable solution strategy.

Routine and Non-Routine Problems Compared:

Routine Problems Non-Routine Problems
A familiar procedure is available to the solver. A direct procedure may not initially be apparent.
Often solved by applying known rules or methods. Often requires exploration and strategy development.
The structure is usually familiar. The structure may be unfamiliar or complex.
May require relatively little adaptation. May require combining or adapting several techniques.
Example: computing simple interest from a known formula. Example: designing a timetable under numerous interacting constraints.

2.13 Well-Defined and Ill-Defined Problems

Well-Defined Problems:

Well-Defined Problem

A well-defined problem has a sufficiently clear initial situation, objective, relevant conditions and criteria for determining whether a proposed solution is acceptable.

Example

Given three integers A, B and C, determine and display the largest value. If two or more values are equal and jointly largest, display that largest value.

The inputs and required output are clear, and a proposed answer can be tested objectively.

Ill-Defined Problems:

Ill-Defined Problem

An ill-defined problem is one in which the goals, relevant information, constraints or criteria for an acceptable solution are incomplete, ambiguous or open to interpretation.

Example

“Create the best university website” is ill-defined. What does “best” mean? Fastest? Most accessible? Most visually attractive? Most secure? Most informative? Without clearer criteria, different developers may solve substantially different problems.

Many real-world problems begin in an ill-defined form. Part of the problem-solving process is to investigate the situation and convert the vague request into sufficiently clear requirements.

2.14 Computational and Non-Computational Aspects of Problems

Not every part of a real-world problem should necessarily be solved by a computer. Some parts involve human judgement, policy, ethics, negotiation or contextual understanding.

Example: Scholarship Selection

A computer system can calculate applicants' scores, check whether documents are complete and rank candidates according to explicitly stated criteria. However, if the scholarship rules require consideration of exceptional circumstances that cannot be reduced to predetermined data and rules, human review may still be necessary.

An effective problem solver therefore asks not only, “Can this be computerized?” but also, “Which parts should be automated, and which require human responsibility or judgement?”

2.15 Recognizing Patterns in Problems

Pattern recognition involves identifying similarities, repetitions or structures that connect a new problem with other problems.

Suppose a student has already learned how to determine the largest of two numbers. The problem of determining the largest of three numbers has a related structure: values must still be compared according to their magnitude. Recognizing this relationship can help the student develop the new solution.

Pattern Example

Problems such as determining whether a student passed, checking whether a customer is eligible for a discount, and deciding whether a user is old enough to access a service all share a general pattern: test a condition and select an action according to the result.

Recognizing such patterns is important because computing frequently involves reusing general solution ideas in new contexts.

2.16 Selecting Relevant Information

A problem description may contain information that is not required for the particular result being calculated. Effective analysis separates relevant data from irrelevant detail.

Example

Suppose a problem states that a student named Ada is 19 years old, lives in Abuja, studies Computer Science, scored 72 in a test and 68 in an examination, and the task is to calculate the student's total score from the test and examination.

For this particular calculation, the relevant numerical values are 72 and 68. The student's age and place of residence do not affect the required total.

Total = 72 + 68 = 140.

This does not mean the other information is useless in every context. It means it is not relevant to the specific problem currently being solved.

2.17 Developing Test Cases from the Problem Definition

A well-defined problem should provide enough information to begin thinking about how a future solution will be tested. A test case consists of selected input conditions together with the behaviour or output expected from the solution.

Test cases should not contain only ordinary values. Boundary and exceptional conditions may reveal weaknesses that normal examples do not expose.

Example: Score Classification

Suppose valid scores range from 0 to 100 and a score of 40 or above is considered a pass.

Input Reason for Test Expected Result
75 Normal passing value Pass
25 Normal failing value Fail
40 Exact pass boundary Pass
39 Immediately below pass boundary Fail
0 Lowest valid score Fail
100 Highest valid score Pass
-5 Below valid range Invalid score
105 Above valid range Invalid score

Thinking about test cases during analysis often exposes missing requirements. If the problem statement does not say what should happen when a score is outside the valid range, the analyst has discovered an ambiguity that should be resolved before implementation.

2.18 Applied Problem Analysis

The following examples combine the ideas developed throughout the chapter.

Example 1: Calculate a Student's Total and Average:

Analysis

Problem: Given four course scores, calculate the total and arithmetic mean.

Inputs: S1, S2, S3 and S4.

Outputs: Total and average.

Processing:

Total = S1 + S2 + S3 + S4

Average = Total ÷ 4

Example values: 64, 75, 81 and 60.

Total = 64 + 75 + 81 + 60 = 280.

Average = 280 ÷ 4 = 70.

Expected output: Total = 280; Average = 70.

Example 2: Determine Admission Eligibility:

Suppose, purely for this example, that an institution defines eligibility for a particular process as a score of at least 50.

Analysis

Input: Candidate's score.

Constraint: Score must be between 0 and 100 inclusive.

Decision rule: If score ≥ 50, report “Eligible”; otherwise report “Not Eligible.”

Special case: A score outside 0–100 should be treated as invalid.

Test 1: Score = 68 → Eligible.

Test 2: Score = 49 → Not Eligible.

Test 3: Score = 110 → Invalid score.

Example 3: Find the Smallest of Three Values:

Analysis

Inputs: Three numeric values A, B and C.

Required output: The smallest value.

Relevant operation: Comparison.

Example: A = 18, B = 7, C = 12.

Compare the values. Since 7 is less than both 18 and 12, the required output is 7.

Example 4: Automated Teller Machine Withdrawal:

More Detailed Problem Analysis

Consider a simplified ATM withdrawal problem. A customer requests a withdrawal of ₦20,000.

Possible inputs: Account identifier, requested amount, authentication information and available balance.

Possible requirements: Authenticate the user, validate the amount, determine whether sufficient funds are available, apply relevant transaction rules and report the outcome.

Possible constraints: Daily withdrawal limit, available account balance, permitted withdrawal denominations and security rules.

Outputs: Transaction approval or an appropriate rejection result; if approved, the account record must be updated consistently with the transaction.

This example demonstrates why real computing problems require careful analysis. A simplistic rule such as “if balance is greater than the withdrawal amount, give cash” ignores authentication, equality at the boundary, applicable limits, transaction charges where relevant, permitted denominations and other operational requirements.

The purpose of problem analysis is therefore not to make simple tasks unnecessarily complicated. It is to identify the details that genuinely determine whether a solution will work correctly.

Chapter Summary
  • Problem identification determines the actual issue, need or objective that requires a solution.
  • A reported symptom may be different from the underlying cause of a problem.
  • A problem statement should describe the required outcome and relevant conditions clearly enough to guide solution development.
  • Problem analysis identifies inputs, outputs, relationships, requirements, constraints, assumptions and special cases.
  • Inputs are data supplied for processing, while outputs are the results expected from the solution.
  • Requirements describe what a solution must provide, whereas constraints establish boundaries or restrictions within which it must operate.
  • Assumptions should be reasonable and made explicit when they affect the solution.
  • Problem decomposition divides a complex problem into smaller and more manageable subproblems.
  • Routine problems have familiar procedures that can be applied directly, while non-routine problems require greater exploration and strategy development.
  • A well-defined problem has sufficiently clear goals, conditions and criteria for evaluating a solution; an ill-defined problem contains important ambiguity or incompleteness.
  • Not every aspect of a real-world problem necessarily requires automation; some aspects may require human judgement or responsibility.
  • Pattern recognition helps problem solvers transfer useful structures and methods from familiar problems to new ones.
  • Effective analysis distinguishes information relevant to the required result from details that do not affect that result.
  • Test cases can be derived from problem requirements and should include normal, boundary and invalid conditions where appropriate.
  • Careful problem identification and analysis reduce the likelihood of designing a technically correct solution to the wrong problem.

CHAPTER THREE

Algorithms and Algorithm Development

Once a problem has been clearly identified and analysed, the next task is to develop a method for solving it. In computing, this method is commonly expressed as an algorithm.

An algorithm is one of the most important ideas in computing because it provides the logical structure of a solution before that solution is translated into a programming language. Programming languages may differ in syntax, but the underlying problem-solving logic can often be represented independently of any particular language.

Simple Illustration

Suppose a student wants to calculate the average of three scores. The essential solution is not tied to Python, C or any other language. The logical method is simply to obtain the three scores, add them, divide the total by three, and report the result.

3.2 Meaning of an Algorithm

Algorithm

An algorithm is a finite, ordered and unambiguous sequence of effective steps for solving a problem or performing a specified task.

Several ideas in this definition are important. The steps must be arranged in a meaningful order, each step must be sufficiently clear, the procedure must eventually stop, and the steps must be capable of being carried out.

An algorithm does not have to be written in a programming language. It may be expressed in ordinary structured language, pseudocode, a flowchart or another precise representation.

3.3 Why Algorithms Are Important

Algorithms are important because they separate problem-solving logic from programming syntax. This allows the problem solver to concentrate on the structure of the solution before dealing with the detailed rules of a programming language.

Algorithms also help to:

  • clarify the logic of a solution;
  • detect missing steps before implementation;
  • communicate a solution to other people;
  • support testing and verification;
  • make translation into different programming languages easier;
  • compare alternative solution methods.
Key Principle

A strong algorithm usually makes programming easier. A weak algorithm often produces a program that is difficult to understand, test or maintain.

3.4 Characteristics of a Good Algorithm

A useful algorithm should possess certain important characteristics.

Definiteness:

Each step should be stated clearly enough that its meaning is not ambiguous.

Finiteness:

The algorithm should terminate after a finite number of steps for every valid input for which it is intended to produce a result.

Effectiveness:

Each step should be sufficiently basic and practical that it can actually be carried out.

Input:

An algorithm may receive zero or more input values depending on the problem.

Output:

An algorithm should produce at least one meaningful result for the problem it solves.

Correctness:

The algorithm should produce the required result for all valid cases within the problem definition.

Generality:

Where appropriate, an algorithm should solve a class of problems rather than only one specific numerical example.

Property Meaning
Definiteness Each step has a clear and unambiguous meaning.
Finiteness The procedure eventually terminates.
Effectiveness Each step can be carried out in practice.
Correctness The procedure gives the required result for valid cases.
Generality The method applies to a useful class of inputs.

3.5 Inputs and Outputs in Algorithms

Inputs are values supplied to the algorithm, while outputs are the values or messages produced after processing.

Example: Rectangle Area

Inputs: Length and width.

Processing: Multiply length by width.

Output: Area.

START READ length READ width area = length × width DISPLAY area STOP

If the inputs are 8 and 5, the output is 40.

3.6 Finiteness and Definiteness

Finiteness requires an algorithm to stop after a limited number of operations. An algorithm that continues indefinitely without reaching a result does not satisfy this property for the intended problem.

Definiteness requires every instruction to be stated precisely.

Ambiguous and Definite Instructions

Ambiguous: “Add enough to make the value large.”

Definite: “Add 10 to the current value.”

A computer requires the second form because it specifies exactly what operation should occur.

3.7 Effectiveness and Correctness

An algorithm should contain operations that can actually be performed. For example, “determine instantly whether any arbitrary computer program will eventually stop for every possible input” is not a practical elementary step.

Correctness means that the algorithm gives the right result according to the problem specification.

Correctness Example

Suppose an algorithm is meant to determine the largest of two numbers. If it checks only whether A > B and otherwise reports B, it still works when A = B if the required output is simply the largest value. But if the problem specifically requires a message when the values are equal, the algorithm is incomplete because it does not satisfy the specification.

3.8 Generality of Algorithms

A useful algorithm should normally solve the general form of a problem.

Specific Calculation and General Algorithm

Specific calculation: 7 × 4 = 28.

General method: Read length and width, then calculate area = length × width.

The second form can solve many rectangle-area problems, not only one particular instance.

3.9 Steps in Algorithm Development

Algorithm development should follow the earlier stages of problem analysis.

  1. Understand the problem.
  2. Identify required inputs.
  3. Identify required outputs.
  4. Identify the relationships and conditions involved.
  5. Break the solution into logical steps.
  6. Arrange the steps in the correct order.
  7. Test the steps using representative values.
  8. Refine the algorithm if necessary.
Example: Celsius to Fahrenheit

Problem: Convert Celsius temperature to Fahrenheit.

Input: Celsius temperature C.

Output: Fahrenheit temperature F.

Relationship: F = (9/5)C + 32.

START READ C F = (9/5) × C + 32 DISPLAY F STOP

If C = 20, then F = 68.

3.10 Sequence in Algorithms

Sequence

Sequence is the execution of algorithmic steps one after another in a specified order.

Many simple problems consist entirely of sequence.

Example: Total Cost

A customer buys 6 books at ₦2,500 each.

START READ quantity READ unit_price total = quantity × unit_price DISPLAY total STOP

For quantity = 6 and unit price = 2500:

Total = 6 × 2500 = ₦15,000.

3.11 Selection in Algorithms

Selection

Selection is an algorithmic control structure in which one of two or more possible actions is chosen according to whether specified conditions are satisfied.

Selection is required whenever the solution depends on a decision.

Example: Pass or Fail

Suppose a score of 40 or above is classified as a pass.

START READ score IF score >= 40 THEN DISPLAY "Pass" ELSE DISPLAY "Fail" END IF STOP

For score = 65, the algorithm displays “Pass.” For score = 32, it displays “Fail.”

Multiple Selection:

Some problems require more than two alternatives.

Example: Grade Classification
START READ score IF score >= 70 THEN DISPLAY "A" ELSE IF score >= 60 THEN DISPLAY "B" ELSE IF score >= 50 THEN DISPLAY "C" ELSE IF score >= 45 THEN DISPLAY "D" ELSE IF score >= 40 THEN DISPLAY "E" ELSE DISPLAY "F" END IF STOP

The conditions are checked from the highest range downward. Once a condition is satisfied, the corresponding grade is selected.

3.12 Repetition in Algorithms

Repetition

Repetition, also called iteration or looping, is the repeated execution of one or more steps while a stated condition or count requires repetition.

Repetition avoids writing the same instruction many times.

Example

Suppose the numbers 1 to 5 must be displayed.

START count = 1 WHILE count <= 5 DISPLAY count count = count + 1 END WHILE STOP

The output is:

1, 2, 3, 4, 5

3.13 Algorithm Tracing

Algorithm Tracing

Algorithm tracing is the systematic examination of an algorithm step by step using selected input values in order to determine how variables and outputs change during execution.

Tracing helps the problem solver test logic before implementation.

Trace Example
START READ A READ B total = A + B double_total = total × 2 DISPLAY double_total STOP

Let A = 4 and B = 7.

Step A B total double_total
Read values 4 7 — —
total = A + B 4 7 11 —
double_total = total × 2 4 7 11 22

The final output is 22.

3.14 Algorithms for Arithmetic Problems

Arithmetic algorithms are common introductory examples because the relationships are often clear and easy to verify.

Example: Simple Interest:

START READ principal READ rate READ time interest = (principal × rate × time) / 100 DISPLAY interest STOP

If principal = ₦60,000, rate = 5 and time = 3 years:

Interest = (60,000 × 5 × 3) / 100 = ₦9,000.

Example: Average of Four Numbers:

START READ A READ B READ C READ D total = A + B + C + D average = total / 4 DISPLAY average STOP

For 50, 60, 70 and 80:

Total = 260 and average = 65.

3.15 Algorithms for Decision Problems

Decision problems require conditions.

Example: Even or Odd Number:

START READ number IF number MOD 2 = 0 THEN DISPLAY "Even" ELSE DISPLAY "Odd" END IF STOP

The MOD operation returns the remainder after integer division. If the remainder after division by 2 is zero, the number is even.

Example: Larger of Two Values:

START READ A READ B IF A > B THEN DISPLAY A ELSE IF B > A THEN DISPLAY B ELSE DISPLAY "Equal" END IF STOP

3.16 Algorithms for Repetitive Problems

Some tasks involve repeated accumulation or processing.

Example: Sum of the Numbers 1 to 5:

START sum = 0 count = 1 WHILE count <= 5 sum = sum + count count = count + 1 END WHILE DISPLAY sum STOP

The successive values of sum are:

1, 3, 6, 10 and 15.

Therefore, the final output is 15.

Generalizing the Problem:

A more general version can read a positive integer N and calculate:

1 + 2 + 3 + ... + N

START READ N sum = 0 count = 1 WHILE count <= N sum = sum + count count = count + 1 END WHILE DISPLAY sum STOP

3.17 Evaluating an Algorithm

Before implementation, an algorithm should be evaluated against the problem requirements.

Useful questions include:

  • Does it produce the correct result for normal inputs?
  • Does it handle boundary conditions correctly?
  • Does it handle invalid inputs where required?
  • Does it eventually terminate?
  • Are all steps clear?
  • Are required outputs actually produced?
  • Is the method unnecessarily complicated?
Evaluation Example

If an algorithm classifies a valid examination score but does not reject values below 0 or above 100 even though the problem specification requires validation, the algorithm is incomplete. Algorithm evaluation compares the solution with the complete specification, not merely with a few convenient examples.

3.18 Algorithm Efficiency at Introductory Level

Two correct algorithms may require different amounts of computational work. The study of how resource requirements grow with problem size is an important area of computer science.

At introductory level, efficiency can be understood by comparing unnecessary and necessary work.

Example

Suppose a list is already arranged in ascending order and the largest element is known to be the last item. Examining every element again to find the largest may be unnecessary if the ordering is guaranteed. Understanding the properties of the data can therefore influence the design of an efficient solution.

Efficiency should not be confused with correctness. A fast algorithm that gives the wrong result is not a useful solution.

3.19 From Algorithm to Program

An algorithm expresses the logical method of solving a problem. A program expresses that method using the rules of a programming language.

Algorithm and Program
Algorithm Program
Describes the logic of a solution. Implements the logic in a programming language.
Usually language-independent. Follows the syntax of a specific language.
Used for planning and reasoning. Executed by a computer through the relevant language environment.
Algorithm
START READ number square = number × number DISPLAY square STOP

This same algorithm can later be implemented in Python, C or another programming language without changing its essential logic.

Chapter Summary
  • An algorithm is a finite, ordered and unambiguous sequence of steps for solving a problem.
  • Algorithms separate solution logic from the syntax of programming languages.
  • Important properties of algorithms include definiteness, finiteness, effectiveness, correctness and generality.
  • Algorithms may contain sequence, selection and repetition.
  • Sequence executes instructions in order.
  • Selection chooses among alternatives according to conditions.
  • Repetition executes steps repeatedly while a condition or count requires it.
  • Algorithm tracing helps verify the behaviour of a proposed solution before programming.
  • Algorithms should be evaluated using normal, boundary and exceptional cases where relevant.
  • Efficiency concerns the resources required by a solution, but correctness remains essential.
  • A program is an implementation of an algorithm in a specific programming language.

CHAPTER FOUR

Heuristics, Solvable and Unsolvable Problems

Not every problem has an obvious step-by-step solution. Some problems are too complex for a simple direct method, while others have exact algorithms that become impractical when the amount of data becomes very large. There are also problems for which no algorithm can solve every possible instance.

These facts lead to two important ideas in problem solving: heuristics and solvability. A heuristic provides a practical strategy for finding a useful solution when an exact method is difficult, expensive or unnecessary. Solvability concerns whether a problem can, in principle, be solved by an algorithm under the stated conditions.

4.2 Meaning of a Heuristic

Heuristic

A heuristic is a practical problem-solving strategy or guiding rule used to search for a satisfactory solution when an exact method is unavailable, too costly or unnecessary.

A heuristic does not necessarily guarantee the best possible solution. Instead, it is intended to guide the search toward a useful answer efficiently.

Everyday Example

A person looking for a misplaced item may begin by searching the places where the item is usually kept. This strategy does not guarantee success, but it is a sensible heuristic because those locations are more promising than searching every possible location in a random order.

4.3 Algorithms and Heuristics Compared

Algorithm Heuristic
A defined procedure intended to solve a specified problem. A guiding strategy intended to find a useful solution efficiently.
May guarantee a correct result when its assumptions are satisfied. May not guarantee an optimal or exact result.
Usually follows explicit steps. May use informed rules or estimates.
Suitable when an exact and practical method is available. Useful when exact search is too expensive or unnecessary.

The distinction is not always absolute. A heuristic can itself be implemented as an algorithm. The important distinction is whether the method guarantees the required exact or optimal result.

4.4 Why Heuristics Are Used

Heuristics are useful for several reasons.

Large Search Spaces:

A problem may have so many possible solutions that examining every one would require excessive time.

Incomplete Information:

The solver may not have enough information to construct a fully exact model.

Time Constraints:

A useful solution may be needed quickly even if a more exhaustive search could eventually produce a better result.

Approximation Is Acceptable:

In some applications, a sufficiently good result is more valuable than an exact result that arrives too late.

Example

Suppose a delivery company must plan routes for many vehicles visiting numerous locations. The number of possible route combinations can become extremely large. A practical system may therefore use heuristics to obtain good routes quickly rather than examining every possible route.

4.5 Common Forms of Heuristic Reasoning

Heuristics may take many forms depending on the problem.

Use of Experience:

A solver may apply knowledge gained from similar problems.

Pattern-Based Reasoning:

A familiar pattern may suggest a likely solution method.

Prioritization:

The solver may investigate the most promising possibilities first.

Simplification:

The problem may be temporarily simplified so that useful progress can be made.

Incremental Improvement:

A solution may be improved step by step rather than constructed perfectly in one operation.

4.6 Rule-of-Thumb Strategies

Rule of Thumb

A rule of thumb is an informal practical guideline derived from experience rather than a complete formal proof that the strategy is always optimal.

Examples include:

  • check the most likely cause of a fault before rare causes;
  • start with the simplest plausible explanation;
  • test small examples before large ones;
  • solve the easiest subproblem first if it simplifies the rest.

Such rules can be useful, but they should not be mistaken for universal laws.

4.7 Greedy Choice as a Heuristic Idea

A greedy strategy repeatedly chooses an option that appears best at the current stage, without necessarily considering every future consequence.

Greedy Strategy

A greedy strategy constructs a solution by repeatedly selecting a locally preferred option according to a chosen criterion.

Simple Illustration

Suppose a person wants to move toward a destination through a network of roads and repeatedly chooses the road that appears to reduce the remaining straight-line distance the most. This may lead to a good route, but it does not automatically guarantee the globally shortest route.

In some problems, a properly designed greedy algorithm can be mathematically proven to produce an optimal solution. In other problems, greedy choice is only a heuristic.

4.8 Search and Exploration

Many problem-solving tasks can be viewed as searching through possible states or possible solutions.

Examples include:

  • finding a route;
  • choosing a timetable arrangement;
  • finding a suitable configuration;
  • selecting the best sequence of actions;
  • solving a puzzle.

A blind search may examine possibilities without using additional knowledge. A heuristic search uses information about the problem to guide which possibilities are examined first.

Illustration

If a system is searching for a route to a destination, it may prefer locations estimated to be closer to the destination rather than exploring every possible direction equally.

4.9 Heuristics in Everyday Computing Problems

Troubleshooting:

When a computer cannot access the Internet, a technician may first check whether other devices can connect, whether Wi-Fi is enabled and whether the network interface is active before investigating more unusual causes.

Password Strength Estimation:

Some systems estimate password strength using heuristic indicators such as length, variety and known patterns. Such indicators provide useful guidance but are not a complete mathematical guarantee that a password is secure.

Search Engines:

Search systems use sophisticated ranking methods to determine which results are likely to be most useful. Ranking involves estimates of relevance rather than a simple universally correct ordering.

Scheduling:

Timetabling systems may use heuristic methods when many interacting constraints make exhaustive exploration impractical.

4.10 Limitations of Heuristics

Heuristics are useful, but they have limitations.

  • They may produce suboptimal solutions.
  • They may perform well for some cases and poorly for others.
  • They may depend heavily on the assumptions built into the heuristic.
  • They may require evaluation against better-known solutions.
  • They may introduce bias when based on inappropriate rules or data.
Important

A heuristic should be judged by how well it performs for the intended problem, not simply by how quickly it produces an answer.

4.11 Meaning of Problem Solvability

Problem Solvability

Problem solvability concerns whether a problem can be solved by a defined method or algorithm under the stated conditions.

In introductory computing, it is useful to distinguish among:

  • problems that can be solved exactly and efficiently;
  • problems that can be solved exactly but may require excessive computational resources for large inputs;
  • problems for which useful approximate or heuristic solutions are used;
  • problems for which no algorithm can solve every possible instance.

4.12 Solvable Problems

Solvable Problem

A solvable computational problem is one for which a method exists that can produce the required solution for the cases covered by the problem specification.

Many familiar problems are solvable.

Examples include:

  • sorting a finite collection of numbers;
  • finding the maximum value in a non-empty finite list;
  • computing the area of a circle from its radius;
  • checking whether a finite string contains a specified character;
  • calculating the average of a finite set of numeric values.

4.13 Problems with Exact Solutions

Some problems have exact solution methods that are practical for typical input sizes.

Example: Maximum Value

To determine the largest value in a finite non-empty list, the algorithm can begin with the first value as the current maximum and compare each remaining value with it. Whenever a larger value is found, the current maximum is updated.

START READ first_value maximum = first_value FOR each remaining value IF value > maximum THEN maximum = value END IF END FOR DISPLAY maximum STOP

This method produces an exact answer.

4.14 Problems with Approximate or Practical Solutions

Some problems can be described exactly, but finding the best possible answer may be computationally expensive for large instances. In such cases, approximation or heuristic methods may be used.

Example: Scheduling

A complex timetable may need to satisfy room capacities, lecturer availability, student conflicts and institutional preferences. A practical system may produce a very good timetable without proving that no other possible timetable is better according to every selected criterion.

4.15 Computational Difficulty

A problem may be solvable in principle but difficult in practice because the required amount of computation grows very rapidly as the input becomes larger.

Consider a problem in which the system must examine possible arrangements of many objects. The number of possible arrangements can increase dramatically as the number of objects increases.

Factorial Growth Example

Three distinct objects can be arranged in 3! = 6 ways.

Five distinct objects can be arranged in 5! = 120 ways.

Ten distinct objects can be arranged in 10! = 3,628,800 ways.

This illustrates why exhaustive search can become impractical even when the problem itself is finite and solvable.

4.16 Intractable Problems

Intractable Problem

Intractability generally refers to computational problems for which known exact solution methods require impractically large resources as the input size grows.

An intractable problem is not the same as an unsolvable problem. An exact method may exist, but using it on large inputs may require too much time or memory for practical purposes.

Intractable versus Unsolvable

Intractable: A solution method may exist, but practical computation becomes excessively expensive for large instances.

Unsolvable: No algorithm exists that can correctly solve every instance of the stated problem.

4.17 Unsolvable Problems

Unsolvable Computational Problem

An unsolvable computational problem is a problem for which no algorithm can produce the required correct answer for every possible valid instance of the problem.

This idea is important because it shows that computers have theoretical limits. Unlimited processor speed or memory does not remove every limitation. Some problems are not solvable by any general algorithm.

At introductory level, the purpose is not to prove advanced results in computability theory but to understand that computation itself has boundaries.

4.18 The Halting Problem as a Conceptual Example

One of the most famous examples of an undecidable problem is the halting problem.

Halting Problem

The halting problem asks whether there exists a general algorithm that, given any arbitrary program together with its input, can always determine whether that program will eventually stop or continue running forever.

Alan Turing showed that no such universal algorithm exists for all possible programs and inputs.

Meaning of the Result

The result does not mean that we can never determine whether a particular program stops. Many individual programs are easy to analyse. The result means there is no single algorithm capable of correctly answering the question for every possible program and input.

4.19 Decidable and Undecidable Problems

Decidable Problem

A decidable problem is a computational decision problem for which an algorithm exists that always terminates and produces the correct yes-or-no answer for every valid input.

Undecidable Problem

An undecidable problem is a decision problem for which no algorithm exists that can always terminate and give the correct answer for every valid input.

For example, determining whether a given integer is even is decidable. An algorithm can divide the integer by 2 and inspect the remainder.

The general halting problem, however, is undecidable.

4.20 Recognizing the Limits of Computation

Understanding computational limits is valuable for several reasons.

  • It prevents unrealistic expectations of software.
  • It helps distinguish difficult problems from impossible general problems.
  • It encourages careful problem reformulation.
  • It motivates the use of approximation and heuristics where exact computation is impractical.
  • It shows that faster hardware cannot solve every theoretical limitation.
Problem Reformulation

If finding the absolute best solution is too computationally expensive, the problem may be reformulated as finding a solution that satisfies all essential constraints and is sufficiently good according to a practical measure.

4.21 Choosing Between Exact and Heuristic Approaches

The choice between an exact algorithm and a heuristic approach depends on the nature of the problem.

Situation Likely Approach
A simple exact algorithm exists and runs efficiently. Use the exact algorithm.
An exact answer is essential and the problem size is manageable. Use an exact method.
Exact search becomes impractical for realistic input sizes. Consider approximation or heuristic methods.
A satisfactory answer is acceptable and time is limited. A heuristic may be appropriate.
The problem is undecidable in its general form. Reformulate or restrict the problem; no universal exact algorithm exists.
Integrated Example

Suppose a university must allocate examination rooms to hundreds of courses under numerous constraints. A small instance might be solved by exhaustive search. For a larger instance, examining every possible arrangement may become impractical. A heuristic strategy can prioritize arrangements that avoid clashes and use room capacity efficiently. The resulting solution may be highly satisfactory even if the system cannot prove that it is the single best arrangement possible.

Central Principle

Good problem solving requires understanding not only how to construct solutions but also what level of solution is realistically achievable. Sometimes the correct objective is an exact answer; in other situations, a reliable practical approximation is more appropriate.

Chapter Summary
  • A heuristic is a practical strategy for guiding problem solving when an exact method is unavailable, expensive or unnecessary.
  • Heuristics often trade a guarantee of optimality for speed or practicality.
  • Heuristic reasoning may use experience, prioritization, simplification, patterns and incremental improvement.
  • A greedy strategy repeatedly selects a locally preferred option and may or may not produce a globally optimal result.
  • Heuristic search uses problem-specific information to guide which possibilities are investigated first.
  • Problem solvability concerns whether a problem can be solved by an algorithm under the stated conditions.
  • Some problems have exact and practical algorithms.
  • Some problems are solvable in principle but become computationally difficult for large inputs.
  • Intractability refers to problems whose exact solution can require impractically large computational resources.
  • An unsolvable computational problem has no algorithm capable of correctly solving every possible instance.
  • A decidable problem has an algorithm that always terminates with the correct answer for every valid input.
  • An undecidable problem has no such universal terminating algorithm.
  • The halting problem is a standard example showing that computation has theoretical limits.
  • Understanding solvability and computational difficulty helps determine when exact, approximate or heuristic methods are appropriate.

CHAPTER FIVE

Problem-Solving Techniques I

A problem-solving technique is a structured way of thinking about a problem in order to make progress toward a solution. Some problems can be solved by applying a known formula or algorithm directly. Others are unfamiliar, incomplete, complex or too large to approach in one step. In such situations, the solver requires strategies that help reveal structure, generate ideas, test possibilities or transform the original problem into a more manageable form.

No single technique is appropriate for every problem. A strong problem solver therefore develops a collection of methods and learns when each method is useful. This chapter examines five important techniques: abstraction, analogy, brainstorming, trial and error, hypothesis testing and reduction.

Central Idea

Problem-solving techniques are not rigid recipes. They are thinking tools. Their value depends on how appropriately they are applied to the structure of the problem.

5.2 Why Different Problem-Solving Techniques Are Needed

Problems differ in structure. Some contain too much unnecessary detail. Some resemble previously solved problems. Some require many possible ideas before a good one emerges. Others require testing possible explanations or reducing a complicated situation into smaller parts.

For example:

  • Abstraction is useful when irrelevant details make a problem difficult to understand.
  • Analogy is useful when the new problem resembles a familiar one.
  • Brainstorming is useful when several possible solutions need to be generated.
  • Trial and error is useful when possible solutions can be tested safely and progressively.
  • Hypothesis testing is useful when the cause of a problem is uncertain.
  • Reduction is useful when a problem can be simplified or transformed into a known problem.

These techniques frequently overlap. A programmer may use abstraction to simplify a problem, analogy to recognize a known pattern, and trial and error to test implementation choices.

5.3 Abstraction

Abstraction

Abstraction is the process of focusing on the essential features of a problem while temporarily ignoring details that are not relevant to the current purpose.

Abstraction is fundamental to computing because real-world systems contain enormous amounts of detail. A useful computational model includes the details necessary to solve the problem while leaving out information that does not affect the solution.

Example: Student Result

Suppose the task is to calculate a student's average examination score. The student's name may be needed for identification, and the scores are required for calculation. The student's favourite colour, shoe size and home address are irrelevant to the average and can be ignored for that particular task.

Abstraction does not mean that ignored details are unimportant in every context. It means they are not necessary for the current problem.

5.4 Levels of Abstraction

A system may be understood at different levels of detail.

Example: Using a Printer

At the user level, printing may be described as selecting a document and choosing the Print command. At a software level, the operating system and printer driver prepare data for the printer. At a hardware level, electrical signals control printing mechanisms. Each description is valid at a different level of abstraction.

Problem solvers should choose the level of abstraction appropriate to the task.

High-Level Abstraction:

A high-level view emphasizes major functions and relationships while hiding implementation details.

Low-Level Detail:

A lower-level view exposes more specific operations, components or implementation mechanisms.

Example

High level: “Authenticate the user.”

Lower level: Receive credentials, locate the account record, verify the supplied credential against the stored authentication data, check account status and return the authentication result.

5.5 Abstraction in Computing

Abstraction appears throughout computing.

Functions and Procedures:

A function can hide several internal operations behind a simple name. The user of the function needs to understand what it does without necessarily knowing every implementation detail.

Data Abstraction:

A user may work with a data structure through defined operations without knowing precisely how the data is stored internally.

Operating Systems:

Applications use operating-system services rather than directly controlling every hardware component.

Networks:

Users send messages without manually controlling every router through which the data passes.

Problem-Solving Example

Suppose a program must calculate a student's GPA. At an early stage, the problem can be abstracted as:

  1. Obtain valid course grades and units.
  2. Convert grades to grade points.
  3. Calculate weighted grade points.
  4. Divide total weighted points by total units.
  5. Display the GPA.

The detailed programming statements can be developed later.

5.6 Analogy

Analogy

Analogy is a problem-solving technique in which similarities between a new problem and a familiar problem are used to suggest a possible solution approach.

Analogy is powerful because many apparently different problems share the same underlying structure.

Example

A student who already knows how to determine the larger of two numbers can use that knowledge when developing a solution for the largest of three numbers. The new problem is not identical, but it involves the same fundamental operation: comparison.

Structural Similarity:

Useful analogies depend on similarity in the relevant structure of the problems, not simply superficial resemblance.

Example: Eligibility Problems

The following problems have a common structure:

  • Determine whether a student passed an examination.
  • Determine whether a customer qualifies for a discount.
  • Determine whether a candidate satisfies a minimum age requirement.

In each case, the solution tests one or more conditions and selects an outcome.

5.7 Using Analogy Correctly

An analogy is useful only when the similarities relevant to the solution actually hold. Superficial comparison can produce incorrect reasoning.

A careful use of analogy involves:

  1. identifying a familiar problem;
  2. identifying the structure that made its solution work;
  3. comparing that structure with the new problem;
  4. identifying important differences;
  5. adapting rather than blindly copying the old solution;
  6. testing whether the adapted solution works.
Important

Analogy suggests a solution; it does not prove that the solution is correct. The proposed solution must still be analysed and tested.

5.8 Brainstorming

Brainstorming

Brainstorming is a technique for generating a wide range of possible ideas or solutions before evaluating and selecting among them.

Brainstorming is particularly useful when a problem has many possible approaches and the solver wants to avoid choosing the first idea too quickly.

The basic principle is to separate idea generation from idea evaluation. During generation, the aim is to produce possibilities. Evaluation occurs afterward.

Example:

Suppose a university department wants to reduce long queues during student registration. Possible ideas might include:

  • online registration;
  • appointment scheduling;
  • additional registration points;
  • automatic validation of student records;
  • self-service kiosks;
  • extended registration hours;
  • better separation of different categories of requests.

The ideas should later be evaluated according to cost, feasibility, security, user accessibility and likely effectiveness.

5.9 Structured Brainstorming

Brainstorming becomes more useful when it is guided by a clear problem statement.

A structured approach may involve:

  1. state the problem clearly;
  2. define important constraints;
  3. generate multiple solution ideas;
  4. group related ideas;
  5. eliminate ideas that violate essential constraints;
  6. compare remaining alternatives;
  7. select promising options for further analysis.
Computing Example

Problem: A website becomes slow when many users are active.

Possible ideas may include optimizing database queries, caching frequently requested data, improving server capacity, reducing unnecessary network requests, compressing resources or examining inefficient application code.

Brainstorming generates possible causes and improvements. Measurement and testing are then required to determine which ideas are relevant.

5.10 Trial and Error

Trial and Error

Trial and error is a problem-solving method in which possible solutions are tried, their results are observed, and unsuccessful attempts are modified or replaced until an acceptable solution is found.

Trial and error is useful when:

  • possible solutions are easy to test;
  • failure is inexpensive or safe;
  • there is feedback showing whether an attempt improved the situation;
  • the solution space is manageable.
Simple Example

A student adjusting the width of columns in a spreadsheet may try one width, observe the result and adjust again until the data is displayed appropriately.

5.11 Systematic Trial and Error

Random guessing is not the same as good trial and error. A systematic method keeps track of what has been tried and uses the result of each attempt to guide the next one.

Example: Debugging a Network Connection

Suppose a computer cannot connect to the Internet. A systematic approach might test:

  1. whether Wi-Fi or Ethernet is enabled;
  2. whether the device has obtained network configuration;
  3. whether other devices can connect;
  4. whether the router is operating;
  5. whether the problem is limited to one website or service.

Each test eliminates possibilities and narrows the search.

Advantages:

  • Simple to apply in manageable situations.
  • Can produce useful feedback quickly.
  • Can support learning through experimentation.

Limitations:

  • May be inefficient when possibilities are extremely numerous.
  • May be unsafe when failed attempts have serious consequences.
  • Does not guarantee an optimal solution.
  • Can become repetitive if results are not recorded and analysed.

5.12 Hypothesis Testing

Hypothesis Testing in Problem Solving

Hypothesis testing is a method in which a possible explanation or proposed cause of a problem is stated and then tested against evidence.

This form of reasoning is especially useful in troubleshooting and diagnosis.

A general process is:

  1. Observe the problem.
  2. Propose a possible explanation.
  3. Determine what evidence would be expected if the explanation were correct.
  4. Perform a test.
  5. Compare the result with the expected evidence.
  6. Accept, reject or revise the hypothesis.
Example

Observation: A printer does not print.

Hypothesis: The printer has lost its network connection.

Prediction: If this is true, the computer should be unable to communicate with the printer over the network.

Test: Check the printer's network status and test connectivity.

Result: If connectivity is normal, the hypothesis is weakened and another cause should be investigated.

5.13 Hypothesis Testing in Computing

Computing professionals use hypothesis testing frequently, even when they do not describe it formally.

Software Debugging:

A programmer may hypothesize that a wrong result is caused by an incorrect formula and test the formula separately.

Performance Problems:

A developer may hypothesize that a slow application is caused by repeated database queries and measure query activity.

Hardware Problems:

A technician may hypothesize that unexpected shutdowns are caused by overheating and inspect temperature measurements.

Applied Example: Incorrect Student Average

Suppose a result program displays an average of 62 when manual calculation gives 72.

Hypothesis 1: One score was omitted.

Test: Display or inspect all scores used in the calculation.

Hypothesis 2: The total was divided by the wrong number of subjects.

Test: Inspect the divisor used by the algorithm.

Hypothesis 3: The program is reading an incorrect record.

Test: Compare the student identifier and stored values.

Each hypothesis leads to a testable investigation rather than random modification of the program.

5.14 Reduction

Reduction

Reduction is a problem-solving technique in which a problem is transformed into a simpler problem or into another problem whose solution method is already known.

Reduction is extremely important in mathematics and computer science. Instead of solving the original problem directly, the solver asks whether it can be converted into a form that is easier to handle.

5.15 Reduction by Simplification

One form of reduction simplifies a problem by temporarily removing complexity while preserving the essential structure.

Example

Suppose a program must calculate payroll for thousands of employees under many rules. Instead of beginning with every rule at once, the developer may first solve a simpler case involving one employee with a fixed hourly rate and no deductions. Once the basic calculation works, additional rules can be introduced progressively.

Why Simplification Helps:

  • It reveals the core structure of the problem.
  • It reduces the number of interactions considered at once.
  • It creates smaller testable stages.
  • It helps identify which complexities genuinely affect the solution.

5.16 Reduction to a Known Problem

Another form of reduction converts an unfamiliar problem into a known one.

Example: Student Ranking

Suppose a system must rank students according to final scores. This can be reduced partly to a sorting problem: arrange student records according to the score field and then assign positions according to the ranking rules.

Example: Finding the Cheapest Product

If the prices of several products are stored in a list, the task of finding the cheapest product can be reduced to the familiar problem of finding the minimum value.

Reduction is valuable because established algorithms can be reused once the relationship between problems has been identified correctly.

5.17 Combining Problem-Solving Techniques

Real problems often require several techniques.

Example: Slow University Portal

Suppose users complain that a university portal becomes slow during registration.

  1. Abstraction: Ignore visual details that do not affect performance and focus on request processing, database activity, network behaviour and server resources.
  2. Brainstorming: Generate possible causes such as database bottlenecks, inefficient code, insufficient server capacity or large files.
  3. Hypothesis testing: Measure each suspected cause.
  4. Reduction: Reproduce the problem on one specific page or operation rather than analysing the entire system at once.
  5. Trial and error: Test controlled changes and measure whether performance improves.

This example demonstrates that problem-solving methods should be combined according to the demands of the situation.

5.18 Selecting an Appropriate Technique

Problem Situation Useful Technique
Too much irrelevant detail Abstraction
New problem resembles a familiar one Analogy
Many possible solutions need to be generated Brainstorming
Possible solutions can be tested safely and progressively Trial and error
The cause of a fault is uncertain Hypothesis testing
Problem can be simplified or transformed Reduction

Selection should depend on the structure of the problem rather than personal habit. Using the same strategy for every problem limits a solver's effectiveness.

5.19 Applied Problem-Solving Examples

Example 1: Designing a Student Login System:

Using Abstraction

Ignore unrelated student information such as course registration and academic history. Focus on account identity, credential verification, account status and access decision.

Using Analogy

Compare the task with other authentication systems. The familiar pattern is: receive identity information, verify supplied evidence and grant or deny access.

Example 2: Program Gives Wrong Total:

Using Hypothesis Testing

Hypothesis: one of the values is stored as text and is not included correctly in the calculation. Test the data type and value before changing unrelated parts of the program.

Example 3: Course Timetable:

Using Reduction

Instead of attempting to schedule every course immediately, first solve the smaller problem of identifying courses that cannot occur at the same time because they share students or lecturers. The resulting conflict information can then support the larger scheduling problem.

Problem-Solving Principle

A good technique makes the problem easier to reason about. If a chosen method introduces more confusion than clarity, another technique or combination of techniques may be more appropriate.

Chapter Summary
  • Problem-solving techniques provide structured ways of reasoning about unfamiliar or complex problems.
  • Abstraction focuses attention on essential information while hiding irrelevant detail.
  • Different levels of abstraction allow the same system to be understood at different degrees of detail.
  • Analogy transfers useful ideas from familiar problems to new problems with similar structure.
  • Analogy must be tested because superficial similarities can be misleading.
  • Brainstorming generates multiple possible solutions before evaluation and selection.
  • Trial and error tests possible solutions and uses the results to guide further attempts.
  • Systematic trial and error is more effective than random guessing.
  • Hypothesis testing proposes a possible explanation and tests it against evidence.
  • Hypothesis testing is especially valuable in debugging, diagnosis and troubleshooting.
  • Reduction transforms a difficult problem into a simpler or already familiar problem.
  • Real problems frequently require several problem-solving techniques used together.
  • The appropriate technique depends on the structure and requirements of the problem.

CHAPTER SIX

Problem-Solving Techniques II

The previous chapter introduced several general problem-solving techniques. This chapter develops additional techniques that are especially valuable when a problem requires creative restructuring, progressive movement toward a goal, systematic investigation of causes, formal justification or decomposition into independent subproblems.

The techniques considered are lateral thinking, means-end analysis, focal-object method, morphological analysis, research, root-cause analysis, proof and divide-and-conquer.

Some of these methods emphasize creativity, while others emphasize analysis and logical justification. A skilled problem solver should be comfortable with both forms of reasoning.

6.2 Lateral Thinking

Lateral Thinking

Lateral thinking is an approach to problem solving that deliberately attempts to generate new perspectives and alternative ways of framing a problem instead of following only the most obvious line of reasoning.

Traditional step-by-step reasoning often proceeds from existing assumptions. Lateral thinking questions whether those assumptions must be retained.

Example

Suppose a computer laboratory experiences long queues because every student must use the same physical desk to complete a particular registration process. A conventional solution might be to add more desks. Lateral thinking asks whether the process must occur at the desk at all. Moving suitable parts of the process online may address the problem in a completely different way.

6.3 Applying Lateral Thinking

Lateral thinking can be encouraged through several questions:

  • What assumption am I making?
  • What if the opposite assumption were considered?
  • Can the problem be viewed from the user's perspective?
  • Can a step be removed entirely rather than improved?
  • Can the order of activities be changed?
  • Can a resource serve more than one purpose?
  • Can the problem be avoided rather than solved directly?
Example: Forgotten Password Requests

Suppose an organization's support desk receives hundreds of requests from users who forgot their passwords.

One response is to employ more support staff. A lateral approach asks whether users can securely reset passwords themselves through a controlled recovery process. The new perspective changes the problem from “How do we answer more reset requests?” to “How do we reduce the need for manual reset requests?”

Lateral thinking is especially useful during solution generation, but proposed ideas must still be evaluated for feasibility, cost, security and correctness.

6.4 Means-End Analysis

Means-End Analysis

Means-end analysis is a problem-solving strategy in which the solver compares the current state with the desired goal, identifies the differences between them, and selects actions that reduce those differences.

The method repeatedly asks:

  1. Where am I now?
  2. Where do I need to be?
  3. What is the important difference?
  4. What action can reduce that difference?
  5. What new subproblem must be solved before that action can be taken?
Example: Publishing a Website

Current state: Website works only on a local computer.

Goal state: Website is accessible publicly through a domain name.

Differences: No public hosting, domain not connected, production database not configured.

Possible subgoals: Obtain hosting, configure the application, upload files, configure the database, connect the domain and test public access.

6.5 Subgoals in Means-End Analysis

Complex goals are often reached through a sequence of intermediate goals called subgoals.

Example: Building a Student Registration System

Final goal: A student can complete registration successfully.

Useful subgoals may include:

  • create the student's account;
  • collect required personal data;
  • validate mandatory fields;
  • store the registration record;
  • generate the required identification number;
  • display confirmation.

The advantage of subgoals is that progress can be measured. Instead of facing one large vague goal, the solver works toward smaller clearly defined states.

6.6 Method of Focal Object

Focal-Object Method

The focal-object method is a creative problem-solving technique in which a selected object, product or problem is deliberately combined with attributes or ideas taken from unrelated objects in order to generate new possibilities.

The method attempts to break habitual patterns of thinking. The selected problem or product becomes the focal object, and unrelated attributes are transferred to it to stimulate new ideas.

6.7 Applying the Focal-Object Method

A simple procedure is:

  1. Select the focal object.
  2. Select one or more unrelated objects.
  3. List important attributes of the unrelated objects.
  4. Combine those attributes with the focal object.
  5. Interpret the combinations creatively.
  6. Evaluate useful ideas.
Example: Improving a University Learning Portal

Focal object: Online learning portal.

Unrelated object: Navigation application.

Attributes of navigation application: route guidance, progress indication, alerts, suggested next action.

Transferring these attributes may inspire features such as learning-path guidance, percentage completion, reminders for unfinished work and recommended next course activities.

The resulting ideas are not accepted automatically. The purpose is to generate possibilities that ordinary linear reasoning might not produce.

6.8 Morphological Analysis

Morphological Analysis

Morphological analysis is a systematic technique for generating possible solutions by identifying important dimensions of a problem, listing alternatives for each dimension and exploring combinations of those alternatives.

This technique is useful when a design problem contains several independent choices.

Example: Designing a Student Notification System

Important dimensions might include:

  • delivery method;
  • message timing;
  • message priority;
  • recipient group.

6.9 Constructing a Morphological Matrix

A morphological matrix organizes alternatives into categories.

Dimension Option 1 Option 2 Option 3 Option 4
Delivery Method Email SMS Portal Alert Mobile Push
Timing Immediate Hourly Daily Scheduled Date
Priority Normal Important Urgent Emergency
Recipient One Student Class Department All Students

Possible solutions can be generated by selecting one option from each dimension. For example:

SMS + Immediate + Urgent + One Student

or:

Portal Alert + Daily + Normal + Department

Not every combination will be sensible. Morphological analysis generates possibilities; evaluation identifies combinations that are practical and useful.

6.10 Research as a Problem-Solving Technique

Research

Research in problem solving is the systematic search for reliable information, evidence, methods, documentation or prior solutions that can improve understanding of a problem and guide the development of a solution.

Effective problem solvers do not assume they must invent every solution from the beginning. Existing knowledge can prevent wasted effort and reveal tested methods.

Research may involve:

  • textbooks;
  • technical documentation;
  • standards;
  • scholarly articles;
  • official manuals;
  • existing software designs;
  • reliable technical communities;
  • experiments and measurements.

6.11 Effective Technical Research

Technical research should be purposeful. Searching randomly for information can produce large amounts of irrelevant material.

A useful process is:

  1. Define the exact question.
  2. Identify likely authoritative sources.
  3. Search using specific terminology.
  4. Compare multiple reliable sources where necessary.
  5. Check whether the information is current enough for the topic.
  6. Test technical recommendations before relying on them in production.
Example

If a programmer encounters an error in a database library, searching only the phrase “database not working” is too broad. A more effective search includes the library name, version, exact error message and relevant programming environment.

Important

Research does not mean copying code or solutions without understanding them. A borrowed method should be evaluated for correctness, licensing, compatibility and relevance to the actual problem.

6.12 Root Cause Analysis

Root Cause Analysis

Root cause analysis is a systematic process for identifying the underlying cause or causes of a problem rather than addressing only its visible symptoms.

Solving only a symptom may allow the problem to return.

Example

Symptom: A web application repeatedly runs out of disk space.

Temporary response: Delete some files.

Possible root cause: Application log files are growing continuously because log rotation has not been configured correctly.

Deleting files provides short-term relief. Correcting the logging configuration addresses the deeper cause.

6.13 The Five Whys Technique

Five Whys

The Five Whys is a root-cause technique in which the solver repeatedly asks why an observed problem occurred, using each answer to explore a deeper contributing cause.

The number five is not a rigid requirement. The objective is to continue questioning until the relevant underlying cause has been identified sufficiently for action.

Example: Students Cannot See Results

Problem: Students cannot view newly released results.

Why 1: Why can students not see the results?
Because the result page returns no records.

Why 2: Why does the query return no records?
Because it is filtering by the wrong term identifier.

Why 3: Why is the wrong term identifier being used?
Because the page reads an outdated configuration value.

Why 4: Why is the configuration value outdated?
Because the active term was changed in one table but not synchronized with the old configuration mechanism.

At this point, simply modifying the result page would treat one symptom. The deeper design problem is that two different sources of truth are being used for the active academic term.

6.14 Cause-and-Effect Reasoning

Complex problems may have several contributing causes rather than one root cause.

A cause-and-effect analysis groups possible causes into categories so that the investigation does not focus too narrowly.

Example: Slow Application

Possible categories include:

  • Software: inefficient algorithm, repeated queries, memory leak;
  • Database: missing indexes, inefficient queries, excessive locking;
  • Hardware: insufficient memory, overloaded CPU, slow storage;
  • Network: high latency, packet loss, insufficient bandwidth;
  • Configuration: unsuitable limits, disabled caching, incorrect environment settings;
  • Usage: unexpectedly high concurrent traffic.

This form of analysis encourages a broad investigation before conclusions are drawn.

6.15 Proof as a Problem-Solving Technique

Proof

A proof is a logical argument demonstrating that a statement follows necessarily from accepted assumptions, definitions or previously established results.

Proof is important in computing because some claims must be established logically rather than tested only through examples.

Example

Claim: The sum of two even integers is even.

Let the two even integers be 2a and 2b for integers a and b.

Their sum is:

2a + 2b = 2(a + b)

Since a + b is an integer, the result is divisible by 2 and is therefore even.

Testing many examples can support confidence but does not replace a general proof when proof is required.

6.16 Direct Proof and Counterexample

Direct Proof:

A direct proof begins with accepted facts or assumptions and logically derives the required conclusion.

Counterexample:

Counterexample

A counterexample is a specific case showing that a general statement is false.

Example

Claim: “Every prime number is odd.”

The number 2 is prime and is even. Therefore, 2 is a counterexample and the general claim is false.

Counterexamples are powerful in algorithm design. If a developer claims that an algorithm works for all valid inputs, finding one valid input for which it fails disproves that claim.

6.17 Divide and Conquer

Divide and Conquer

Divide and conquer is a problem-solving strategy that divides a problem into smaller subproblems of the same or related form, solves the subproblems, and combines their solutions to obtain the result for the original problem.

The basic pattern is:

  1. Divide: Break the original problem into smaller subproblems.
  2. Conquer: Solve the subproblems.
  3. Combine: Merge the partial solutions.

6.18 Divide and Conquer in Computing

Divide-and-conquer methods appear in many important algorithms.

Binary Search:

Binary search finds a target value in a sorted collection by repeatedly dividing the search region into halves.

Example

Consider the sorted list:

4, 9, 13, 18, 21, 27, 35, 41, 50

To find 35, compare with the middle value 21. Since 35 is greater than 21, the left half can be ignored. Search the remaining half. The search region becomes smaller after each comparison.

Merge Sort:

Merge sort divides a collection into smaller parts, sorts the parts and combines the sorted results.

Conceptual Example

Suppose the list is:

8, 3, 6, 2

Divide into:

[8, 3] and [6, 2]

Sort the parts:

[3, 8] and [2, 6]

Merge them in order:

[2, 3, 6, 8]

Difference from Ordinary Decomposition:

General decomposition divides a complex system into manageable parts. Divide and conquer is more specific: the subproblems are typically structured so that the same general solution method can be applied repeatedly, and their results are combined.

6.19 Comparing Problem-Solving Techniques

Technique Main Purpose Typical Use
Lateral Thinking Generate new perspectives When conventional approaches seem limited
Means-End Analysis Reduce the difference between current and desired states Goal-oriented planning
Focal-Object Method Stimulate creative ideas through unusual combinations Product or interface innovation
Morphological Analysis Explore combinations of design alternatives Multi-dimensional design problems
Research Obtain relevant knowledge and evidence Unfamiliar technical problems
Root Cause Analysis Identify underlying causes Repeated faults and failures
Proof Establish logical correctness Mathematical and algorithmic claims
Divide and Conquer Break a problem into related smaller problems Search, sorting and structured computational tasks

6.20 Combining Techniques in Complex Problems

Complex problems rarely fit one method perfectly.

Example: Online Examination Platform Failure

Suppose an online examination platform becomes unreliable when thousands of students attempt to begin an examination at the same time.

Research: Examine monitoring data, server logs, architecture and known platform limitations.

Root cause analysis: Determine whether the failure originates from database connections, authentication load, server capacity, network infrastructure or another component.

Means-end analysis: Define the current system capacity and required target capacity, then identify the technical differences that must be addressed.

Divide and conquer: Examine authentication, question delivery, answer submission and database operations as separate subsystems.

Lateral thinking: Consider whether all students must start in one exact second or whether controlled start windows could reduce peak load without violating examination requirements.

The techniques complement one another because they answer different questions.

6.21 Applied Problem-Solving Case Studies

Case Study 1: Duplicate Student Records:

Situation

A student database contains duplicate records for some students.

Research: Inspect database rules and registration procedures.

Root cause analysis: Determine whether duplicate records result from repeated form submission, missing unique constraints or manual data entry.

Means-end analysis: Current state contains duplicates; desired state requires one authoritative record per student.

Possible solution: Correct existing duplicates and prevent recurrence through appropriate validation and uniqueness controls.

Case Study 2: Designing a Course Recommendation Feature:

Situation

A learning platform wants to recommend the next useful study material to students.

Focal-object thinking: Borrow ideas from navigation systems, such as suggested next route and progress indicators.

Morphological analysis: Consider combinations of recommendation basis, timing, content type and student level.

Research: Examine educational requirements and available student data.

Evaluation: Determine whether recommendations actually support learning rather than merely increasing platform activity.

Case Study 3: Searching a Sorted Student List:

Situation

A system must find a matriculation number in a very large list that is already sorted.

Divide-and-conquer idea: Compare the target with the middle entry. Eliminate the half that cannot contain the target and repeat on the remaining half.

This approach leads naturally to binary search, an important divide-and-conquer search method.

Final Principle

Good problem solving is not simply the possession of many techniques. It is the ability to recognize the structure of a problem, select appropriate methods, combine them intelligently, test conclusions and refine the resulting solution.

Chapter Summary
  • Lateral thinking seeks alternative ways of framing and approaching a problem.
  • Means-end analysis compares the current state with the desired state and selects actions that reduce the difference.
  • Subgoals break a large goal into manageable intermediate states.
  • The focal-object method generates new ideas by combining a problem or product with attributes from unrelated objects.
  • Morphological analysis generates solution possibilities by combining alternatives across several problem dimensions.
  • Research helps problem solvers obtain reliable information, established methods and technical evidence.
  • Effective technical research begins with a precise question and prioritizes authoritative and relevant sources.
  • Root cause analysis seeks the underlying causes of a problem rather than merely treating visible symptoms.
  • The Five Whys technique explores progressively deeper causes through repeated questioning.
  • Cause-and-effect analysis is useful when several factors may contribute to one problem.
  • Proof establishes a conclusion logically, while a counterexample can disprove a general statement.
  • Divide and conquer divides a problem into smaller related subproblems, solves them and combines the results.
  • Binary search and merge sort illustrate divide-and-conquer thinking in computing.
  • Complex computing problems often require several problem-solving techniques used together.

CHAPTER SEVEN

Solution Formulation Using Flowcharts

After analysing a problem and determining the logical steps required for its solution, the solution must often be represented in a form that can be examined before programming begins. One important representation is the flowchart.

A flowchart presents the logical flow of a solution graphically. Instead of describing every operation entirely in sentences, it uses standardized shapes connected by directional lines. This allows the student to see the order in which operations occur, where decisions are made, and where actions are repeated.

Flowcharts are particularly useful to beginning programmers because they make the structure of an algorithm visible. They can expose logical errors that may be less obvious in ordinary prose.

7.2 Meaning of a Flowchart

Flowchart

A flowchart is a graphical representation of an algorithm, process or procedure in which standardized symbols are connected by directional flow lines to show the sequence of operations and decisions.

The word flow refers to the direction in which control moves through the solution. The chart therefore shows not merely what operations are required but also the order in which they are performed.

Simple Illustration

Suppose a program receives the length and width of a rectangle and calculates its area. The logical flow is:

Start → Input Length and Width → Area = Length × Width → Display Area → Stop

7.3 Purposes of Flowcharts

Flowcharts serve several purposes in problem solving and program development. They can be used to:

  • plan the logic of a solution before coding;
  • communicate an algorithm visually;
  • identify missing or unnecessary operations;
  • show alternative paths through decisions;
  • represent repeated operations clearly;
  • support debugging and logical verification;
  • provide documentation for an existing process or program.

A flowchart should not be treated merely as a drawing exercise. Its real purpose is to represent logic accurately.

7.4 Basic Flowchart Symbols

Different symbols represent different categories of operations. The most important symbols at introductory level are shown below.

Symbol Typical Shape Purpose
Terminal Oval or rounded rectangle Indicates the start or end of a process.
Process Rectangle Represents a calculation, assignment or processing operation.
Input/Output Parallelogram Represents data entering or leaving the system.
Decision Diamond Represents a condition that determines which path is followed.
Flow Line Arrow Shows the direction of control.
Connector Small circle or labelled connector Links separated sections of a flowchart when necessary.
Important Distinction

A calculation such as Total = Price × Quantity belongs in a process symbol, while an instruction such as Read Price or Display Total belongs in an input/output symbol.

7.5 Rules for Constructing Flowcharts

A well-constructed flowchart should communicate the algorithm without unnecessary ambiguity. Useful conventions include the following:

  • Provide a clearly identifiable starting point and ending point.
  • Use the correct symbol for each type of operation.
  • Connect symbols using directional flow lines.
  • Label alternative decision branches appropriately, commonly Yes/No or True/False.
  • Keep the direction of flow consistent wherever practical.
  • Avoid crossing lines unnecessarily.
  • Ensure every path leads logically to another operation or termination.
  • Keep the text inside symbols concise but meaningful.

7.6 Sequence in Flowcharts

A sequence is the simplest control structure. Operations are performed one after another without branching.

Worked Example: Total Purchase Cost

Problem: Calculate the total cost of a quantity of goods.

Input: Quantity and unit price.

Processing: Total = Quantity × Unit Price.

Output: Total cost.

Start → Input Quantity, Price → Total = Quantity × Price → Display Total → Stop

If the quantity is 8 and the unit price is ₦1,250, then:

Total = 8 × ₦1,250 = ₦10,000.

7.7 Selection in Flowcharts

Selection introduces alternative paths. A condition is evaluated, and the result determines which branch of the flowchart is followed.

Worked Example: Pass or Fail

A student passes if the score is at least 40.

Start → Input Score → Is Score ≥ 40?

If the answer is Yes, the flow proceeds to Display "Pass". If the answer is No, it proceeds to Display "Fail". Both branches subsequently terminate.

A decision must be expressed as a condition that can be evaluated. Examples include:

  • Age ≥ 18?
  • Balance ≥ Withdrawal?
  • Password correct?
  • Number MOD 2 = 0?
  • Temperature > 30?

7.8 Multiple Selection

Some problems require more than two possible outcomes. Such problems can be represented using a sequence of decisions.

Example: Grade Classification

Suppose the following grading rules apply:

ScoreGrade
70–100A
60–69B
50–59C
45–49D
40–44E
Below 40F

The flowchart may first ask whether the score is at least 70. If not, it tests whether it is at least 60, then 50, 45 and 40. If none of these conditions is satisfied, the grade is F.

The order of the tests matters. When ranges are tested from the highest boundary downward, a score of 75 satisfies the first condition immediately and need not be compared with lower boundaries.

7.9 Repetition in Flowcharts

Repetition occurs when control returns to an earlier point so that one or more operations are performed again.

Example: Display Numbers 1 to 5

The process begins by setting a counter to 1. The counter is displayed and increased by 1 while its value remains within the required range.

Start → Count = 1 → Count ≤ 5?

If Yes, display Count, calculate Count = Count + 1, and return to the decision. If No, stop.

The output is:

1, 2, 3, 4, 5

A repetition structure must contain some mechanism that eventually changes the condition. Otherwise, the process may continue indefinitely.

7.10 Flowchart for Arithmetic Problems

Worked Example: Simple Interest

Given: Principal P, annual rate R percent, and time T years.

Required: Simple interest I.

Formula:

I = (P × R × T) / 100

For P = ₦80,000, R = 6 and T = 2:

I = (80,000 × 6 × 2) / 100

I = ₦9,600.

Start → Input P, R, T → I = (P × R × T) / 100 → Display I → Stop

7.11 Flowchart for Comparison Problems

Worked Example: Largest of Three Numbers

Let the numbers be A, B and C.

One logical approach is:

  1. Read A, B and C.
  2. Assume A is the largest.
  3. If B is greater than the current largest, replace the largest with B.
  4. If C is greater than the current largest, replace the largest with C.
  5. Display the largest value.

For A = 17, B = 31 and C = 24:

Initially, Largest = 17. Since 31 > 17, Largest becomes 31. Since 24 is not greater than 31, the final answer remains 31.

7.12 Flowchart for Validation Problems

Validation checks whether data satisfies defined rules before it is accepted for processing.

Example: Examination Score

A valid percentage score must lie between 0 and 100 inclusive.

After the score is entered, the flowchart evaluates:

Score ≥ 0 AND Score ≤ 100?

If the condition is true, processing continues. Otherwise, an error message can be displayed and another value requested.

Validation is important because even a mathematically correct algorithm can produce meaningless results when inappropriate data is accepted.

7.13 Flowchart for Accumulation and Counting

Two common repetitive operations are counting and accumulation.

A counter records how many times an event has occurred. An accumulator maintains a running total.

Worked Example: Average of Five Scores

Initialize:

Total = 0
Count = 1

While Count ≤ 5:

  1. Read a score.
  2. Add the score to Total.
  3. Increase Count by 1.

After five scores have been processed:

Average = Total / 5

If the scores are 60, 75, 48, 82 and 70:

Total = 60 + 75 + 48 + 82 + 70 = 335

Average = 335 / 5 = 67.

7.14 Nested Decisions

A decision may occur inside another decision. This structure is called a nested decision.

Example: Account Withdrawal

A withdrawal may require two conditions:

  1. The PIN must be correct.
  2. The available balance must be sufficient.

The system can first test the PIN. Only if it is correct does it test whether the balance is sufficient.

This structure prevents an unnecessary balance test when authentication has already failed.

7.15 Developing a Flowchart from a Problem Statement

A reliable procedure is to move from the problem statement to a flowchart in stages.

  1. Identify the required result.
  2. Identify the input data.
  3. Determine the processing operations.
  4. Identify decisions and their possible outcomes.
  5. Identify repeated operations.
  6. Arrange the operations logically.
  7. Draw the appropriate symbols and connections.
  8. Trace the flowchart with sample data.
Practical Illustration

Problem: Determine whether an integer is positive, negative or zero.

Input: Number N.

Decision 1: Is N > 0?

If Yes, display “Positive”. If No, test whether N < 0. If that condition is true, display “Negative”; otherwise display “Zero”.

This problem demonstrates why analysis should occur before drawing. The three possible outcomes must first be identified.

7.16 Tracing a Flowchart

Tracing means following the flowchart manually using selected values and recording the changes that occur.

Example

Suppose a flowchart calculates the sum of integers from 1 to N. Let N = 4.

Iteration Count Total After Addition
111
223
336
4410

When Count becomes 5, the condition Count ≤ 4 is false and the repetition terminates. The output is 10.

7.17 Advantages and Limitations of Flowcharts

Advantages:

  • They provide a visual representation of logic.
  • They make decisions and repetitions easy to identify.
  • They can improve communication between developers and learners.
  • They assist in detecting logical omissions.
  • They provide useful documentation.

Limitations:

  • Large programs can produce very large and complicated flowcharts.
  • Changing complex flowcharts may require substantial redrawing.
  • They may become difficult to follow when too many connectors and branches are present.
  • They do not directly express all programming-language details.

7.18 From Flowchart to Program

A flowchart provides a language-independent representation of program logic. Each major flowchart structure has a corresponding programming structure.

Flowchart Concept Programming Concept
Process Assignment or computation
Input/Output Input and output statements
Decision Conditional statement
Repeated flow Loop or iteration

A student who understands the logic represented by a flowchart is therefore well prepared to express the same solution in pseudocode and subsequently in a programming language.

Chapter Summary
  • A flowchart is a graphical representation of an algorithm or process.
  • Standardized symbols distinguish terminals, processes, input/output operations and decisions.
  • Flow lines indicate the direction in which control proceeds.
  • Sequence represents operations executed in order.
  • Selection represents alternative paths based on conditions.
  • Repetition represents operations performed repeatedly.
  • Flowcharts can represent arithmetic calculations, validation, comparison, counting and accumulation.
  • Nested decisions allow one decision to occur within another.
  • Tracing helps verify flowchart logic using sample data.
  • Flowcharts provide a useful bridge between problem analysis and program implementation.

CHAPTER EIGHT

Pseudocode and Structured Solution Design

A flowchart expresses solution logic graphically. Pseudocode expresses the same type of logic textually using structured, programming-like statements that are intended primarily for human understanding.

Pseudocode is especially useful because it allows a problem solver to develop programming logic without being distracted by the exact syntax of Python, C or another language. Once the logic has been established, translation into a programming language becomes more systematic.

8.2 Meaning of Pseudocode

Pseudocode

Pseudocode is an informal but structured textual representation of an algorithm that uses clear, programming-like statements without requiring the exact syntax of a particular programming language.

Consider an algorithm for calculating the square of a number:

START READ number square = number × number DISPLAY square STOP

The logic is clear even though the statements are not required to follow the exact syntax of C or Python.

8.3 Characteristics of Good Pseudocode

Good pseudocode should be:

  • clear: each instruction should have an obvious meaning;
  • ordered: statements should appear in their intended execution sequence;
  • consistent: similar operations should use similar notation;
  • structured: decisions and repetitions should be visibly organized;
  • language-independent: unnecessary dependence on a particular programming language should be avoided;
  • complete: the major logical operations needed to solve the problem should be present.
Poor and Improved Pseudocode

Poor:

Get things Do calculation Show answer

Improved:

READ length READ width area = length × width DISPLAY area

The improved version makes the required data and operation explicit.

8.4 Pseudocode and Programming Languages

Pseudocode resembles programming code but should not be confused with executable code.

Pseudocode Programming Language
Designed primarily for human reasoning. Designed to be translated or executed according to language rules.
No universal compulsory syntax. Has formally defined syntax.
Usually language-independent. Specific to languages such as C or Python.
Focuses on algorithmic logic. Expresses both logic and implementation details.
Cannot normally be executed directly. Can be compiled, interpreted or otherwise executed through the appropriate environment.

8.5 Variables and Assignment Statements

Variable

A variable is a named storage concept used to represent a value that may be assigned, examined or changed during an algorithm.

Examples of meaningful variable names include:

  • score
  • total
  • average
  • quantity
  • balance
  • student_count

An assignment gives a value to a variable.

age = 18 total = price × quantity count = count + 1

The statement count = count + 1 should be interpreted operationally: obtain the current value of count, add 1, and store the result back in count.

Example

If count currently contains 7, then:

count = count + 1

changes its value to 8.

8.6 Input and Output Statements

Input statements obtain data required by the algorithm. Output statements communicate results.

READ name READ score DISPLAY name DISPLAY score

Other pseudocode conventions may use words such as INPUT, GET, PRINT, WRITE or OUTPUT. Consistency and clarity are more important than adopting one universal keyword because pseudocode has no single official syntax.

8.7 Arithmetic Expressions

Arithmetic expressions combine values and operators to produce numerical results.

Operation Common Representation
Addition+
Subtraction−
Multiplication× or *
Division/
RemainderMOD
Worked Example: Average

Suppose three scores are 62, 74 and 80.

total = score1 + score2 + score3 average = total / 3

Total = 62 + 74 + 80 = 216.

Average = 216 / 3 = 72.

8.8 Relational and Logical Conditions

Conditions are used to make decisions. A relational condition compares values.

Condition Meaning
A > BA is greater than B
A < BA is less than B
A >= BA is greater than or equal to B
A <= BA is less than or equal to B
A = BA is equal to B in the intended pseudocode convention
A != BA is not equal to B

Logical operators combine conditions.

age >= 18 AND citizen = TRUE score < 0 OR score > 100 NOT account_locked

8.9 Sequence in Pseudocode

Sequence means executing statements in the order in which they appear.

Worked Example: Circle Area

Given: Radius r.

Required: Area A.

Formula: A = πr².

START READ radius area = π × radius × radius DISPLAY area STOP

If radius = 7 and π is approximated as 3.14159:

Area = 3.14159 × 7 × 7

Area ≈ 153.94 square units.

8.10 IF Statements

An IF statement performs an action only when a specified condition is true.

IF condition THEN statement END IF
Example
READ temperature IF temperature > 30 THEN DISPLAY "High temperature" END IF

If the temperature is 35, the message is displayed. If the temperature is 25, the conditional statement performs no output.

8.11 IF-ELSE Statements

An IF-ELSE structure chooses between two alternatives.

IF condition THEN action1 ELSE action2 END IF
Example: Even or Odd
START READ number IF number MOD 2 = 0 THEN DISPLAY "Even" ELSE DISPLAY "Odd" END IF STOP

For number = 26, the remainder after division by 2 is zero, so the output is “Even”.

8.12 Multiple and Nested Decisions

Multiple alternatives may be represented using ELSE IF statements.

Example: Classifying a Number
START READ number IF number > 0 THEN DISPLAY "Positive" ELSE IF number < 0 THEN DISPLAY "Negative" ELSE DISPLAY "Zero" END IF STOP

A decision can also occur inside another decision.

Example: ATM Withdrawal Logic
IF pin_is_correct THEN IF withdrawal <= balance THEN DISPLAY "Transaction approved" ELSE DISPLAY "Insufficient balance" END IF ELSE DISPLAY "Incorrect PIN" END IF

8.13 Repetition Using WHILE

A WHILE structure repeats statements as long as its condition remains true.

WHILE condition statements END WHILE
Example: Numbers 1 to 5
count = 1 WHILE count <= 5 DISPLAY count count = count + 1 END WHILE

The condition is tested before each repetition. After 5 is displayed, count becomes 6. The condition 6 ≤ 5 is false, so the loop terminates.

8.14 Count-Controlled Repetition

Count-controlled repetition is appropriate when the required number of repetitions is known.

Example: Read Ten Scores
count = 1 WHILE count <= 10 READ score DISPLAY score count = count + 1 END WHILE

The counter begins at 1 and increases once after each score. When it reaches 11, the condition becomes false.

8.15 Accumulators and Counters

Counter

A counter is a variable used to record the number of times an event or operation occurs.

Accumulator

An accumulator is a variable used to maintain a running total as values are processed.

Worked Example: Average of Four Scores
total = 0 count = 1 WHILE count <= 4 READ score total = total + score count = count + 1 END WHILE average = total / 4 DISPLAY average

Suppose the scores are 55, 70, 65 and 90.

Score Total Before Total After
55055
7055125
65125190
90190280

Average = 280 / 4 = 70.

8.16 Sentinel-Controlled Repetition

Sentinel Value

A sentinel value is a special value used to indicate that input or repetition should terminate, provided that the value cannot be confused with ordinary valid data.

Sentinel-controlled repetition is useful when the number of data items is not known in advance.

Example

Suppose positive sales amounts are entered and −1 indicates the end of input.

total = 0 READ sale WHILE sale != -1 total = total + sale READ sale END WHILE DISPLAY total

The value −1 is not included in the total because it serves only as the termination signal.

8.17 Data Validation in Pseudocode

Pseudocode can express validation before data is used.

Example: Score Validation
READ score WHILE score < 0 OR score > 100 DISPLAY "Invalid score" READ score END WHILE DISPLAY "Score accepted"

If the user enters 120, the condition is true and another score is requested. If 75 is entered, the condition becomes false and the value is accepted.

Notice that validation is not merely an error message. The algorithm must specify what happens after invalid data is detected.

8.18 Developing Pseudocode from a Problem

The development of pseudocode should begin with analysis rather than immediate writing.

Worked Problem: Calculate a Student's Average and Status

Problem: Read three examination scores, calculate their average, and display “Pass” if the average is at least 50; otherwise display “Fail”.

Inputs: score1, score2, score3.

Processing:

Total = score1 + score2 + score3

Average = Total / 3

Decision: Average ≥ 50?

Outputs: Average and status.

START READ score1 READ score2 READ score3 total = score1 + score2 + score3 average = total / 3 DISPLAY average IF average >= 50 THEN DISPLAY "Pass" ELSE DISPLAY "Fail" END IF STOP

Suppose the scores are 62, 55 and 48.

Total = 62 + 55 + 48 = 165

Average = 165 / 3 = 55

Since 55 ≥ 50, the status is Pass.

8.19 Tracing Pseudocode

A trace table records the values of variables as an algorithm executes. It is particularly useful for checking loops and decisions.

Trace Example
total = 0 count = 1 WHILE count <= 4 total = total + count count = count + 1 END WHILE DISPLAY total
Iteration Count Used Total Before Total After
1101
2213
3336
44610

The final output is 10.

Tracing is especially valuable for identifying:

  • incorrect initial values;
  • conditions that stop too early or too late;
  • counters that are not updated;
  • incorrect accumulation;
  • wrong decision branches.

8.20 Flowcharts and Pseudocode Compared

Feature Flowchart Pseudocode
Representation Graphical Textual
Main Elements Symbols and arrows Structured statements
Best Strength Visualizing control flow Expressing detailed logic compactly
Modification Can become difficult for large charts Usually easier to edit as plain text
Programming Similarity Conceptual Closer to programming statements
Execution Not directly executable Not normally directly executable

Neither representation is universally superior. A flowchart can make branching easier to visualize, while pseudocode can express a detailed algorithm more compactly. Both are tools for solution design.

8.21 From Pseudocode to Programming Code

One major advantage of pseudocode is that its structures correspond closely to programming constructs.

Example Transformation

Pseudocode:

READ score IF score >= 50 THEN DISPLAY "Pass" ELSE DISPLAY "Fail" END IF

The essential operations are input, comparison, selection and output. A programmer translating the algorithm into C or Python therefore needs to express these same operations using the syntax of the selected language.

Before translation, the pseudocode should be tested logically. Programming code should not be used as a substitute for understanding the problem. If the underlying logic is incorrect, translating it accurately into a programming language merely produces a program that implements the wrong solution.

Connection to Programming

The concepts developed so far form a progression: a problem is identified and analysed; an algorithm is developed; the solution may be represented with a flowchart or pseudocode; the logic is traced and refined; and only then is it implemented in a programming language.

Chapter Summary
  • Pseudocode is a structured textual representation of an algorithm.
  • It emphasizes solution logic without requiring the exact syntax of a programming language.
  • Variables represent values used during processing, while assignment statements create or update those values.
  • Input statements obtain data and output statements communicate results.
  • Arithmetic expressions perform calculations, while relational and logical expressions form conditions.
  • Sequence executes statements in order.
  • IF, IF-ELSE and nested decisions implement selection.
  • WHILE and related structures express repetition.
  • Counters record occurrences, while accumulators maintain running totals.
  • Sentinel values can terminate input when the number of data items is unknown in advance.
  • Validation prevents unacceptable data from entering later stages of processing.
  • Trace tables help verify the behaviour of pseudocode before implementation.
  • Flowcharts represent logic graphically, while pseudocode represents it textually.
  • Well-designed pseudocode provides a direct conceptual bridge from algorithm design to implementation in languages such as C and Python.

CHAPTER NINE

Decision Tables and Decision Trees

Many computing problems require a solution to choose an action from several alternatives. Such problems are called decision-oriented problems. The final result depends not merely on a calculation but on the combination of conditions that apply.

Simple decisions can be represented adequately with an IF statement or a decision symbol in a flowchart. As the number of conditions increases, however, the logic may become difficult to understand. Two useful tools for organizing such logic are decision tables and decision trees.

A decision table organizes conditions and actions in tabular form. A decision tree represents the same general type of logic as a branching structure. Both techniques help the problem solver examine whether all important combinations have been considered.

Central Idea

Decision tables and decision trees are not programming languages. They are solution-design tools used to make complex decision logic clearer before implementation.

9.2 Decision-Oriented Problems

A decision-oriented problem contains one or more conditions whose values determine what action should be taken.

Simple Example

A student receives a course grade according to the examination score. The score is the condition being examined, while the assigned grade is the resulting action.

Other examples include:

  • determining whether a bank transaction should be approved;
  • deciding whether a student is eligible for a course;
  • determining shipping charges according to location and weight;
  • assigning a discount according to customer type and purchase amount;
  • deciding whether a user may access a protected resource;
  • determining whether a registration record is complete.

The complexity increases when several conditions must be considered together.

9.3 Meaning of a Decision Table

Decision Table

A decision table is a tabular representation of decision logic that shows combinations of conditions and the actions that should be taken for each combination.

Decision tables are especially useful when several conditions interact. Instead of tracing nested IF statements mentally, the problem solver can inspect the combinations systematically.

9.4 Components of a Decision Table

A typical decision table contains four important elements:

  • condition statements — the factors being tested;
  • condition entries — the values or states of those factors;
  • action statements — the possible actions;
  • action entries — indicators showing which actions apply under each rule.

Each column of condition and action entries normally represents one rule.

9.5 Constructing a Simple Decision Table

Suppose a student is permitted to enter an examination hall only if the student has a valid examination card.

Condition / Action Rule 1 Rule 2
Valid examination card? Yes No
Allow entry X
Deny entry X

The table contains two possible cases: the condition is true or false. Each case produces a different action.

9.6 Decision Tables with Multiple Conditions

Suppose an online examination requires both a registered account and a valid examination authorization.

There are two conditions, each with two possible values. This gives four possible combinations.

Condition / Action Rule 1 Rule 2 Rule 3 Rule 4
Registered account? Yes Yes No No
Authorized for examination? Yes No Yes No
Allow examination X
Reject access X X X

The table makes an important rule immediately visible: access is permitted only when both conditions are satisfied.

9.7 Rules in Decision Tables

Decision Rule

A decision rule is one particular combination of condition values together with the action or actions that must occur for that combination.

If there are n independent conditions and each condition has exactly two possible values, a complete table may contain up to:

2n possible combinations.

Example

For three independent Yes/No conditions:

Number of combinations = 23 = 8.

For four independent Yes/No conditions:

Number of combinations = 24 = 16.

This explains why decision tables can become large when many conditions are included. However, some combinations may be impossible or may lead to exactly the same action and can sometimes be simplified.

9.8 Complete and Reduced Decision Tables

Complete Decision Table:

A complete decision table explicitly represents every relevant combination of condition values.

Reduced Decision Table:

A reduced decision table combines rules when some condition does not affect the outcome.

Example

Suppose a system denies access whenever an account is locked, regardless of whether the supplied password is correct.

When Account Locked = Yes, the password condition becomes irrelevant to the final action. A reduced table may represent that condition using a dash or “don't care” notation.

Condition / Action Rule 1 Rule 2 Rule 3
Account locked? Yes No No
Password correct? — Yes No
Allow access X
Deny access X X

The dash means that the value of the password condition does not matter when the account is locked.

9.9 Validating a Decision Table

A decision table should be checked carefully before implementation.

Important questions include:

  • Have all relevant conditions been included?
  • Are all meaningful combinations represented?
  • Does each rule produce the required action?
  • Are any rules contradictory?
  • Are impossible combinations being treated as though they were valid?
  • Can some rules be combined without changing the logic?
Example of Missing Logic

Suppose a table for examination grading includes scores from 0 to 39, 40 to 69 and 70 to 100 but says nothing about scores below 0 or above 100. If the system is expected to validate input, the table is incomplete because invalid values have not been addressed.

9.10 Meaning of a Decision Tree

Decision Tree

A decision tree is a branching representation of decision logic in which internal nodes represent conditions or decisions, branches represent possible outcomes of those decisions, and terminal nodes represent final actions or results.

Decision trees display the order in which conditions are examined. This makes them particularly useful when one decision determines whether another decision needs to be considered.

9.11 Components of a Decision Tree

A simple decision tree contains:

  • root node — the first decision;
  • decision nodes — conditions tested during the process;
  • branches — possible outcomes of each decision;
  • leaf or terminal nodes — final actions or conclusions.
Password Correct? Yes ↓ Allow Access No ↓ Deny Access

9.12 Constructing a Decision Tree

A useful procedure is:

  1. Identify the first relevant condition.
  2. Create a branch for each possible result.
  3. Determine whether another condition must be tested on each branch.
  4. Continue branching until a final action is reached.
  5. Check that all meaningful cases are represented.
Example: Course Registration

Suppose a student may register for an advanced course only if:

  • the prerequisite course has been passed; and
  • the maximum permitted course load has not been exceeded.

The decision tree can first test whether the prerequisite has been passed. If not, registration is rejected immediately. If yes, the system then checks the course-load condition.

9.13 Decision Trees with Multiple Conditions

Consider a simplified bank withdrawal rule:

  • the PIN must be correct;
  • the requested amount must be positive;
  • the available balance must be sufficient.
PIN Correct? No → Reject Yes ↓ Amount > 0? No → Invalid Amount Yes ↓ Balance ≥ Amount? Yes → Approve Withdrawal No → Insufficient Balance

The tree demonstrates that some conditions are evaluated only if earlier requirements are satisfied.

9.14 Order of Decisions

The order of conditions in a decision tree can affect clarity and efficiency even when the final logical result is the same.

Example

In an authentication system, it may be more sensible to check whether an account exists before performing other account-specific checks. If the account does not exist, later checks are unnecessary.

Good decision ordering can:

  • eliminate impossible paths early;
  • avoid unnecessary processing;
  • improve readability;
  • reflect important business or security rules.

9.15 Decision Table and Decision Tree Compared

Feature Decision Table Decision Tree
Representation Tabular Branching graphical structure
Main Strength Shows condition combinations systematically Shows decision order and paths clearly
Useful For Many interacting conditions and rules Sequential decision logic
Completeness Checking Very strong when all combinations are listed Requires careful inspection of branches
Large Problems Can become wide Can become deep and visually complex
Programming Translation Often maps to combinations of conditions Often maps naturally to nested decisions

9.16 Translating Decision Tables into Pseudocode

Decision tables can be translated into conditional statements after the rules are understood.

Example

Suppose a student qualifies for a special academic award if:

  • GPA is at least 4.50; and
  • there is no outstanding disciplinary restriction.
IF GPA >= 4.50 AND disciplinary_restriction = FALSE THEN DISPLAY "Eligible" ELSE DISPLAY "Not Eligible" END IF

The decision table helps establish the rule, while the pseudocode expresses the rule in algorithmic form.

9.17 Translating Decision Trees into Pseudocode

Decision trees frequently translate into nested IF structures.

Example
IF account_exists THEN IF account_locked THEN DISPLAY "Access denied" ELSE IF password_correct THEN DISPLAY "Access granted" ELSE DISPLAY "Incorrect password" END IF END IF ELSE DISPLAY "Account not found" END IF

The nested structure follows the same sequence of questions represented in the decision tree.

9.18 Applied Case Study: Student Result Classification

Suppose scores must be validated and classified according to the following simplified rules:

  • Score below 0 or above 100: Invalid.
  • 70–100: A.
  • 60–69: B.
  • 50–59: C.
  • 45–49: D.
  • 40–44: E.
  • 0–39: F.
READ score IF score < 0 OR score > 100 THEN DISPLAY "Invalid" ELSE IF score >= 70 THEN DISPLAY "A" ELSE IF score >= 60 THEN DISPLAY "B" ELSE IF score >= 50 THEN DISPLAY "C" ELSE IF score >= 45 THEN DISPLAY "D" ELSE IF score >= 40 THEN DISPLAY "E" ELSE DISPLAY "F" END IF
Tracing Selected Cases
Score Result
78A
62B
47D
39F
105Invalid

9.19 Applied Case Study: Loan Eligibility

Consider a simplified illustration in which a loan request may proceed only if:

  • the applicant's account is active;
  • the applicant satisfies the stated minimum income condition;
  • the requested amount does not exceed an applicable limit.
Condition / Action Rule 1 Rule 2 Rule 3 Rule 4
Account active? No Yes Yes Yes
Income condition satisfied? — No Yes Yes
Amount within limit? — — No Yes
Proceed X
Reject / Stop X X X

The table shows that later conditions become irrelevant once an earlier mandatory requirement fails.

9.20 Choosing an Appropriate Solution Representation

Algorithms, flowcharts, pseudocode, decision tables and decision trees are complementary tools. The problem solver should select the representation that makes the logic easiest to understand and verify.

Situation Useful Representation
Simple ordered calculations Algorithm or pseudocode
Need to visualize overall flow Flowchart
Many combinations of conditions Decision table
Sequential branching decisions Decision tree
Preparing directly for programming Pseudocode
Key Principle

The purpose of a design representation is to clarify the solution. A complicated representation that makes the logic harder to understand defeats its purpose.

Chapter Summary
  • Decision-oriented problems require actions to be selected according to conditions.
  • A decision table represents combinations of conditions and corresponding actions in tabular form.
  • Each decision-table column normally represents one rule.
  • Complete tables show all relevant combinations, while reduced tables combine rules where some conditions do not affect the result.
  • A decision tree represents conditions and actions as branching paths.
  • Decision trees make the order of decisions particularly clear.
  • Decision tables are especially useful for checking combinations of several conditions.
  • Decision trees often translate naturally into nested conditional statements.
  • The order of decisions can affect efficiency and clarity.
  • Decision tables and decision trees complement flowcharts and pseudocode rather than replacing them.
  • The most appropriate representation depends on the structure of the problem.

CHAPTER TEN

Fundamentals of Programming for Problem Solving

The earlier chapters have concentrated on understanding problems and designing solutions. Programming is the stage at which a designed solution is expressed in a formal language that a computer system can process.

A beginner may be tempted to start by memorizing programming commands. However, successful programming depends more fundamentally on clear problem analysis, correct algorithms and sound logical thinking. Programming syntax provides a way to express the solution; it does not replace the reasoning required to discover that solution.

This chapter introduces the essential concepts required to translate simple algorithms into programs, with illustrations in Python and C.

10.2 Meaning of Programming

Programming

Programming is the process of designing, writing, testing, debugging and maintaining instructions expressed in a programming language so that a computer can perform specified tasks.

Programming therefore involves more than typing code. A complete programming task may include:

  • understanding the problem;
  • designing the algorithm;
  • choosing suitable data representations;
  • writing source code;
  • testing the program;
  • correcting errors;
  • improving the solution.

10.3 Programming Language

Programming Language

A programming language is a formal language with defined syntax and meaning that allows programmers to express instructions and computational processes for execution by a computer system.

Examples include:

  • C;
  • Python;
  • Java;
  • C++;
  • JavaScript;
  • C#.

Programming languages differ in syntax and design philosophy, but fundamental ideas such as variables, expressions, conditions and repetition occur across many languages.

10.4 From Problem to Executable Program

A sound programming workflow can be represented as:

  1. Define the problem.
  2. Analyse inputs, outputs, rules and constraints.
  3. Develop an algorithm.
  4. Represent the algorithm using pseudocode or another design tool.
  5. Translate the solution into source code.
  6. Run or compile the program.
  7. Test with selected inputs.
  8. Debug and refine the program.
Important

Writing code before understanding the problem often leads to unnecessary rewriting because implementation begins before the required logic has been established.

10.5 Source Code and Program Translation

Source Code

Source code is the human-readable form of a program written using the rules of a programming language.

A processor ultimately executes machine-level instructions. Therefore, source code must be translated or executed through an appropriate language implementation.

10.6 Compiler and Interpreter

Compiler:

Compiler

A compiler translates source code into another form, commonly machine code or an intermediate representation, before the resulting program is executed.

C implementations commonly use compilation to produce executable machine code.

Interpreter:

Interpreter

An interpreter executes program instructions through a language runtime without requiring the programmer to manually produce a separate native executable before each ordinary run.

Python programs are commonly executed through the Python runtime environment.

Technical Clarification

Modern language implementations may combine compilation and interpretation internally. The important introductory distinction is that source code requires a translation or execution environment before the processor can carry out the intended operations.

10.7 Syntax and Semantics

Syntax

Syntax is the set of grammatical rules that determines how valid statements are written in a programming language.

Semantics

Semantics concerns the meaning or effect of syntactically valid program statements.

Example

In Python:

print("Hello")

is syntactically valid and means that the text Hello should be displayed.

If the required parentheses or quotation marks are used incorrectly, the program may violate the language syntax.

10.8 Variables

Variable

A variable is a named program element used to refer to a value that may be stored, read or changed during execution.

Examples include:

score = 75 age = 18 total = 0

The value associated with a variable may change:

count = 5 count = count + 1

After the second statement, count has the value 6.

10.9 Constants and Literals

Literal

A literal is a value written directly in source code, such as 25, 3.5, 'A' or "Student".

A constant represents a value that is intended not to change during a particular computation or program design.

Example

In the formula for the area of a circle, π acts as a constant while the radius may vary from one calculation to another.

10.10 Data Types

Data Type

A data type describes the kind of value represented in a program and determines the operations that are meaningful for that value.

Common basic data types include:

Type Typical Values Example Use
Integer −5, 0, 17, 250 Age, quantity, count
Floating-Point 3.14, 72.5, −0.25 Average, temperature, measurement
Character 'A', 'Y', '7' Single symbol
String "Kehinde", "Computer Science" Name or text
Boolean True / False Logical conditions

The exact data types and their representation differ among languages.

10.11 Identifiers and Naming

Identifier

An identifier is a name used to refer to a program element such as a variable or function.

Meaningful identifiers improve readability.

Naming Example

Less descriptive:

x = p * q

More descriptive:

total_cost = unit_price * quantity

Both may perform the same arithmetic, but the second statement communicates its purpose more clearly.

Naming rules differ among languages, but identifiers generally must follow the language's lexical rules and must not conflict improperly with reserved keywords.

10.12 Assignment Statements

Assignment stores or associates a value with a variable.

total = 50 average = total / 5 balance = balance - withdrawal

The equals symbol in an assignment does not necessarily express mathematical equality in the ordinary algebraic sense. It directs the program to evaluate the expression on the right and assign the result to the variable on the left.

Example
x = 4 x = x + 3

The second statement means:

Take the current value 4, add 3, and assign 7 back to x.

10.13 Arithmetic Operators

Operation Python / C Symbol Example
Addition + a + b
Subtraction - a - b
Multiplication * a * b
Division / a / b
Remainder % a % b
Remainder Example

17 % 5 gives 2 because:

17 = (3 × 5) + 2.

The remainder operator is useful in tasks such as determining whether an integer is even.

10.14 Operator Precedence

Programming languages define rules that determine the order in which operations are evaluated.

Example
result = 2 + 3 * 4

Multiplication is performed before addition:

3 × 4 = 12

2 + 12 = 14

Therefore, result = 14.

Parentheses can make the intended order explicit:

result = (2 + 3) * 4

Now the result is 20.

Programming Practice

When there is any risk of ambiguity, use parentheses to make the intended order of evaluation clear.

10.15 Expressions

Expression

An expression is a combination of values, variables, operators and function calls that can be evaluated to produce a value.

Examples include:

length * width total / count score >= 50 age + 1

Expressions may be arithmetic, relational or logical.

10.16 Input Statements

Programs often require values from users.

Python Input:

name = input("Enter your name: ")

The input() function returns textual input. Numerical input usually requires conversion.

age = int(input("Enter your age: ")) score = float(input("Enter your score: "))

C Input:

In introductory C programs, scanf() can be used to obtain formatted input.

int age; scanf("%d", &age);

The %d conversion specification is used here for an integer.

10.17 Output Statements

Python Output:

print("Welcome") print(total)

C Output:

printf("Welcome\n"); printf("%d\n", total);

The specific syntax differs, but the underlying purpose is the same: communicate a result to the user.

10.18 Relational Operators

Relational operators compare values and produce a logical result.

Operator Meaning
==Equal to
!=Not equal to
>Greater than
<Less than
>=Greater than or equal to
<=Less than or equal to
Important Distinction

In Python and C, = is used for assignment, while == is used to test equality.

10.19 Logical Operators

Logical operators combine or modify conditions.

Meaning Python C
Logical AND and &&
Logical OR or ||
Logical NOT not !
Example

A valid score may be represented in Python as:

score >= 0 and score <= 100

In C, the same logical condition can be expressed as:

score >= 0 && score <= 100

10.20 Implementing Sequence in Python and C

Consider the algorithm:

READ length READ width area = length × width DISPLAY area

Python:

length = float(input("Enter length: ")) width = float(input("Enter width: ")) area = length * width print("Area =", area)

C:

#include <stdio.h> int main(void) { float length, width, area; printf("Enter length: "); scanf("%f", &length); printf("Enter width: "); scanf("%f", &width); area = length * width; printf("Area = %.2f\n", area); return 0; }

Although the syntax differs, the logical sequence is identical.

10.21 Worked Program: Rectangle Area

Question

Write a simple program to calculate the area of a rectangle with length 12.5 cm and width 8 cm.

Given:

Length = 12.5 cm

Width = 8 cm

Required: Area.

Formula:

Area = Length × Width

Solution:

Area = 12.5 × 8 = 100 cm².

Answer: 100 cm².

Python:

length = 12.5 width = 8 area = length * width print("Area =", area, "cm²")

C:

#include <stdio.h> int main(void) { float length = 12.5f; float width = 8.0f; float area; area = length * width; printf("Area = %.2f cm^2\n", area); return 0; }

10.22 Worked Program: Average Score

Question

Calculate the average of the scores 65, 78 and 71.

Given: 65, 78, 71.

Required: Arithmetic mean.

Formula:

Average = Total / Number of Scores

Solution:

Total = 65 + 78 + 71 = 214

Average = 214 / 3 = 71.333...

Answer: Approximately 71.33.

Python:

score1 = 65 score2 = 78 score3 = 71 total = score1 + score2 + score3 average = total / 3 print("Average =", average)

C:

#include <stdio.h> int main(void) { float score1 = 65.0f; float score2 = 78.0f; float score3 = 71.0f; float total, average; total = score1 + score2 + score3; average = total / 3.0f; printf("Average = %.2f\n", average); return 0; }

10.23 Worked Program: Temperature Conversion

Question

Convert 25°C to degrees Fahrenheit.

Given: C = 25°C.

Required: F.

Formula:

F = (9/5)C + 32

Solution:

F = (9/5 × 25) + 32

F = 45 + 32

F = 77°F

Answer: 77°F.

Python:

celsius = 25 fahrenheit = (9 / 5) * celsius + 32 print("Fahrenheit =", fahrenheit)

C:

#include <stdio.h> int main(void) { float celsius = 25.0f; float fahrenheit; fahrenheit = (9.0f / 5.0f) * celsius + 32.0f; printf("Fahrenheit = %.2f\n", fahrenheit); return 0; }
Important C Detail

Using 9.0 / 5.0 makes floating-point division explicit. This avoids unintended integer-division behaviour that can occur when both operands are integers in C.

10.24 Errors in Programs

Programs may fail in different ways. Understanding the type of error helps determine how it should be corrected.

Syntax Error:

A syntax error occurs when source code violates the grammar of the programming language.

Python Example
print("Hello"

The closing parenthesis is missing, so the statement is syntactically incomplete.

Runtime Error:

A runtime error occurs while the program is executing.

Example

Attempting to divide a number by zero may cause a runtime failure or exception depending on the programming environment.

Logical Error:

Logical Error

A logical error occurs when a program runs but produces an incorrect result because the implemented logic is wrong.

Example

Suppose the intended rectangle formula is:

Area = Length × Width

but the program contains:

area = length + width

The statement may be syntactically valid and execute successfully, but the result is wrong.

10.25 Testing and Debugging

Testing

Testing is the systematic execution or evaluation of a program using selected cases in order to determine whether it behaves according to its specification.

Debugging

Debugging is the process of locating, understanding and correcting defects in a program.

Testing should include more than one convenient example.

Example: Rectangle Area Program
Length Width Expected Area Reason
5 4 20 Normal values
10.5 2 21 Decimal value
1 1 1 Simple small case

If the specification requires dimensions to be positive, later program versions should also test how invalid values such as zero or negative dimensions are handled.

Debugging by Tracing:

Suppose a program calculates the wrong average. The programmer can inspect:

  • the input values;
  • the calculated total;
  • the number used as the divisor;
  • the final average.

This mirrors the algorithm-tracing methods used before programming and demonstrates why careful algorithm design remains useful during debugging.

10.26 Relationship Between Algorithm, Pseudocode and Program

The relationship among these concepts can be summarized as follows.

Stage Purpose Example
Problem Analysis Determine what must be solved Identify input scores and required average
Algorithm Describe the logical solution Add scores and divide by number of scores
Pseudocode Express logic in structured textual form READ scores, calculate total, calculate average
Program Implement the solution in a language Python or C source code
Testing Check implementation against expected behaviour Use known scores and verify result
Integrated Example

Problem: Calculate the total cost of a purchase.

Inputs: Quantity and unit price.

Algorithm: Multiply quantity by unit price.

Pseudocode:

READ quantity READ unit_price total = quantity × unit_price DISPLAY total

Python:

quantity = int(input("Enter quantity: ")) unit_price = float(input("Enter unit price: ")) total = quantity * unit_price print("Total =", total)

If quantity = 4 and unit price = ₦2,500:

Total = 4 × ₦2,500 = ₦10,000.

Central Principle

Programming should be seen as the implementation of a carefully designed solution. The strongest beginner habit is to understand the problem first, establish the algorithm second, and write code only after the logic is clear.

Chapter Summary
  • Programming is the process of designing, writing, testing, debugging and maintaining computer instructions.
  • A programming language provides formal rules for expressing executable computational procedures.
  • Source code is the human-readable program written in a programming language.
  • Compilers and interpreters provide mechanisms through which source code is translated or executed.
  • Syntax concerns how statements are written, while semantics concerns their meaning.
  • Variables represent values that may change during program execution.
  • Data types describe the kinds of values represented in a program.
  • Assignment stores the result of an expression in a variable.
  • Arithmetic, relational and logical operators support calculations and conditions.
  • Input statements obtain data, while output statements communicate results.
  • The same algorithm can be implemented in different languages even when their syntax differs.
  • Python and C use different syntax but share fundamental programming ideas.
  • Syntax errors violate language grammar, runtime errors occur during execution, and logical errors produce incorrect behaviour despite successful execution.
  • Testing checks whether a program satisfies its specification, while debugging locates and corrects defects.
  • Problem analysis, algorithms, pseudocode and programming form successive stages of structured computational problem solving.

CHAPTER ELEVEN

Selection, Repetition and Program Logic

Most useful programs do more than execute a fixed sequence of statements. They make decisions and repeat operations. A banking application decides whether a withdrawal should be approved. A result-processing system assigns different grades to different scores. A payroll system repeatedly processes many employees. A search program examines data until the required item is found or the available data is exhausted.

The two programming ideas that make these behaviours possible are selection and repetition. Selection allows the program to choose among alternative actions. Repetition allows one or more statements to be executed repeatedly under controlled conditions.

These concepts were introduced earlier through algorithms, flowcharts and pseudocode. This chapter now develops them as actual programming logic using Python and C.

11.2 Control Structures in Programming

Control Structure

A control structure is a programming construct that determines the order in which program statements are executed.

Three fundamental control structures are:

  • Sequence — statements execute one after another.
  • Selection — one path is chosen according to a condition.
  • Repetition — statements are executed repeatedly.

A large proportion of introductory programming problems can be solved by combining these three structures appropriately.

Illustration

A program that reads a student's score, checks whether it is valid, assigns a grade and repeats the process for several students uses sequence, selection and repetition in one solution.

11.3 Boolean Expressions

Boolean Expression

A Boolean expression is an expression whose result is either true or false.

Examples include:

score >= 50 age < 18 balance >= withdrawal number % 2 == 0

The result of each expression depends on the current values of the variables involved.

Example

If score = 72, then:

score >= 50

evaluates to true.

If score = 35, the same expression evaluates to false.

11.4 Relational and Logical Operators

Relational operators compare values.

Operator Meaning Example
== Equal to x == 10
!= Not equal to x != 10
> Greater than x > 10
< Less than x < 10
>= Greater than or equal to x >= 10
<= Less than or equal to x <= 10

Logical operators combine conditions.

Meaning Python C
AND and &&
OR or ||
NOT not !
Compound Condition

Suppose an examination score is valid only if it lies between 0 and 100 inclusive.

Python:

score >= 0 and score <= 100

C:

score >= 0 && score <= 100

11.5 Simple Selection

Simple selection performs an action only when a condition is true.

Python:

score = 75 if score >= 70: print("Excellent performance")

C:

int score = 75; if (score >= 70) { printf("Excellent performance\n"); }

If the condition is false, the controlled statement is skipped.

11.6 Two-Way Selection

Two-way selection chooses between two alternatives.

Example: Pass or Fail

A score of at least 40 is considered a pass.

Python:

score = float(input("Enter score: ")) if score >= 40: print("Pass") else: print("Fail")

C:

#include <stdio.h> int main(void) { float score; printf("Enter score: "); scanf("%f", &score); if (score >= 40) { printf("Pass\n"); } else { printf("Fail\n"); } return 0; }

For score = 67, the output is Pass. For score = 28, the output is Fail.

11.7 Multiple Selection

Multiple selection is required when several possible outcomes exist.

Python Grade Classification
score = float(input("Enter score: ")) if score >= 70: print("A") elif score >= 60: print("B") elif score >= 50: print("C") elif score >= 45: print("D") elif score >= 40: print("E") else: print("F")

Python uses elif to represent additional alternatives after the first IF condition.

C Version:

if (score >= 70) { printf("A\n"); } else if (score >= 60) { printf("B\n"); } else if (score >= 50) { printf("C\n"); } else if (score >= 45) { printf("D\n"); } else if (score >= 40) { printf("E\n"); } else { printf("F\n"); }

Conditions should be ordered carefully. Testing score ≥ 40 before score ≥ 70 would cause a score of 80 to satisfy the lower condition too early if the logic were structured incorrectly.

11.8 Nested Selection

Nested Selection

Nested selection occurs when one selection structure is placed inside another selection structure.

Example: Simplified Withdrawal

Python:

pin_correct = True balance = 50000 withdrawal = 20000 if pin_correct: if withdrawal <= balance: print("Withdrawal approved") else: print("Insufficient balance") else: print("Incorrect PIN")

The balance check is performed only when authentication succeeds.

11.9 Compound Conditions

Sometimes several conditions must be true at the same time.

Example: Admission Condition

Suppose a candidate is eligible only if the examination score is at least 50 and the required document has been submitted.

Python:

score = 68 document_submitted = True if score >= 50 and document_submitted: print("Eligible") else: print("Not eligible")

The AND operator requires both conditions to be true.

An OR condition requires at least one of its component conditions to be true.

if day == "Saturday" or day == "Sunday": print("Weekend")

11.10 Selection in Python

Python uses indentation to indicate the statements that belong to an IF, ELIF or ELSE block.

temperature = 32 if temperature > 30: print("Hot") print("Drink water") else: print("Temperature is not above 30")
Python Structure

Indentation is part of Python's syntax. Statements belonging to the same control block must be indented consistently.

11.11 Selection in C

C usually uses braces to group statements belonging to a control structure.

if (temperature > 30) { printf("Hot\n"); printf("Drink water\n"); } else { printf("Temperature is not above 30\n"); }

Although braces may sometimes be omitted for a single controlled statement, using braces consistently can improve clarity for beginners.

11.12 Introduction to Repetition

Repetition

Repetition is the controlled execution of one or more statements multiple times.

Without repetition, processing one hundred students might require one hundred copies of the same statements. Loops allow the repeated operation to be written once and controlled systematically.

Repetition may be:

  • count-controlled;
  • condition-controlled;
  • sentinel-controlled.

11.13 Count-Controlled Repetition

Count-controlled repetition is appropriate when the number of required iterations is known.

Example: Display 1 to 5

Python:

for number in range(1, 6): print(number)
1 2 3 4 5

C:

for (int number = 1; number <= 5; number++) { printf("%d\n", number); }

11.14 Condition-Controlled Repetition

A condition-controlled loop continues while a condition remains true.

Example

Python:

count = 1 while count <= 5: print(count) count = count + 1

C:

int count = 1; while (count <= 5) { printf("%d\n", count); count = count + 1; }

The update statement is essential. If count never changes, the condition may remain true indefinitely.

11.15 Sentinel-Controlled Repetition

A sentinel value indicates the end of data when the number of entries is not known beforehand.

Example: Total Positive Values Until -1

Python:

total = 0 value = float(input("Enter value (-1 to stop): ")) while value != -1: total = total + value value = float(input("Enter value (-1 to stop): ")) print("Total =", total)

If the user enters 20, 15, 30 and then -1:

Total = 20 + 15 + 30 = 65.

11.16 The FOR Loop

A FOR loop is particularly suitable when iterating over a known range or collection.

Python:

for i in range(1, 11): print(i)

The call range(1, 11) produces values beginning at 1 and ending before 11, giving 1 through 10.

C:

for (int i = 1; i <= 10; i++) { printf("%d\n", i); }

The C FOR statement contains initialization, condition and update expressions.

11.17 The WHILE Loop

A WHILE loop checks its condition before each iteration.

Example: Countdown

Python:

count = 5 while count >= 1: print(count) count = count - 1 print("Go!")
5 4 3 2 1 Go!

11.18 Nested Loops

Nested Loop

A nested loop is a loop that appears inside another loop.

Nested loops are useful when a repeated operation itself contains another repeated operation.

Example: Coordinate Pairs

Python:

for row in range(1, 4): for column in range(1, 4): print(row, column)
1 1 1 2 1 3 2 1 2 2 2 3 3 1 3 2 3 3

For each value of row, the inner loop completes all three column values.

11.19 Counters and Accumulators

Counters and accumulators are fundamental in repetitive programs.

Counter

A counter records how many times a particular event has occurred.

Accumulator

An accumulator maintains a running total.

Example: Total and Count
total = 0 count = 0 for score in [60, 75, 80, 65]: total = total + score count = count + 1 average = total / count print("Total =", total) print("Average =", average)

Total = 280, Count = 4, Average = 70.

11.20 Input Validation Using Loops

A program should not always accept the first input blindly. A loop can repeatedly request input until an acceptable value is supplied.

Python Score Validation
score = float(input("Enter score from 0 to 100: ")) while score < 0 or score > 100: print("Invalid score") score = float(input("Enter score from 0 to 100: ")) print("Accepted score:", score)

If the first value is 120, the program rejects it and requests another value. If the next value is 78, it is accepted.

C Version:

float score; printf("Enter score from 0 to 100: "); scanf("%f", &score); while (score < 0 || score > 100) { printf("Invalid score\n"); printf("Enter score from 0 to 100: "); scanf("%f", &score); } printf("Accepted score: %.2f\n", score);

11.21 Combining Selection and Repetition

Real programs frequently make a decision during each iteration.

Example: Count Passes and Failures

Suppose five student scores are processed and a score of 40 or above is a pass.

Python:

passes = 0 failures = 0 for i in range(5): score = float(input("Enter score: ")) if score >= 40: passes = passes + 1 else: failures = failures + 1 print("Passes =", passes) print("Failures =", failures)

The loop repeats the processing five times, while the IF statement classifies each score.

11.22 Worked Program: Grade Classification

Question

Write a program that accepts a score from 0 to 100 and displays the corresponding grade using the following scale:

  • 70–100 = A
  • 60–69 = B
  • 50–59 = C
  • 45–49 = D
  • 40–44 = E
  • 0–39 = F

Given: A numeric score.

Required: Corresponding grade.

Important condition: Scores below 0 or above 100 are invalid.

Python Solution:

score = float(input("Enter score: ")) if score < 0 or score > 100: print("Invalid score") elif score >= 70: print("Grade A") elif score >= 60: print("Grade B") elif score >= 50: print("Grade C") elif score >= 45: print("Grade D") elif score >= 40: print("Grade E") else: print("Grade F")

C Solution:

#include <stdio.h> int main(void) { float score; printf("Enter score: "); scanf("%f", &score); if (score < 0 || score > 100) printf("Invalid score\n"); else if (score >= 70) printf("Grade A\n"); else if (score >= 60) printf("Grade B\n"); else if (score >= 50) printf("Grade C\n"); else if (score >= 45) printf("Grade D\n"); else if (score >= 40) printf("Grade E\n"); else printf("Grade F\n"); return 0; }

11.23 Worked Program: Sum and Average of Scores

Question

Read five scores, calculate their total and average, and display both results.

Given: Five scores.

Required: Total and average.

Formula:

Average = Total ÷ 5

Python Solution:

total = 0 for i in range(5): score = float(input("Enter score: ")) total = total + score average = total / 5 print("Total =", total) print("Average =", average)
Worked Values

Suppose the scores are 60, 75, 81, 64 and 70.

Total = 60 + 75 + 81 + 64 + 70 = 350

Average = 350 ÷ 5 = 70.

C Solution:

#include <stdio.h> int main(void) { float score, total = 0, average; for (int i = 1; i <= 5; i++) { printf("Enter score %d: ", i); scanf("%f", &score); total = total + score; } average = total / 5.0f; printf("Total = %.2f\n", total); printf("Average = %.2f\n", average); return 0; }

11.24 Worked Program: Multiplication Table

Question

Display the multiplication table of a number from 1 to 12.

If the input number is 5, the program should produce:

5 × 1 = 5 5 × 2 = 10 5 × 3 = 15 ... 5 × 12 = 60

Python Solution:

number = int(input("Enter a number: ")) for i in range(1, 13): result = number * i print(number, "x", i, "=", result)

C Solution:

#include <stdio.h> int main(void) { int number; printf("Enter a number: "); scanf("%d", &number); for (int i = 1; i <= 12; i++) { printf("%d x %d = %d\n", number, i, number * i); } return 0; }

11.25 Tracing Program Logic

Tracing remains useful after an algorithm has been converted to code. The programmer can follow variable values through the program and compare actual behaviour with expected behaviour.

Tracing a Loop
total = 0 for number in range(1, 5): total = total + number print(total)
Iteration number total before total after
1 1 0 1
2 2 1 3
3 3 3 6
4 4 6 10

The final output is 10.

Chapter Summary
  • Control structures determine the order in which program statements execute.
  • Sequence, selection and repetition are fundamental control structures.
  • Boolean expressions evaluate to true or false.
  • Relational operators compare values, while logical operators combine conditions.
  • Simple selection executes an action only when a condition is true.
  • Two-way selection chooses between two alternatives.
  • Multiple selection handles several possible outcomes.
  • Nested selection places one decision inside another.
  • Compound conditions use logical operators such as AND, OR and NOT.
  • Repetition allows one or more statements to execute repeatedly.
  • Count-controlled loops are appropriate when the number of repetitions is known.
  • Condition-controlled loops continue while a condition remains true.
  • Sentinel values can indicate the end of input when the number of data items is unknown.
  • FOR and WHILE loops provide important forms of repetition in Python and C.
  • Counters track occurrences, while accumulators maintain running totals.
  • Loops can be used for input validation.
  • Selection and repetition are frequently combined in practical programs.
  • Tracing helps verify program logic and identify defects.

CHAPTER TWELVE

Practical Problem Solving with Python and C

The purpose of programming in a problem-solving course is not simply to memorize commands. The real objective is to convert a clearly defined problem into a reliable computational solution. The programmer should understand the problem, identify the required data, design the algorithm, represent the logic clearly, implement the algorithm, test the program and refine the solution where necessary.

This chapter integrates the major ideas developed throughout the course. The examples demonstrate the complete path from problem statement to working program using Python and C.

Central Principle

The programming language changes the syntax of the solution, but the underlying reasoning remains the same. A correct algorithm can often be implemented in many languages.

12.2 The Complete Problem-Solving Cycle

A disciplined programming solution may follow the stages below:

  1. Identify the problem.
  2. Define the expected result.
  3. Analyse inputs, outputs, requirements and constraints.
  4. Develop the algorithm.
  5. Represent the solution using pseudocode, flowchart or another suitable design tool.
  6. Translate the solution into a programming language.
  7. Compile or execute the program.
  8. Test the program using suitable data.
  9. Debug defects.
  10. Evaluate whether the program satisfies the original problem.
  11. Refine the solution where necessary.

These stages are not always strictly linear. Testing may reveal that the original algorithm was incomplete, requiring the programmer to return to an earlier stage.

12.3 Translating a Problem into a Program

A programmer should not translate the problem statement directly into code without analysis. The task should first be reduced to precise computational requirements.

Example Problem

“Calculate the total price of goods purchased by a customer.”

This statement can be analysed as:

Inputs: Quantity and unit price.

Processing: Total = Quantity × Unit Price.

Output: Total price.

Possible constraints: Quantity should not be negative; unit price should not be negative.

The program becomes easier to write after these elements have been identified.

12.4 Developing a Program from an Algorithm

Problem: Area of a Circle

Input: Radius.

Formula:

Area = πr²

Algorithm:

START READ radius area = π × radius × radius DISPLAY area STOP

Python:

import math radius = float(input("Enter radius: ")) area = math.pi * radius * radius print("Area =", area)

C:

#include <stdio.h> int main(void) { const double PI = 3.141592653589793; double radius, area; printf("Enter radius: "); scanf("%lf", &radius); area = PI * radius * radius; printf("Area = %.2f\n", area); return 0; }

12.5 Program Testing Strategy

Testing should be planned. A program that produces the correct result for one example has not necessarily been tested adequately.

Useful test categories include:

  • normal data;
  • boundary data;
  • invalid data;
  • special cases.
Example: Grade Program
Score Reason Expected Result
75Normal A caseA
70Boundary of AA
69Immediately below AB
40Boundary of EE
39Immediately below pass rangeF
0Lowest valid scoreF
100Highest valid scoreA
-1Invalid low valueInvalid
101Invalid high valueInvalid

12.6 Debugging and Refinement

Debugging should be systematic rather than based on random changes.

A useful debugging process is:

  1. Observe the incorrect behaviour.
  2. Identify the smallest part of the program that may be responsible.
  3. Form a hypothesis about the defect.
  4. Inspect variable values or intermediate results.
  5. Correct one identified problem.
  6. Test again.
  7. Confirm that the correction did not introduce another defect.
Example

If the average of three scores is unexpectedly low, inspect the three input values, the total and the divisor separately. This is more effective than rewriting the entire program without evidence.

12.7 Practical Program: Simple Calculator

Problem

Read two numbers and an arithmetic operator. Perform addition, subtraction, multiplication or division according to the selected operator.

Inputs: First number, second number, operator.

Output: Result.

Special condition: Division by zero must be prevented.

Python:

first = float(input("Enter first number: ")) operator = input("Enter operator (+, -, *, /): ") second = float(input("Enter second number: ")) if operator == "+": print("Result =", first + second) elif operator == "-": print("Result =", first - second) elif operator == "*": print("Result =", first * second) elif operator == "/": if second != 0: print("Result =", first / second) else: print("Cannot divide by zero") else: print("Invalid operator")

C:

#include <stdio.h> int main(void) { double first, second; char operator; printf("Enter first number: "); scanf("%lf", &first); printf("Enter operator (+, -, *, /): "); scanf(" %c", &operator); printf("Enter second number: "); scanf("%lf", &second); if (operator == '+') printf("Result = %.2f\n", first + second); else if (operator == '-') printf("Result = %.2f\n", first - second); else if (operator == '*') printf("Result = %.2f\n", first * second); else if (operator == '/') { if (second != 0) printf("Result = %.2f\n", first / second); else printf("Cannot divide by zero\n"); } else printf("Invalid operator\n"); return 0; }

12.8 Practical Program: Even or Odd Number

Problem

Determine whether an integer is even or odd.

Principle: An integer is even if division by 2 leaves remainder 0.

Python:

number = int(input("Enter an integer: ")) if number % 2 == 0: print("Even") else: print("Odd")

C:

#include <stdio.h> int main(void) { int number; printf("Enter an integer: "); scanf("%d", &number); if (number % 2 == 0) printf("Even\n"); else printf("Odd\n"); return 0; }

12.9 Practical Program: Largest of Three Numbers

Problem

Read three numbers and determine the largest value.

Algorithm:

READ A READ B READ C largest = A IF B > largest THEN largest = B END IF IF C > largest THEN largest = C END IF DISPLAY largest

Python:

a = float(input("Enter first number: ")) b = float(input("Enter second number: ")) c = float(input("Enter third number: ")) largest = a if b > largest: largest = b if c > largest: largest = c print("Largest =", largest)

C:

#include <stdio.h> int main(void) { double a, b, c, largest; printf("Enter three numbers: "); scanf("%lf %lf %lf", &a, &b, &c); largest = a; if (b > largest) largest = b; if (c > largest) largest = c; printf("Largest = %.2f\n", largest); return 0; }

12.10 Practical Program: Student Result Processor

Problem

Read five subject scores, calculate the total and average, and display a simple performance status. Assume an average of 50 or above is a pass.

Inputs: Five scores.

Outputs: Total, average and status.

Python:

total = 0 for i in range(1, 6): score = float(input("Enter score " + str(i) + ": ")) while score < 0 or score > 100: print("Invalid score") score = float(input("Enter score " + str(i) + ": ")) total = total + score average = total / 5 print("Total =", total) print("Average =", average) if average >= 50: print("Status = Pass") else: print("Status = Fail")
Worked Values

For scores 70, 65, 55, 80 and 60:

Total = 70 + 65 + 55 + 80 + 60 = 330

Average = 330 ÷ 5 = 66

Since 66 ≥ 50, Status = Pass.

12.11 Practical Program: Simple Interest Calculator

Question

Calculate simple interest on ₦120,000 at 7% per year for 3 years.

Given:

P = ₦120,000

R = 7%

T = 3 years

Formula:

I = PRT / 100

Solution:

I = (120,000 × 7 × 3) / 100

I = ₦25,200

Answer: Simple Interest = ₦25,200.

Python:

principal = float(input("Enter principal: ")) rate = float(input("Enter rate: ")) time = float(input("Enter time in years: ")) interest = principal * rate * time / 100 print("Simple interest =", interest)

C:

#include <stdio.h> int main(void) { double principal, rate, time, interest; printf("Enter principal: "); scanf("%lf", &principal); printf("Enter rate: "); scanf("%lf", &rate); printf("Enter time in years: "); scanf("%lf", &time); interest = principal * rate * time / 100.0; printf("Simple interest = %.2f\n", interest); return 0; }

12.12 Practical Program: Sum of Integers

Problem

Given a positive integer N, calculate:

1 + 2 + 3 + ... + N

For N = 5:

1 + 2 + 3 + 4 + 5 = 15.

Python:

n = int(input("Enter a positive integer: ")) total = 0 for number in range(1, n + 1): total = total + number print("Sum =", total)

C:

#include <stdio.h> int main(void) { int n; int total = 0; printf("Enter a positive integer: "); scanf("%d", &n); for (int number = 1; number <= n; number++) { total = total + number; } printf("Sum = %d\n", total); return 0; }

12.13 Practical Program: Factorial

Factorial

For a non-negative integer n, the factorial of n, written n!, is the product of all positive integers from 1 to n. By definition, 0! = 1.

For example:

5! = 5 × 4 × 3 × 2 × 1 = 120

Python:

n = int(input("Enter a non-negative integer: ")) if n < 0: print("Factorial is not defined here for negative integers") else: factorial = 1 for number in range(1, n + 1): factorial = factorial * number print("Factorial =", factorial)

C:

#include <stdio.h> int main(void) { int n; unsigned long long factorial = 1; printf("Enter a non-negative integer: "); scanf("%d", &n); if (n < 0) { printf("Invalid input\n"); } else { for (int number = 1; number <= n; number++) { factorial = factorial * number; } printf("Factorial = %llu\n", factorial); } return 0; }
Practical Limitation

Factorials grow extremely quickly. Fixed-size integer types in C can overflow for sufficiently large values of n. A correct mathematical algorithm therefore does not automatically imply that every numeric result can be stored in every programming data type.

12.14 Practical Program: Prime Number Test

Prime Number

A prime number is an integer greater than 1 that has exactly two positive divisors: 1 and itself.

To determine whether n is prime, a simple introductory algorithm can test whether any integer from 2 up to n − 1 divides n exactly. A more efficient elementary version needs to test divisors only up to the square root of n.

Python:

number = int(input("Enter an integer: ")) if number < 2: print("Not prime") else: is_prime = True divisor = 2 while divisor * divisor <= number: if number % divisor == 0: is_prime = False break divisor = divisor + 1 if is_prime: print("Prime") else: print("Not prime")
Example

For number = 29:

2 does not divide 29.

3 does not divide 29.

4 does not divide 29.

5 does not divide 29.

Since 6² exceeds 29, no larger divisor below 29 needs to be tested. Therefore, 29 is prime.

12.15 Practical Program: Searching a List

Searching is a fundamental computing problem. One simple method is linear search, which examines items one after another until the target is found or the collection ends.

Example

List: 15, 22, 9, 31, 18

Target: 31

The search compares 31 with 15, then 22, then 9, and finally 31. The target is found at the fourth position.

Python:

numbers = [15, 22, 9, 31, 18] target = int(input("Enter number to find: ")) found = False for number in numbers: if number == target: found = True break if found: print("Found") else: print("Not found")

C:

#include <stdio.h> int main(void) { int numbers[] = {15, 22, 9, 31, 18}; int target; int found = 0; printf("Enter number to find: "); scanf("%d", &target); for (int i = 0; i < 5; i++) { if (numbers[i] == target) { found = 1; break; } } if (found) printf("Found\n"); else printf("Not found\n"); return 0; }

12.16 Practical Program: Menu-Driven Application

A menu-driven program allows the user to select an operation from a displayed list.

Python Example
print("1. Add") print("2. Subtract") print("3. Multiply") choice = int(input("Choose an option: ")) a = float(input("Enter first number: ")) b = float(input("Enter second number: ")) if choice == 1: print("Result =", a + b) elif choice == 2: print("Result =", a - b) elif choice == 3: print("Result =", a * b) else: print("Invalid option")

The menu converts one general program into several selectable operations.

12.17 Functions and Problem Decomposition

Function

A function is a named block of program statements designed to perform a specific task, often using input values and possibly returning a result.

Functions support problem decomposition by allowing a large problem to be divided into smaller tasks.

Example

A student result program may be decomposed into functions that:

  • read scores;
  • validate scores;
  • calculate average;
  • determine grade;
  • display result.

Each function can be developed and tested separately.

12.18 Python Functions

Python defines a function using the def keyword.

Example: Square of a Number
def square(number): return number * number value = float(input("Enter number: ")) result = square(value) print("Square =", result)

The function receives one parameter, calculates the square and returns the result.

Function for Average:

def average(a, b, c): return (a + b + c) / 3 result = average(70, 80, 60) print(result)

The result is 70.

12.19 C Functions

C also supports functions.

Example: Square of a Number
#include <stdio.h> double square(double number) { return number * number; } int main(void) { double value; printf("Enter number: "); scanf("%lf", &value); printf("Square = %.2f\n", square(value)); return 0; }

The square function can be reused whenever the program needs to calculate a square.

12.20 Input Validation and Defensive Programming

Defensive Programming

Defensive programming is the practice of designing software to anticipate invalid input, unexpected conditions and possible misuse so that the program behaves predictably and safely.

Examples include:

  • checking score ranges before grading;
  • preventing division by zero;
  • checking that quantities are not negative;
  • checking that required values are supplied;
  • checking that menu choices are valid.
Example: Division

Unsafe Logic:

result = first / second

Improved Logic:

if second != 0: result = first / second print(result) else: print("Division by zero is not allowed")

12.21 Testing with Normal, Boundary and Invalid Data

A reliable test strategy should deliberately include different categories of input.

Normal Data

Normal data consists of typical valid values expected during ordinary use.

Boundary Data

Boundary data consists of values at or immediately around important limits in the problem specification.

Invalid Data

Invalid data consists of values that violate the stated requirements or constraints.

Example: Age Requirement

Suppose a service requires age ≥ 18.

Input Type Expected Outcome
25NormalEligible
18BoundaryEligible
17Boundary-adjacentNot eligible
-4InvalidReject as invalid age

12.22 Comparing Python and C Solutions

Python and C can implement the same algorithm even though their syntax and execution models differ.

Feature Python C
Block Structure Indentation Usually braces
Statement Terminator Usually line ending Semicolon
Variable Declaration Usually inferred from assigned values Variables are explicitly declared with types
Input input() Functions such as scanf()
Output print() printf()
Logical AND and &&
Logical OR or ||
Same Algorithm, Different Syntax

Pseudocode:

READ number IF number MOD 2 = 0 THEN DISPLAY "Even" ELSE DISPLAY "Odd" END IF

Both Python and C implement the same logical procedure even though the statements are written differently.

12.23 Program Evaluation and Refinement

A program should be evaluated against the original problem rather than judged only by whether it runs.

Evaluation questions include:

  • Does the program produce the correct result?
  • Does it handle required boundary cases?
  • Does it reject invalid input where necessary?
  • Is the code understandable?
  • Is unnecessary repetition present?
  • Can the program be divided into clearer functions?
  • Does the output communicate results clearly?
  • Does the program satisfy the original requirements?
Refinement Example

A first version of a result program may accept one score and produce a grade. A refined version may:

  • validate the score;
  • process many students;
  • count grades;
  • calculate class average;
  • use functions to separate tasks;
  • provide clearer output.

Refinement improves the solution while preserving its fundamental purpose.

12.24 Integrating the Problem-Solving Process

The central ideas of this course can now be combined into one complete example.

Integrated Case Study: Student Performance Program

A lecturer wants a program that receives the scores of several students, validates each score, calculates the class average and reports how many students passed or failed.

Problem Identification:

The problem is to process multiple student scores and produce class-performance information.

Inputs:

  • number of students;
  • score for each student.

Constraints:

  • number of students must be positive;
  • each score must lie between 0 and 100;
  • score ≥ 40 represents a pass.

Outputs:

  • class average;
  • number of passes;
  • number of failures.

Algorithm:

READ number_of_students total = 0 passes = 0 failures = 0 REPEAT for each student READ score WHILE score < 0 OR score > 100 DISPLAY "Invalid score" READ score END WHILE total = total + score IF score >= 40 THEN passes = passes + 1 ELSE failures = failures + 1 END IF END REPEAT average = total / number_of_students DISPLAY average DISPLAY passes DISPLAY failures

Python Implementation:

students = int(input("Enter number of students: ")) while students <= 0: print("Number of students must be positive") students = int(input("Enter number of students: ")) total = 0 passes = 0 failures = 0 for i in range(1, students + 1): score = float(input("Enter score for student " + str(i) + ": ")) while score < 0 or score > 100: print("Invalid score") score = float(input("Enter score for student " + str(i) + ": ")) total = total + score if score >= 40: passes = passes + 1 else: failures = failures + 1 average = total / students print("Class average =", average) print("Passes =", passes) print("Failures =", failures)

Worked Example:

Suppose there are five students with scores:

75, 48, 32, 66, 59

Total = 75 + 48 + 32 + 66 + 59 = 280

Average = 280 ÷ 5 = 56

Passes: 75, 48, 66, 59 = 4

Failures: 32 = 1

Therefore:

Class Average = 56

Passes = 4

Failures = 1

This example combines nearly every important idea developed in the course: problem identification, requirements, constraints, algorithm design, pseudocode, validation, repetition, selection, counters, accumulators, programming, testing and evaluation.

Concluding Academic Comment

Problem solving is the foundation on which effective programming is built. A programming language provides a notation for expressing a solution, but the quality of the final program depends largely on the quality of the reasoning that precedes the code. Students who learn to identify problems accurately, analyse requirements, design algorithms, test assumptions and evaluate results develop skills that remain useful even when programming languages and technologies change.

The most transferable skill gained from COS 102 is therefore not familiarity with one particular language. It is the ability to approach an unfamiliar problem systematically, reduce it to manageable parts, express the solution precisely and verify that the implemented result actually solves the original problem.

Chapter Summary
  • Practical programming should follow a disciplined problem-solving process rather than begin with code.
  • A complete solution normally progresses from problem identification through analysis, algorithm design, implementation, testing and refinement.
  • Python and C can implement the same algorithm even though their syntax differs.
  • Programs should be tested with normal, boundary, invalid and special-case data where appropriate.
  • Debugging is most effective when based on evidence and controlled testing rather than random modification.
  • Simple programs can demonstrate calculations, selection, repetition, searching and menu-driven interaction.
  • Functions support decomposition by separating a large program into smaller reusable tasks.
  • Defensive programming anticipates invalid input and exceptional conditions.
  • Factorial calculations illustrate repetition and the practical limitations of fixed-size numeric data types.
  • Prime-number testing illustrates how an algorithm can be improved by reducing unnecessary work.
  • Linear search demonstrates systematic examination of data until a target is found or the collection ends.
  • Program evaluation considers correctness, clarity, validation, maintainability and conformity with requirements.
  • The same problem-solving concepts apply across different programming languages.
  • The central objective of COS 102 is to develop systematic computational reasoning that can be transferred to future programming and computing courses.