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.
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
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.
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 is the data supplied to the system. Processing consists of the operations performed on that data. Output is the information or result produced.
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
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.
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 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.
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 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:
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.
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 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.
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.
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.
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.
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:
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.
- 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.
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 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 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
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?
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 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:
- What information is available?
- What result is required?
- What relationships connect the available information to the required result?
- What restrictions or special cases must be considered?
Worked Analysis: Celsius to Fahrenheit Conversion:
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.
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.
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:
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:
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.
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
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.
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 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.
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
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.
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
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.
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:
A well-defined problem has a sufficiently clear initial situation, objective, relevant conditions and criteria for determining whether a proposed solution is acceptable.
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:
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.
“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.
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.
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.
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.
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:
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.
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:
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:
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.
- 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.
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
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.
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.
Inputs: Length and width.
Processing: Multiply length by width.
Output: Area.
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: “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.
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: 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.
- Understand the problem.
- Identify required inputs.
- Identify required outputs.
- Identify the relationships and conditions involved.
- Break the solution into logical steps.
- Arrange the steps in the correct order.
- Test the steps using representative values.
- Refine the algorithm if necessary.
Problem: Convert Celsius temperature to Fahrenheit.
Input: Celsius temperature C.
Output: Fahrenheit temperature F.
Relationship: F = (9/5)C + 32.
If C = 20, then F = 68.
3.10 Sequence in Algorithms
Sequence is the execution of algorithmic steps one after another in a specified order.
Many simple problems consist entirely of sequence.
A customer buys 6 books at ₦2,500 each.
For quantity = 6 and unit price = 2500:
Total = 6 × 2500 = ₦15,000.
3.11 Selection in Algorithms
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.
Suppose a score of 40 or above is classified as a pass.
For score = 65, the algorithm displays “Pass.” For score = 32, it displays “Fail.”
Multiple Selection:
Some problems require more than two alternatives.
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, 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.
Suppose the numbers 1 to 5 must be displayed.
The output is:
1, 2, 3, 4, 5
3.13 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.
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:
If principal = ₦60,000, rate = 5 and time = 3 years:
Interest = (60,000 × 5 × 3) / 100 = ₦9,000.
Example: Average of Four Numbers:
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:
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:
3.16 Algorithms for Repetitive Problems
Some tasks involve repeated accumulation or processing.
Example: Sum of the Numbers 1 to 5:
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
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?
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.
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 | 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. |
This same algorithm can later be implemented in Python, C or another programming language without changing its essential logic.
- 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
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.
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.
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
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.
A greedy strategy constructs a solution by repeatedly selecting a locally preferred option according to a chosen criterion.
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.
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.
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 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
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.
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.
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.
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.
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
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: 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
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.
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.
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
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.
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.
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. |
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.
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.
- 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.
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 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.
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.
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.
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.
Suppose a program must calculate a student's GPA. At an early stage, the problem can be abstracted as:
- Obtain valid course grades and units.
- Convert grades to grade points.
- Calculate weighted grade points.
- Divide total weighted points by total units.
- Display the GPA.
The detailed programming statements can be developed later.
5.6 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.
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.
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:
- identifying a familiar problem;
- identifying the structure that made its solution work;
- comparing that structure with the new problem;
- identifying important differences;
- adapting rather than blindly copying the old solution;
- testing whether the adapted solution works.
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 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:
- state the problem clearly;
- define important constraints;
- generate multiple solution ideas;
- group related ideas;
- eliminate ideas that violate essential constraints;
- compare remaining alternatives;
- select promising options for further analysis.
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 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.
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.
Suppose a computer cannot connect to the Internet. A systematic approach might test:
- whether Wi-Fi or Ethernet is enabled;
- whether the device has obtained network configuration;
- whether other devices can connect;
- whether the router is operating;
- 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 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:
- Observe the problem.
- Propose a possible explanation.
- Determine what evidence would be expected if the explanation were correct.
- Perform a test.
- Compare the result with the expected evidence.
- Accept, reject or revise the hypothesis.
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.
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 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.
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.
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.
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.
Suppose users complain that a university portal becomes slow during registration.
- Abstraction: Ignore visual details that do not affect performance and focus on request processing, database activity, network behaviour and server resources.
- Brainstorming: Generate possible causes such as database bottlenecks, inefficient code, insufficient server capacity or large files.
- Hypothesis testing: Measure each suspected cause.
- Reduction: Reproduce the problem on one specific page or operation rather than analysing the entire system at once.
- 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:
Ignore unrelated student information such as course registration and academic history. Focus on account identity, credential verification, account status and access decision.
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:
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:
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.
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.
- 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 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.
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?
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 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:
- Where am I now?
- Where do I need to be?
- What is the important difference?
- What action can reduce that difference?
- What new subproblem must be solved before that action can be taken?
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.
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
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:
- Select the focal object.
- Select one or more unrelated objects.
- List important attributes of the unrelated objects.
- Combine those attributes with the focal object.
- Interpret the combinations creatively.
- Evaluate useful ideas.
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 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.
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 | 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 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:
- Define the exact question.
- Identify likely authoritative sources.
- Search using specific terminology.
- Compare multiple reliable sources where necessary.
- Check whether the information is current enough for the topic.
- Test technical recommendations before relying on them in production.
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.
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 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.
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
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.
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.
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
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.
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:
A counterexample is a specific case showing that a general statement is false.
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 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:
- Divide: Break the original problem into smaller subproblems.
- Conquer: Solve the subproblems.
- 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.
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.
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.
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:
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:
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:
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.
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.
- 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
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.
Suppose a program receives the length and width of a rectangle and calculates its area. The logical flow is:
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. |
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.
Problem: Calculate the total cost of a quantity of goods.
Input: Quantity and unit price.
Processing: Total = Quantity × Unit Price.
Output: Total cost.
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.
A student passes if the score is at least 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.
Suppose the following grading rules apply:
| Score | Grade |
|---|---|
| 70–100 | A |
| 60–69 | B |
| 50–59 | C |
| 45–49 | D |
| 40–44 | E |
| Below 40 | F |
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.
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.
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
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.
7.11 Flowchart for Comparison Problems
Let the numbers be A, B and C.
One logical approach is:
- Read A, B and C.
- Assume A is the largest.
- If B is greater than the current largest, replace the largest with B.
- If C is greater than the current largest, replace the largest with C.
- 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.
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.
Initialize:
Total = 0
Count = 1
While Count ≤ 5:
- Read a score.
- Add the score to Total.
- 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.
A withdrawal may require two conditions:
- The PIN must be correct.
- 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.
- Identify the required result.
- Identify the input data.
- Determine the processing operations.
- Identify decisions and their possible outcomes.
- Identify repeated operations.
- Arrange the operations logically.
- Draw the appropriate symbols and connections.
- Trace the flowchart with sample data.
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.
Suppose a flowchart calculates the sum of integers from 1 to N. Let N = 4.
| Iteration | Count | Total After Addition |
|---|---|---|
| 1 | 1 | 1 |
| 2 | 2 | 3 |
| 3 | 3 | 6 |
| 4 | 4 | 10 |
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.
- 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 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:
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:
Improved:
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
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.
The statement count = count + 1 should be interpreted operationally: obtain the current value of count, add 1, and store the result back in count.
If count currently contains 7, then:
changes its value to 8.
8.6 Input and Output Statements
Input statements obtain data required by the algorithm. Output statements communicate results.
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 | / |
| Remainder | MOD |
Suppose three scores are 62, 74 and 80.
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 > B | A is greater than B |
| A < B | A is less than B |
| A >= B | A is greater than or equal to B |
| A <= B | A is less than or equal to B |
| A = B | A is equal to B in the intended pseudocode convention |
| A != B | A is not equal to B |
Logical operators combine conditions.
8.9 Sequence in Pseudocode
Sequence means executing statements in the order in which they appear.
Given: Radius r.
Required: Area A.
Formula: A = πr².
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 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.
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.
A decision can also occur inside another decision.
8.13 Repetition Using WHILE
A WHILE structure repeats statements as long as its condition remains true.
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.
The counter begins at 1 and increases once after each score. When it reaches 11, the condition becomes false.
8.15 Accumulators and Counters
A counter is a variable used to record the number of times an event or operation occurs.
An accumulator is a variable used to maintain a running total as values are processed.
Suppose the scores are 55, 70, 65 and 90.
| Score | Total Before | Total After |
|---|---|---|
| 55 | 0 | 55 |
| 70 | 55 | 125 |
| 65 | 125 | 190 |
| 90 | 190 | 280 |
Average = 280 / 4 = 70.
8.16 Sentinel-Controlled Repetition
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.
Suppose positive sales amounts are entered and −1 indicates the end of input.
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.
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.
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.
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.
| Iteration | Count Used | 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.
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.
Pseudocode:
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.
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.
- 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.
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.
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
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
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.
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.
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?
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
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.
9.12 Constructing a Decision Tree
A useful procedure is:
- Identify the first relevant condition.
- Create a branch for each possible result.
- Determine whether another condition must be tested on each branch.
- Continue branching until a final action is reached.
- Check that all meaningful cases are represented.
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.
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.
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.
Suppose a student qualifies for a special academic award if:
- GPA is at least 4.50; and
- there is no outstanding disciplinary restriction.
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.
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.
| Score | Result |
|---|---|
| 78 | A |
| 62 | B |
| 47 | D |
| 39 | F |
| 105 | Invalid |
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 |
The purpose of a design representation is to clarify the solution. A complicated representation that makes the logic harder to understand defeats its purpose.
- 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 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
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:
- Define the problem.
- Analyse inputs, outputs, rules and constraints.
- Develop an algorithm.
- Represent the algorithm using pseudocode or another design tool.
- Translate the solution into source code.
- Run or compile the program.
- Test with selected inputs.
- Debug and refine the program.
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 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:
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:
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.
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 is the set of grammatical rules that determines how valid statements are written in a programming language.
Semantics concerns the meaning or effect of syntactically valid program statements.
In Python:
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
A variable is a named program element used to refer to a value that may be stored, read or changed during execution.
Examples include:
The value associated with a variable may change:
After the second statement, count has the value 6.
10.9 Constants and Literals
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.
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
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
An identifier is a name used to refer to a program element such as a variable or function.
Meaningful identifiers improve readability.
Less descriptive:
More descriptive:
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.
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.
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 |
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.
Multiplication is performed before addition:
3 × 4 = 12
2 + 12 = 14
Therefore, result = 14.
Parentheses can make the intended order explicit:
Now the result is 20.
When there is any risk of ambiguity, use parentheses to make the intended order of evaluation clear.
10.15 Expressions
An expression is a combination of values, variables, operators and function calls that can be evaluated to produce a value.
Examples include:
Expressions may be arithmetic, relational or logical.
10.16 Input Statements
Programs often require values from users.
Python Input:
The input() function returns textual input. Numerical input usually requires conversion.
C Input:
In introductory C programs, scanf() can be used to obtain formatted input.
The %d conversion specification is used here for an integer.
10.17 Output Statements
Python Output:
C Output:
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 |
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 | ! |
A valid score may be represented in Python as:
In C, the same logical condition can be expressed as:
10.20 Implementing Sequence in Python and C
Consider the algorithm:
Python:
C:
Although the syntax differs, the logical sequence is identical.
10.21 Worked Program: Rectangle Area
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:
C:
10.22 Worked Program: Average Score
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:
C:
10.23 Worked Program: Temperature Conversion
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:
C:
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.
The closing parenthesis is missing, so the statement is syntactically incomplete.
Runtime Error:
A runtime error occurs while the program is executing.
Attempting to divide a number by zero may cause a runtime failure or exception depending on the programming environment.
Logical Error:
A logical error occurs when a program runs but produces an incorrect result because the implemented logic is wrong.
Suppose the intended rectangle formula is:
Area = Length × Width
but the program contains:
The statement may be syntactically valid and execute successfully, but the result is wrong.
10.25 Testing and Debugging
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 is the process of locating, understanding and correcting defects in a program.
Testing should include more than one convenient example.
| 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 |
Problem: Calculate the total cost of a purchase.
Inputs: Quantity and unit price.
Algorithm: Multiply quantity by unit price.
Pseudocode:
Python:
If quantity = 4 and unit price = ₦2,500:
Total = 4 × ₦2,500 = ₦10,000.
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.
- 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
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.
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
A Boolean expression is an expression whose result is either true or false.
Examples include:
The result of each expression depends on the current values of the variables involved.
If score = 72, then:
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 | ! |
Suppose an examination score is valid only if it lies between 0 and 100 inclusive.
Python:
C:
11.5 Simple Selection
Simple selection performs an action only when a condition is true.
Python:
C:
If the condition is false, the controlled statement is skipped.
11.6 Two-Way Selection
Two-way selection chooses between two alternatives.
A score of at least 40 is considered a pass.
Python:
C:
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 uses elif to represent additional alternatives after the first IF condition.
C Version:
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 occurs when one selection structure is placed inside another selection structure.
Python:
The balance check is performed only when authentication succeeds.
11.9 Compound Conditions
Sometimes several conditions must be true at the same time.
Suppose a candidate is eligible only if the examination score is at least 50 and the required document has been submitted.
Python:
The AND operator requires both conditions to be true.
An OR condition requires at least one of its component conditions to be true.
11.10 Selection in Python
Python uses indentation to indicate the statements that belong to an IF, ELIF or ELSE block.
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.
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 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.
Python:
C:
11.14 Condition-Controlled Repetition
A condition-controlled loop continues while a condition remains true.
Python:
C:
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.
Python:
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:
The call range(1, 11) produces values beginning at 1 and ending before 11, giving 1 through 10.
C:
The C FOR statement contains initialization, condition and update expressions.
11.17 The WHILE Loop
A WHILE loop checks its condition before each iteration.
Python:
11.18 Nested Loops
A nested loop is a loop that appears inside another loop.
Nested loops are useful when a repeated operation itself contains another repeated operation.
Python:
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.
A counter records how many times a particular event has occurred.
An accumulator maintains a running total.
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.
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:
11.21 Combining Selection and Repetition
Real programs frequently make a decision during each iteration.
Suppose five student scores are processed and a score of 40 or above is a pass.
Python:
The loop repeats the processing five times, while the IF statement classifies each score.
11.22 Worked Program: Grade Classification
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:
C Solution:
11.23 Worked Program: Sum and Average of Scores
Read five scores, calculate their total and average, and display both results.
Given: Five scores.
Required: Total and average.
Formula:
Python Solution:
Suppose the scores are 60, 75, 81, 64 and 70.
Total = 60 + 75 + 81 + 64 + 70 = 350
Average = 350 ÷ 5 = 70.
C Solution:
11.24 Worked Program: Multiplication Table
Display the multiplication table of a number from 1 to 12.
If the input number is 5, the program should produce:
Python Solution:
C Solution:
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.
| 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.
- 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.
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:
- Identify the problem.
- Define the expected result.
- Analyse inputs, outputs, requirements and constraints.
- Develop the algorithm.
- Represent the solution using pseudocode, flowchart or another suitable design tool.
- Translate the solution into a programming language.
- Compile or execute the program.
- Test the program using suitable data.
- Debug defects.
- Evaluate whether the program satisfies the original problem.
- 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.
“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
Input: Radius.
Formula:
Algorithm:
Python:
C:
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.
| Score | Reason | Expected Result |
|---|---|---|
| 75 | Normal A case | A |
| 70 | Boundary of A | A |
| 69 | Immediately below A | B |
| 40 | Boundary of E | E |
| 39 | Immediately below pass range | F |
| 0 | Lowest valid score | F |
| 100 | Highest valid score | A |
| -1 | Invalid low value | Invalid |
| 101 | Invalid high value | Invalid |
12.6 Debugging and Refinement
Debugging should be systematic rather than based on random changes.
A useful debugging process is:
- Observe the incorrect behaviour.
- Identify the smallest part of the program that may be responsible.
- Form a hypothesis about the defect.
- Inspect variable values or intermediate results.
- Correct one identified problem.
- Test again.
- Confirm that the correction did not introduce another defect.
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
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:
C:
12.8 Practical Program: Even or Odd Number
Determine whether an integer is even or odd.
Principle: An integer is even if division by 2 leaves remainder 0.
Python:
C:
12.9 Practical Program: Largest of Three Numbers
Read three numbers and determine the largest value.
Algorithm:
Python:
C:
12.10 Practical Program: Student Result Processor
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:
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
Calculate simple interest on ₦120,000 at 7% per year for 3 years.
Given:
P = ₦120,000
R = 7%
T = 3 years
Formula:
Solution:
I = (120,000 × 7 × 3) / 100
I = ₦25,200
Answer: Simple Interest = ₦25,200.
Python:
C:
12.12 Practical Program: Sum of Integers
Given a positive integer N, calculate:
For N = 5:
1 + 2 + 3 + 4 + 5 = 15.
Python:
C:
12.13 Practical Program: 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:
Python:
C:
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
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:
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.
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:
C:
12.16 Practical Program: Menu-Driven Application
A menu-driven program allows the user to select an operation from a displayed list.
The menu converts one general program into several selectable operations.
12.17 Functions and Problem Decomposition
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.
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.
The function receives one parameter, calculates the square and returns the result.
Function for Average:
The result is 70.
12.19 C Functions
C also supports functions.
The square function can be reused whenever the program needs to calculate a square.
12.20 Input Validation and 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.
Unsafe Logic:
Improved Logic:
12.21 Testing with Normal, Boundary and Invalid Data
A reliable test strategy should deliberately include different categories of input.
Normal data consists of typical valid values expected during ordinary use.
Boundary data consists of values at or immediately around important limits in the problem specification.
Invalid data consists of values that violate the stated requirements or constraints.
Suppose a service requires age ≥ 18.
| Input | Type | Expected Outcome |
|---|---|---|
| 25 | Normal | Eligible |
| 18 | Boundary | Eligible |
| 17 | Boundary-adjacent | Not eligible |
| -4 | Invalid | Reject 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 | || |
Pseudocode:
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?
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.
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:
Python Implementation:
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.
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.
- 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.