Problem Solving1
Problem Solving1
Problem Solving1
Working backwards is a useful heuristic in which you begin solving the problem by
focusing on the end result. It is common to use the working backwards heuristic to
plan the events of your day on a regular basis, probably without even thinking
about it.
Another useful heuristic is the practice of accomplishing a large goal or task by
breaking it into a series of smaller steps. Students often use this common method to
complete a large research project or long essay for school. For example, students
typically brainstorm, develop a thesis or main topic, research the chosen topic,
organize their information into an outline, write a rough draft, revise and edit the
rough draft, develop a final draft, organize the references list, and proofread their
work before turning in the project. The large task becomes less overwhelming when
it is broken down into a series of small steps.
Means-Ends Analysis
This strategy involves choosing and analysing an action at a series of smaller steps
to move closer to the goal. One example of means-end analysis can be found by
using the Tower of Hanoi paradigm. This paradigm can be modelled as a word
problem.
The actual Tower of Hanoi problem consists of three rods sitting vertically on a
base with a number of disks of different sizes that can slide onto any rod. The
puzzle starts with the disks in a neat stack in ascending order of size on one rod, the
smallest at the top making a conical shape. The objective of the puzzle is to move
the entire stack to another rod obeying the following rules:
1. Only one disk can be moved at a time.
2. Each move consists of taking the upper disk from one of the stacks and placing
it on top of another stack or on an empty rod.
3. No larger disc may be placed on top of a smaller disk.
With 3 disks, the puzzle can be solved in 7 moves. The minimal moves required to
solve a Tower of Hanoi puzzle is 2n – 1, where 𝑛 is the number of disks. For
example, if there were 14 disks in the tower, the minimum amount of moves that
could be made to solve the puzzle would be 214 – 1 = 16,383 moves. There are
various ways of approaching the Tower of Hanoi or its related problems in addition
to the approaches listed above including an iterative solution, recursive solution,
non-recursive solution, a binary and Gray-code solutions, and graphical
representations.
An iterative solution entails moving the smallest pieces over one, then moving the
next over one and if there is no tower position in the chosen direction you are
moving to, move the pieces to the opposite end, but then continue to move in the
same direction. By doing this one will complete the puzzle in the minimum amount
of moves when there are 3 disks. Recursive solutions represent recognizing that the
puzzle can be broken down into a series of sub problems to each of which the same
general solving procedures apply, and then the total solution can be found by
putting together the sub solutions. Non-recursive solutions entail recognizing that
the procedures required to solve the problem have many regularities such as when
counting the moves starting at 1, position of the disk in the series to be moved
during move 𝑚 represents the number of times 𝑚 can be divided by 2 which
indicates that every odd move involves the smallest disk. This allows for the
following algorithm:
Move the smallest disk to the peg that it has not recently come from. Move another
disk legally (there will only be one possibility).
A binary and Gray solutions describe disk move numbers in binary notation (base-
2) where there is only one binary digit (a bit) for each disk and the most
significant (leftmost bit) represents the largest disk. A bit with a different value to
the previous one means that the corresponding disk is one position to the left or
right of the previous one.
Past Experience
Take the time to consider if you have encountered a similar situation to your current
problem in the past. This can help draw connections between different events. Ask
yourself how you approached the previous situation and adapt those solutions to
the problem currently being solved. For example, a company trying to market a
new clothing line may consider marketing tactics they have previously used, such
as magazine advertisements, influencer campaigns or social media
advertisements. By analysing what tactics have worked in the past, they can create
a successful marketing campaign again.
Bring in a facilitator
If one is trying to solve a complex problem with a group of other people, bringing
in a facilitator can help increase efficiency and mediate collaboration. Having an
impartial third party can help a group stay on task, document the process and have a
more meaningful conversation. Consider inviting a facilitator to your next group
meeting to help generate better solutions.
Develop a decision matrix for evaluation
If multiple solutions are developed for a problem, one may need to determine which
one is the best. A decision matrix can be an excellent tool to help you approach this
task because it allows you to rank potential solutions. Some factors you can analyse
when ranking each potential solution are:
• Timeliness
• Risk
• Manageability
• Expense
• Practicality
• Effectiveness
After having decided which factors to include, use them to rank each potential
solution by assigning a weighted value of 0 to 10 in each of these areas. For
example, one solution may receive a score of 10 in the timeliness factor because it
meets all the requirements, while another solution may only receive a seven.
Having ranked each of the potential solutions based on these factors, add up the
total number of points each solution received. The solution with the highest number
of points should meet the most important criteria.
Regardless of the area of study, computer science is all about solving problems with
computers. Hence, it is important to first understand the computer’s information
processing model. The problems that we want to solve can come from any real-
world problem or perhaps even from the abstract world. We need to have a standard
systematic approach to solving problems. The model shown in Fig. 1-2-1 below
assumes a single CPU (Central Processing Unit). Many computers today have
multiple CPUs, so it can be imagined the above model being duplicated multiple
times within the computer.
Input devices
Storage/Network devices
We also need to consider missing grades. What if we do not have the grade for
every student: for instance, some were away during the test? Should we be able to
include that person in our average (i.e., they received 0) or ignore them when
computing the average? We also need to understand what the output should be.
Again, there is a formatting issue. Should the output be a whole or real number or a
letter grade? Do we want to display a pie chart with the average grade? The choice
is ours. Finally, one needs to understand the kind of processing that must be
performed on the data. This leads to the next step.
Formulating a Model
The next step is to formulate a model for the problem. A model (or formula) is thus
needed for computing the average of a bunch of numbers. If there is no such
“formula”, one must be developed. In order to come up with a model, we need to
fully understand the information available to us. Assuming that the input data is a
bunch of integers or real numbers 𝑥1, 𝑥2, ⋯ , 𝑥𝑛 representing a grade percentage,
the following computational model may apply:
𝐴𝑣𝑒𝑟𝑎𝑔𝑒1 = (𝑥1 + 𝑥2 + 𝑥3 + ⋯ + 𝑥𝑛)/𝑛
where the result will be a number from 0 to 100.
That is very straight forward, assuming that the formula for computing the average
of a bunch of numbers is known. However, this approach will not work if the input
data is a set of letter grades like B-, C, A+, F, D-, etc., because addition and
division cannot be performed on the letters. This problem solving step must figure
out a way to produce an average from such letters. Thinking is required.
After some thought, we may decide to assign an integer number to the incoming
letters as follows:
𝐴+ = 12 𝐵+ = 9 𝐶+ = 6 𝐷+ = 3
𝐴 = 11 𝐵 =8 𝐶 =5 𝐷 =2
𝐹=0
𝐴− = 10 𝐵− = 7 𝐶− = 4 𝐷− = 1
If it is assumed that these newly assigned grade numbers are
𝑦1, 𝑦2, ⋯ , 𝑦𝑛, then the following computational model may be used:
𝐴𝑣𝑒𝑟𝑎𝑔𝑒2 = (𝑦1 + 𝑦2 + 𝑦3 + ⋯ + 𝑦𝑛)/𝑛
where the result will be a number from 0 to 12.
As for the output, if it is to be represented as a percentage, then
𝐴𝑣𝑒𝑟𝑎𝑔𝑒1 can either be used directly or one may use (𝐴𝑣𝑒𝑟𝑎𝑔𝑒2/12), depending
on the input that we had originally. If a letter grade is preferred as output, then one
may need to use (𝐴𝑣𝑒𝑟𝑎𝑔𝑒1/100 ∗ 12) or (𝐴𝑣𝑒𝑟𝑎𝑔𝑒1 ∗ 0.12) or 𝐴𝑣𝑒𝑟𝑎𝑔𝑒2 and
then map that to some kind of “lookup table” that allows one to look up a grade
letter according to a number from 0 to 12.
The main point to understand in this step is that it is all about figuring out how to
make use of the available data to compute an answer.
Develop an Algorithm
Having understood the problem and formulated a model, it is time to come up
with a precise plan of what the computer is expected to do.
Lamp
plugged Plug in Lamp
in?
Yes
Bulb Yes
burned Replace Bulb
out?
No
Pseudocode
1. IF lamp works, go to step 7.
2. Check if lamp is plugged in.
3. IF not plugged in, plug in lamp.
4. Check if bulb is burnt out.
5. IF blub is burnt, replace bulb.
6. IF lamp doesn’t work buy new lamp.
7. Quit ... problem is solved.
The point is that there are a variety of ways to write pseudocode. The important thing
to remember is that the algorithm should be clearly explained with no ambiguity as to
what order the steps are performed in. Whether using a flow chart of pseudocode, an
algorithm should be tested by manually going through the steps in mentally to make
sure a step or a special situation is not missed out. Often, a flaw will be found in
one’s algorithm because a special situation that could arise was missed out.
Only when one is convinced that the algorithm will solve the problem, should the
next step be attempted.
Consider the previous example of finding the average of a set of 𝑛 grades stored in a
file. What would the pseudocode look like? Here is an example of what it might look
like if we had the example of 𝑛 numeric grades 𝑥1, 𝑥2, ⋯ , 𝑥𝑛 that were loaded from a
file:
Algorithm: Display Grades
1. set the sum of the grade values to 0.
2. load all grades 𝑥1, 𝑥2, ⋯ , 𝑥𝑛 from file.
3. repeat n times {
4. get grade xi
5. add xi to the sum
It would be wise to run through the above algorithm with a real set of numbers.
Each time an algorithm is tested with a fixed set of input data, this is known as a
test case.
Many test cases can be created. Here are some to try:
𝑛 = 5, 𝑥1 = 92, 𝑥2 = 37, 𝑥3 = 43, 𝑥4 = 12, 𝑥5 = 71…result should be 51
𝑛 = 3, 𝑥1 = 1, 𝑥2 = 1, 𝑥3 = 1……………………….…result should be 1
𝑛 = 0……………………………………………………result should be 0
For now, the details of how to produce the above source code will not be discussed.
In fact, the source code would vary depending on the programming language that
was used. Learning a programming language may seem difficult at first, but it will
become easier with practice.
The computer requires precise instructions in order to understand what it is being
asked to do. For example, removing one of the semi-colon characters (;) from the
program above, will make the computer become confused as to what it’s being
asked to do because the semi-colon characters (;) is what it understands to be the
end of an instruction. Leaving one of them off will cause the program to generate
what is known as a compile-time error.
Definition 1-2-5: Debugging is the process of finding and fixing errors in program
code.
Debugging is often a very time-consuming “chore” when it comes to being a
programmer. However, if one painstakingly and carefully follows steps 1 through 3,
this should greatly reduce the amount of bugs in a program, thus making debugging
much easier.
Brute-force Approach
This strategy is characterized by a lack of sophistication in terms of their approach
to the solution. It typically takes the most direct or obvious route, without
attempting to minimize the number of operations required to compute the solution.
Brute-force approach is considered quite often in the course of searching. In a
searching problem, we are required to look through a list of candidates in an
attempt to find a desired object. In many cases, the structure of the problem itself
allows us to eliminate a large number of the candidates without having to actually
search through them. As an analogy, consider the problem of trying to find a frozen
pie in an unfamiliar grocery store. You would immediately go to the frozen food
aisle, without bothering to look down any of the other aisles. Thus, at the outset of
your search, you would eliminate the need to search down most of the aisles in the
store. Brute force approach, however, ignores such possibilities and naively search
through all candidates in an attempt to find the desired object. This approach is
otherwise known as exhaustive search.
Example:
Imagine a small padlock with 4 digits, each from 0-9. You forgot your combination,
but you don't want to buy another padlock. Since you can't remember any of the
digits, you have to use a brute force method to open the lock. So you set all the
numbers back to 0 and try them one by one: 0001, 0002, 0003, and so on until it
opens. In the worst case scenario, it would take 104, or 10,000 tries to find your
combination.
Divide-and-conquer Approach
In the divide and conquer strategy, a problem is solved recursively by applying
three steps at each level of the recursion: Divide, conquer, and combine.
Divide
“Divide” is the first step of the divide and conquer strategy. In this step the problem
is divided into smaller sub-problems until it is small enough to be solved. At this
step, sub-problems become smaller but still represent some part of the actual
problem. As stated above, recursion is used to implement the divide and conquer
algorithm. A recursive algorithm calls itself with smaller or simpler input values,
known as the recursive case. So, when the divide step is implemented, the recursive
case is determined which will divide the problem into smaller sub- problems.
Then comes the “conquer” step where we straightforwardly solve the sub-problems.
By now, the input has already been divided into the smallest possible parts and
we’re now going to solve them by performing basic operations. The conquer step is
normally implemented with recursion by specifying the recursive base case. Once
the sub- problems become small enough that it can no longer be divided, we say
that the recursion “bottoms out” and that we’ve gotten down to the base case. Once
the base case is arrived at, the sub-problem is solved.
Combine
In this step, the solution of the sub-problems is combined to solve the whole
problem. The output returned from solving the base case will be the input of larger
sub-problems. So after reaching the base case we will begin to go up to solve larger
sub-problems with input returned from smaller sub-problems. In this step, we
merge output from the conquer step to solve bigger sub-problems. Solutions to
smaller sub-problems propagate from the bottom up until they are used to solve the
whole original problem.
Again, divide each subpart recursively into two halves until you get individual
elements.
In the divide and conquer strategy problems are divided into sub- problems that can
be executed independently from each other. Thus, making this strategy suited for
parallel execution.
Algorithm
Let 𝑛 be the number of terms.
1. If 𝑛 ≤ 1, return 1.
2. Else return the sum of two preceding numbers.
We are calculating the Fibonacci sequence up to the 5th term.
1. The first term is 0.
2. The second term is 1.
3. The third term is sum of 0 (from step 1) and 1(from step 2), which is 1.
4. The fourth term is the sum of the third term (from step 3) and second term
(from step 2) i.e. 1 + 1 = 2.
5. The fifth term is the sum of the fourth term (from step 4) and third term (from
step 3) i.e. 2 + 1 = 3.
Hence, we have the sequence 0,1,1, 2, 3. Here, we have used the results of the
previous steps as shown below. This is called a dynamic programming approach.
F(0) = 0
F(1) = 1
F(2) = F(1) + F(0)
F(3) = F(2) + F(1)
F(4) = F(3) + F(2)
Randomized Approach
This approach is dependent not only on the input data, but also on the values
provided by a random number generator. If some portion of an algorithm involves
choosing between a number of alternatives, and it is difficult to determine the
optimal choice, then it is often more effective to choose the course of action at
random rather than taking the time to determine the vest alternative. This is
particularly true in cases where there are a large number of choices, most of which
are “good.”
Although randomising an algorithm will typically not improve its worst- case
running time, it can be used to ensure that no particular input always produces the
worst-case behaviour. Specifically, because the behaviour of a randomised
algorithm is determined by a sequence of random numbers, it would be unusual for
the algorithm to behave the same way on successive runs even when it is supplied
with the same input data.
Randomised approaches are best suited in game-theoretic situations where we want
to ensure fairness in the face of mutual suspicion. This approach is widely used in
computer and information security as well as in various computer-based games.
Solving problems is a key professional skill. Quickly weighing up available
options and taking decisive actions to select the best computational approach to a
problem is integral to efficient performance.
It is important to always get the problem-solving process right, avoiding taking too
little time to define the problem or generate potential solutions. A wide range of
computational techniques for problem solving exist, and each can be appropriate
given the peculiarity of the problem and the individual involved. The important
skills to attain are to assess the situation independently of any other factors and to
know when to trust your own instincts and when to ask for a second opinion on a
potential solution to a problem.
ROLE OF ALGORITHM IN PROBLEM SOLVING
Computational thinking allows us to take a complex problem, understand what it is
and develop possible solutions. The solutions can then be presented in a way that a
computer, a human or both, can understand. There are four cornerstones to
computational thinking:
• decomposition - breaking down a complex problem or system into smaller,
more manageable parts
• pattern recognition – looking for similarities among and within problems
• abstraction – focusing on the important information only, ignoring
irrelevant detail
• algorithms - developing a step-by-step solution to the problem, or the rules to
follow to solve the problem
Correctly applying all the four cornerstones will help to develop a computer-enabled
solution.
This approach involves taking a complex problem and breaking it down into a series
of small, more manageable problems (decomposition). Each of these smaller
problems can then be looked at individually, considering how similar problems have
been solved previously (pattern recognition) and focusing only on the important
details, while ignoring irrelevant information (abstraction). Next, simple steps or
rules to solve each of the smaller problems can be designed (algorithms).
Finally, these simple steps or rules are used to implement a computer- enabled
solution.
For example, when playing a videogame, depending on the game and in order to
complete a level, one may need to know:
• what items are needed to collect, how to collect them, and how much time one
has to collect them
• where the exit is and the best route to reach it in the quickest time possible
• what kinds of enemies there are and their weak points?
From these details, a strategy can be worked out for completing the level in the most
efficient way.
35