Algorithms & Problem Solving with Pseudo Code
Algorithms
In general terms an algorithm is a series of instructions. They are typically used to perform an operation or solve a problem. In Javascript, these are typically written as functions, which are repeatable blocks of code that can take inputs in the form of arguments and return an output.
When writing functions we can make use of Javascript language features to perform certain operations, such as if statements to control when blocks of code run, and it's our job as developers to put these together to achieve our goals.
As our knowledge grows we will understand additional features, methods and even re-use functions of our own making.
A key skill when writing these functions is being able to take a problem that we understand from a high level and translate that high level understanding into code that can be executed.
This requires us to break a problem down into steps that can we can then write code to achieve. In order to visualise these steps, a technique called pseudo code is very useful.
Pseudo Code
Pseudo code is writing down human readable instructions that have equivalents in code. Consider this function which returns a string based on whether a number is less than 10.
function isLessThan10(num) {
if (num < 10) {
return 'less than 10';
}
return '10 or more';
}A pseudo code example of this function could be written as
- take a number as an parameter
- Check if the number is less than 10.
- If so, return the string "less than 10"
- Otherwise return the string "10 or more"
Each step in the pseudo code is an operation that we can perform in Javascript and we can write down the steps needed to solve the problem. This allows us to solve the problem at a high level, without needing to consider the exact syntax required. These are details which can be worked out as we code our solution which will be invaluable when it comes to more complicated functions.
Problem solving with Pseudo Code
Consider the function createGreeting. This function will take an array of names and return the an English sentence saying hello to them all. e.g.
function createGreeting(names) {
// TODO
}
const greeting = createGreeting(['Joey', 'Moe', 'Lisa']);
console.log(greeting); // Hello Joey, Moe and LisaThis function is more complicated. From the description we as humans can interpret what an English sentence should look like, but that's not a feature of Javascript, there is no in-built method that will achieve this for us so we write that function.
In order to write this function and solve the problem, we will have to follow a series of steps that are available to us, in order to produce the output we want.
Here we apply our understanding of the problem and recognise that an English sentence will vary in structure depending on how many names there are in the array.
For example, a single name would return Hello Joey
If there are more names in the list each one is comma separated, except the final name, which uses the word "and" instead of a comma.
Thinking about the problem in these terms helps us align our thinking with how the code is going to be ran.
The above problem could be pseudo coded as so:
- Create a variable with Hello and the first name
- loop over remaining names
- for each name add a comma, a space and the name
- when you get to the last name add a space, the word "and" as well as the name
- return the now complete greeting
Each of the steps above can be translated into code for the following implementation.
function createGreeting(...names) {
let greeting = `Hello ${names[0]}`;
for (let i = 1; i < names.length; i++) {
if (i === names.length - 1) {
greeting += ` and ${names[i]}`;
} else {
greeting += `, ${names[i]}`;
}
}
return greeting;
}
const greeting = createGreeting('Joey', 'Moe', 'Lisa');
console.log(greeting); // Hello Joey, Moe and Lisa- Create a variable with Hello and the first name
// firstName is always names[0]
let greeting = `Hello ${names[0]}`;- loop over remaining names
// start the loop at i = 1 to skip the first name
for (let i = 1; i < names.length; i++) {
// ...
}- for each name add a comma, a space and the name
// use a string template to add the required string
greeting += `, ${names[i]}`;- when you get to the last name add a space, the word "and" as well as the name
// the last name has an index of names.length - 1
if (i === names.length - 1) {
greeting += ` and ${names[i]}`;
}- return the now complete greeting
// return after the for loop has completed
return greeting;It is worth noting that this is not the only approach that could be taken to implement this function. Other logical steps could be taken to produce the same result and they are also valid solutions.
Advantages
When written out as pseudo code we can see that our implementation is logically sound and should produce what we are looking for. There were several implementation details along the way that might not be so intuitive when considering the problem as a whole, like subtracting 1 from names.length to work out when the loop reaches the last name.
By having the steps we are trying to take explicitly defined we can refer back to them when things go wrong or don't work as we expect them to, which is inevitable. By defining what we want to achieve at each step we can consider them as a series of smaller problems to solve, which makes debugging much much easier.
When dealing with a difficult problem it's often helpful to write pseudo code comments as a reminder to yourself, as you gain more experience the more familiar steps can be held in your head, but if you're ever in doubt or struggling to hold on to all the required information, writing it down will help free yourself up to consider the problem at hand.
Considerations
When writing a step of pseudo code the main things to consider are:
-
Information required - Do you have enough data to work out what you need to do?
-
e.g. If you want an element from an array, do you know it's index?
-
Want to retrieve a value from an object, do you know what key it's on?
-
Want to check if something has been done before, are there enough variables so that you can work out if this is the first time or not?
-
-
Single step - can JS do what you want in a single step? You can do if's, loops, comparisons etc with native language features. You also have inbuilt methods that can be used.
-
e.g. convert a string to lowercase -> either write several steps to produce this (create a variable to store it, loop over the original etc) or use the
String.toLowerCase()that will produce exactly what you're looking for. -
A nice analogy for this is each feature and method that we learn to use is a tool on our toolbelt. We will collect more over time and pick the right tool for the job. If we don't have a tool that does the job we want, we'll make one using what we already have (variables, loops and if's.)
-