The idea that working in tech requires a gold star in maths and a membership to MENSA is no longer the case. Forward-thinking tech companies now look to hire diverse teams of people, all of whom can bring their own unique talents.
Do you want to build the world? Code builds the website that you shop on, it runs the trains that you take to work, it runs restaurants and hospitals and just about everything else. Working in tech means you get to build services that make life better, and to ensure that it works equitably for everybody.
Coding as a skill is highly in demand across just about every industry. Automating administrative tasks, monitoring patient health, charting crop growth; these are all tasks that can be achieved with some curiosity and a little coding knowledge.
The purpose behind this guide is to help give you the skills you need to start solving simple challenges and think like a developer. You might like to do this in order to find a new job, or even just out of curiosity
What this is not, is a comprehensive guide to programming, software development or web development. The intention is to light a spark of curiosity, and then to guide you on to bigger and better things! That may be developing apps as a hobby, introducing code to your current job, or it may be a career with 2i.
Throughout this guide, we will be working in JavaScript. Why JavaScript? Because it is used everywhere! JavaScript is used in modern web frameworks like React (created and used by Meta/Facebook) and Vue (used by Netflix and others), it is used to script tests in frameworks like Cypress and Postman, it can even be used to create art and visuals using libraries like three.js and p5.js. In fact, according to PluralSight, it is the number one most learned technology on their platform.
Another great reason to learn JavaScript is that it is a comparatively beginner-friendly language: it is reasonably easy to read, has a forgiving syntax, and a lot of the more complex functionality is abstracted into nice, easy to use methods.
While JavaScript may look pretty “computerish”, it is much closer to English than anything that a computer can understand. So, we need compilers and translators to facilitate the running of our code. Node.js is the runtime most used to achieve this in JavaScript. You can install Node to your device and try writing and running some JavaScript locally, but for this guide, we recommend using a sandbox like Replit. Replit is a free, in-browser development platform where you can quickly spin up a Node environment and start coding. Sandboxes like replit are great because they are safe environments where you cannot do any damage to your computer. If the code freezes up, you can always just close the tab and open a new environment.
The other advantage is that you will not have to use the command line to install and run software like you would if you were learning on your computer. The command line (usually command prompt on Windows, terminal on MacOS) is a way of controlling your computer using text commands. It is incredibly useful, and we will touch on it in a later chapter but for now, save yourself the hassle and use a sandbox. Replit has an excellent getting started video which you can follow here. Just make sure to pick a Node repl template.
The best way to learn to code is by doing, so for best results, you will want to put this site side-by-side with a blank Node repl and follow along with the lessons. If you find that you’re curious about something, follow that curiosity! Change the code, break it and see if you can fix it again. That is a great way to develop your understanding.
Let’s jump straight into some code. Type this into your repl and hit “run”.
let myName = 'Lewis' console.log(myName)
Congratulations! You just ran some code. Some things to note about this code:
Try changing “Lewis” to your name and running the code again
Variables are at the heart of coding. We use them to hold onto values while the code runs, and this enables us to do all sorts of interesting things. A very important aspect of variables is in the name, it is variable, meaning that it can be changed. This is perfect for a script where we want to keep track of a value as it changes, such as a tally:
// say we have a count of people entering a venue let tally = 0 console.log(tally) // and a new customer comes along, so we increment the tally tally = tally + 1 // tally now equals itself plus one console.log(tally) // and another customer tally += 1 // this is another way of writing the above console.log(tally)
You can see that we use the same variable throughout, and just vary its value. This is something that you will find yourself doing a lot!
You will also see some sections of this code which are written in English and with a “//” at the front. These are called comments. Comments are designed to make code readable at a glance, and it is a good idea to include plenty of them in any code challenge which will be read by interviewers.
The downside of variables is that they are sometimes too easy to change! So, what if you want to hold onto a value that will not change during runtime? We would use a constant instead. Constants are declared just like variables, except that we use const instead of let.
const iAm = 'Douglas' console.log(iAm) // here, I am attempting to change the value of iAm to 'Stephen' iAm = 'Stephen' // but, it causes an error, because iAm is a constant console.log(iAm)
TIP: Being sure to use a constant rather than a variable when appropriate will look good on a code challenge, as they make code less prone to bugs.
TIP: In JavaScript, you can also declare a variable using 'var'. This is an older style that still pops up now and then in code but is generally discouraged as it can be accessed anywhere in the code ('globally scoped'), as opposed to 'let' which can only be referred to from the block of code in which it is declared ('block scoped'). This article covers scope in more detail and with examples.
Check your code against the following cheatsheet
As you may have already noticed, a variable is not confined to only being text or a number. Variables can hold pretty much any value that you hand them, but we will get to that later. To start with, we will discuss some of JavaScript’s primitive data types:
Numbers in JavaScript can be either integers (aka whole numbers) or floating-point numbers (aka decimal numbers, for example, 4.54). This is not always the case in all languages. Numbers can also be one of the special types such as NaN (not a number), +Infinity or -Infinity.
// examples of numbers const age = 21 const grade = 67.5 const schoolName = NaN
Strings are text assigned to a variable. They can be a letter, a word, a space, or the entire text of Moby Dick. When assigning a string to a variable, you need to surround it with quotes (“”) so that JavaScript interprets it as a string.
// examples of strings const name = "Bob" const species = "sheep dog" const space = " "
Boolean variables have only two possible states: true or false. Remember that in JavaScript true and false are not capitalised.
// examples of booleans const on = true const off = false
Some other data types that you might come across (usually when things go wrong):
Null represents the intentional absence of value. Some operations will return null if unsuccessful so you can check for a null result in your code.
Undefined is different from null in that it represents a variable that has not yet been assigned a value. Constants cannot be undefined.
// examples of null and undefined let nullExample = null let noValue console.log(noValue) // will return undefined
Operators are used to add, subtract, multiply and divide numbers. You may not be so familiar with modulo: this operator divides the numbers and returns the remainder as an integer (for example 17 % 5 would return 2). This is useful for checking that a number is divisible by another number.
// setting up some numbers to operate on const a = 10 const b = 6 // addition const sum = a + b console.log(sum) // subtraction const sub = a - b console.log(sub) // multiplication const mult = a * b console.log(mult) // division const div = a / b console.log(div) // modulo const mod = a % b console.log(mod)
You can also use the addition operator (+) with strings, although it has a slightly different effect. This is called concatenation.
// string concatenation const firstName = "Homer" const lastName = "Simpson" console.log(firstName + lastName)
prints: “HomerSimpson”
As you can see, the two strings were added together, but there is a space missing. A common trick when concatenating strings is to also concatenate additional spaces.
// adding in spaces console.log(firstName + " " + lastName)
prints: “Homer Simpson”
A property of strings that you may often use is the length of the string:
// string length console.log(firstName + " is a name with "+ firstName.length + " letters.")
prints: Homer is a name with 5 letters.
TIP: The length property can also be used with data collections such as arrays and objects. More about those in another lesson
Check your code against the following cheatsheet
A function is a self-contained section of code which is then called to run when it is needed. Imagine that we have a programme where we need to perform a task over and over. We could sit and copy and paste the code to run that task wherever we need, or we could define the function once, and call it when needed, keeping our code clean and simple to maintain.
Functions are incredibly important and useful, but are often a little misunderstood by beginners, so we will cover a little of the principles of writing good functions, as well as how to write one.
// a simple function that takes in two numbers, and multiplies them together function multiplier (number1, number2) { return number1 * number2 } // calling the function const result1 = multiplier(2,4) console.log(result1)
in this example:
There are a few principles to stick to when writing functions:
The biggest advantage of writing a function is that it can be reused over and over, without having to write code for everything that you want to do.
// An example of a function with poor reusability function divider (number1){ return number1 / 7 }
This is an example of a function with poor reusability because we can only use it to divide numbers by 7. If we want to divide by anything else, we would have to write a whole other function
As functions get to be more complex, they can become long, hard to read and less reusable. Fortunately, functions can be called from within other functions, which means that you can delegate complex tasks to other helper functions.
// an example of a function which calls other (imaginary) functions from within function takeCardPayment(cardNumber, price, shoppingCart){ const priceWithVat = calculatePricePlusVat(price) const validated = validateCardWithBank(cardNumber) if (validated === true) { takePayment(cardNumber, priceWithVat) removeFromStock(shoppingCart) } }
Part of the point of a function is abstraction, meaning that when we call a function, we don’t need to know the inner workings of it, just what goes in and comes out. A short, descriptive name helps with this. If you are struggling to name your function, it may be performing too many tasks. In the example above, we can’t see how the helper functions perform their tasks, but we can take a good guess at the results from the names.
Check your code against the following cheatsheet
We have already looked at some of the basic data types such as numbers and strings, but what if we want to collect several strings or numbers together to do something with them? To do that, we use arrays and objects. These will often have different names in other languages, but they generally work the same.
Arrays are essentially a list of elements that be all of the same type, or of different types. Arrays can also contain other arrays and objects. This is called nesting arrays.
// simple arrays const fruits = ["apple", "orange", "banana"] const mixup = [24, "porridge", false] // individual values within arrays can be accessed by their index, which starts from 0, not 1. console.log(fruits[0]) console.log(fruits[2])
prints: "apple" and "banana"
// adding a new value to the end of an array fruits.push("dragonfruit") console.log(fruits)
prints: ["apple","orange","banana","dragonfruit"]
// removing a value from the end of an array fruits.pop() console.log(fruits)
prints: ["apple","orange","banana"]
// removing a value from the front of an array fruits.shift() console.log(fruits)
prints: ["orange","banana"]
// adding a value to the front of an array fruits.unshift("fig") console.log(fruits)
prints: ["fig","orange","banana"]
// the index of a value can be found using indexOf const pos = fruits.indexOf("orange") // we can then use splice to remove the item at the found position. // The first argument tells splice where to start removing elements, and the second tells how many elements to remove const shoppingBasket = fruits.splice(pos,1) console.log(shoppingBasket)
prints: ["fig","banana"]
Tip: .pop() and .shift() both return the removed value. If you want to store this value and use it elsewhere, you can assign it to a variable like this:
const removedFruit = fruits.pop()
Objects are similar to arrays in that they are collections of elements. The issue with arrays is that they can only be accessed by an index, and their order is not strictly guaranteed. Objects are different because they use key and value pairs to arrange information. You can think of the key as the label that be used to look up the value. Like arrays, the value can be any data type, including nested arrays and objects. This allows us to construct and access complex data structures.
const car = {brand:"Honda", model:"Jazz", colour:"orange"} // accessing a value using the key (both formats work) console.log(car["model"]) console.log(car.brand)
prints "Jazz" and "Honda"
// objects can also be defined across several lines const bike = { brand: "Raleigh", model: "Randonneur" } // new data can be added to the objects like this bike["colour"] = "metallic blue" bike.gears = "3x8" console.log(bike)
prints: { brand: "Raleigh", model: "Randonneur", colour: "metallic blue", gears: "3x8" }
// should you need to delete a key/value pair delete bike.gears console.log(bike)
prints: "{ brand: "Raleigh", model: "Randonneur", colour: "metallic blue" }"
// example of nested objects/arrays // this is the sort of thing you may encounter when working with APIs const zoo = { name: "Edinburgh Zoo", animals: [ { id: 1, name: "Tom", species: "Tiger" }, { id: 2, name: "Jerry", species: "Capybara" }, { id: 3, name: "Sheryl", species: "Tarantula" } ] } // to access the info, we "drill down" one layer at a time console.log(zoo.name) console.log(zoo.animals[1].name) console.log(zoo["animals"][2]["species"])
Prints: "Edinburgh Zoo", "Jerry" and "Tarantula"
For an in depth guide to working with Objects, the MDN guide is an excellent resource
Check your code against the following cheatsheet
Very often, we will want to take one of our data structures and apply some kind processing to it. It may be that we want to sort through and find a certain value, or we may want to take each piece of data and multiply it by a number. To iterate through these structures automatically, we use loops.
In this lesson we will also introduce if statements, which we often use with loops. A very common situation when iterating through a data structure is that we want to work on a piece of data conditionally, in these cases we will use an if statement to assert whether something fits a condition, and if so, we will then run a block of code. If the condition is false, then we skip over the block of code. We can also add an else statement to offer an alternative block of code in the case of the if returning false.
// if and else statements const x = 1 if (x === 1) { console.log("this will run if x equals 1") } else { console.log("this will run if x does not equal 1") }
We have two main types of loops in JavaScript: For and While loops.
A while loop will repeat for as long as a condition remains true. These are often used to set up loops which wait for a condition to change, such as waiting for a keypress.
// while loops while (true) { const input = prompt("press q to exit: ") if (input == "q"){ break } }
For loops will run for a predefined length. This is either defined manually in an older style for loop, or is defined by the length of the array or object in the case of more modern for in and for of loops.
// traditional style for loop for (let i=0; i<10; i++) { console.log("I am a counting machine: "+(i+1)) } // let i=0 - sets up a counter (i starts at zero in this case) // i<10 - sets the end condition (run while i is less than 10) // i++ - increments the counter on every iteration. Could also be i-- to count down // for in loop - specific to objects and arrays const guitar = { brand: "Fender", model: "Telecaster", finish: "Sunburst" } for (property in guitar) { console.log("the "+ property + " of this guitar is: " + guitar[property]) } // for of loop - can be used for any iterable such as arrays, strings and other types that you might not see often const numbers = [13,25,76,99,22,86,247] const counter = { odd: 0, even: 0 } // using the loop to find if numbers are odd or oven for (number of numbers) { // this line checks to see if the number can be divided by two without a remainder if (number % 2 === 0) { // if the IF resolves to true, then this line will run counter.even += 1 } else { // if the IF is false then this line will run instead counter.odd += 1 } } // print out the results console.log(counter)
To make our if statement work, we use comparators. In the example above we used a simple equals (“==”) comparator, but there are several others that we can use.
comparators equals (has the same value) == given that x = 3 x == 8 will resolve as false x == 3 will resolve as true x == "3" will resolve as true strongly equals (has the same value and data type) === given that x = 3 x === 8 will resolve as false x === 3 will resolve as true x === "3" will resolve as false does not equal/does not strongly equal !=/!== Given that x=7 x != 9 will resolve as true x !== 7 will resolve as false x !== "7" will resolve as true x !== 8 will resolve as true greater than/greater than or equal to >/>= Given that x = 10 x > 5 will resolve to true x > 10 will resolve to false x >= 5 will resolve to true x >= 10 will resolve to true less than/less than or equal to </<= Given that x=8 x < 10 will resolve to true x < 8 will resolve to false x <= 10 will resolve to true x <= 8 will resolve to true
Sometimes we may need to assert against multiple conditions at once. We could do this using nested if statements, but that can get messy quickly. Instead we can use AND (&&) and OR (||) operators.
AND && if statement will only resolve as true if both conditions are passed OR || if statement will resolve as true is either condition is passed
// Example: you cannot board a plane unless you have a passport AND enough money to buy a ticket const myPassport = true let myWallet = 200 function canBoardPlane (passport, wallet) { if (passport && wallet >= 150) { return true } else { return false } } console.log(canBoardPlane(myPassport,myWallet))
An important aspect of JavaScript is that it is loosely typed. This means that we can assign a value to a variable without having to explicitly state the data type. The compiler just infers what data type the variable should be. This makes JavaScript simpler to learn, read and write in general, but it can also occasionally slip us up as data can be interpreted as a different type. A simple example is a string containing the number "3". This can be interpreted by the compiler as a string, or as a number if we were to write an if statement containing " "3" >= 3". In the same vein, all data can be interpreted as a boolean value and we call this truthy or falsy . The rules that govern these are sometimes a bit strange, so you can always just look up a list like this one:
Examples of truthy values true (a boolean true) "false" (any string containing text, including the word "false") [] (an empty array) {} (an empty object) function(){} (an empty function) 3 (any number except zero) -10 examples of falsy values false (a boolean false) "" (an empty string) 0 (number of zero) -0 null undefined NaN (not a number, a special number type)
Check your code against the following cheatsheet
Now we are ready to start thinking about coding challenges.
We are designing a system for a rollercoaster, which you must be taller than or exactly 130cm to ride. A scanner will generate an array of the heights of people in the queue. Using functions, loops and ifs, generate a new array with Boolean values of true or false, relating to whether the person in the queue is tall enough to ride.
Given an input of :
const visitorHeights = [88, 129, 130, 154, 200]
The expected result is:
[false, false, true, true, true]
function checkQueueHeights(visitorHeights,minimumHeight){ }
function checkQueueHeights(visitorHeights,minimumHeight){ const result = [] }
function checkQueueHeights(visitorHeights,minimumHeight){ const result = [] for (visitor of visitorHeights) { } }
function checkQueueHeights(visitorHeights,minimumHeight){ const result = [] for (visitor of visitorHeights) { if (visitor >= minimumHeight) { // adds boolean true value to the result array result.push(true) } } }
function checkQueueHeights(visitorHeights,minimumHeight){ const result = [] for (visitor of visitorHeights) { if (visitor >= minimumHeight) { // adds boolean true value to the result array result.push(true) } else { // adds boolean false value to the result array result.push(false) } } }
function checkQueueHeights(visitorHeights,minimumHeight){ const result = [] for (visitor of visitorHeights) { if (visitor >= minimumHeight) { // adds boolean true value to the result array result.push(true) } else { // adds boolean false value to the result array result.push(false) } } return result }
const scannerOutput = [88, 129, 130, 154, 200] const minimum = 130 console.log(checkQueueHeights(scannerOutput,minimum))
prints: [ false, false, true, true, true ]
Job done! We have achieved the expected outcome.
So far, we have focussed on the bare minimum that you need to solve code challenges. In this optional chapter, we are going to look at some slightly more advanced styles of writing JavaScript. Being familiar with these techniques is great because:
If you learn one thing from this chapter, make it this one. Arrow functions are a shorter way of writing JavaScript functions, which is very useful when we start using functions in callbacks (a callback is essentially passing a function into a function as an argument).
Arrow functions essentially strip out some of the keywords associated with functions. Let’s step through from a traditional function to a completely simplified arrow function:
// traditional function function greet (name) { return "hello, my name is " + name }
Now, we are going to make this function into an anonymous function. That is, we’re not going to give it a name. In order to call the function, we’ll assign it to a variable instead.
// traditional anonymous function let greet = function (name) { return "hello my name is " + name }
And now into an arrow function.
// remove the word function, and replace it with an arrow after the parameter let greet = (name) => { return "hello my name is " + name } // if your function only has one line, you can also remove the "return" and braces. let greet = (name) => "hello my name is " + name // if you only have one parameter, you can remove the brackets around that too. // if you have zero parameters, or more than one, you will still need the bracket let greet = name => "hello my name is " + name // call the function just like any other console.log(greet("squidward"))
Prints “hello my name is squidward” You can see how compact and easy to read a function can get using arrow functions. Be aware that they are not suitable for all situations, so you may need to rewrite the function as a traditional function now and then.
For more information on arrow functions, the Mozilla documentation is always an excellent resource.
JavaScript is intended to be a really easy language to use, and a part of that user-friendly design is providing built-in functions called methods. Pretty much every class (Strings are a class, arrays are a class, you can define custom classes etc.) have built-in methods that you can use without having to define a function to use. If you are looking at code challenge solutions online, you’re very likely to come across array methods. Again, Mozilla is your friend, they maintain a list of all of the array methods available to you, with examples. Some, like pop(), push() and shift() should look familiar.
In this lesson, we will cover a few of the very useful methods which take an arrow function as an argument (this is known as a callback). These will absolutely supercharge your coding challenges!
// Class Methods & Callbacks const names = ["Will", "Mike", "Lucas", "Dustin", "Max"] // forEach // This method replaces for loops with a shorthand. names.forEach(name => console.log("presenting: " + name))
Here is a more complex example - drawing lottery numbers
// Drawing lottery Numbers const numbers = [23, 54, 99, 125, 43] // this is a helper function to turn the index into an ordinal (1st, 2nd etc.) const indexToOrdinal = number => { // a switch statement is like multiple ifs at once switch (number) { case 0: return (number+1)+"st" case 1: return (number+1)+"nd" case 2: return (number+1)+"rd" default: return (number+1)+"th" } } // notice how the brackets and braces are needed for this arrow function as we have two parameters and multiple lines of code within numbers.forEach( (number, index) => { const ord = indexToOrdinal(index) console.log("...and the " + ord + " lottery number is... " + number + "!") }) // map // the map method will apply a function to every element of the input array and output a NEW array of the same length. // This is useful if you want to create an array to work with, but not to overwrite the original const isDivisibleByFive = numbers.map( number => { if (number % 5 === 0) { return true } else { return false } }) console.log(isDivisibleByFive) // filter // The filter method creates a new array only populated with the elements of the original which pass a condition const multiplesOfFive = numbers.filter( number => number % 5 === 0) console.log(multiplesOfFive)
JavaScript has been around since 1995, and like most popular languages has gone through some changes and improvements as the scope of its use widened. The last major update to the language is commonly referred to as ES6. Being able to show that you use up-to-date syntax and keywords is a promising sign to potential employers, so try to keep up with new developments when you can.
The good news is, you already know some ES6! let and const, arrow functions and for/of loops are all ES6 features. If you want to learn some more nice ES6 tricks, I highly recommend this article, which generally uses beginner-friendly language and examples.
As you start to encounter more and more complex coding challenges, you will struggle to visualise a complete solution in your head. The best way to approach this is to put the problem onto the page, break the problem down into steps and then work on them one at a time.
Pseudocode is when you write out each line of code, but in a language that makes sense to you. This means that you can fully engage with solving the problem without thinking about code syntax. You may even want to write the steps in plain English first and then rewrite as pseudocode.
Let’s take an example problem of building a medicine dosage calculator. Given a total dosage, and the amount of medicine per pill, write a function to return the number of pills to give to a patient.
// step 1: Write out in plain English (optional) // declare a function that takes total dosage and dose/pill // divide the total by pill // return the result // step 2: Write out in pseudocode // function: (totalDosage, dosePerPill) // result = totalDosage / dosePerPill // return result // step 3: Convert to JavaScript const noPillsToGive = (totalDosage, dosePerPill) => { return totalDosage/dosePerPill }
When writing code professionally, we will often use tools called debuggers to help us discover and fix bugs. Bugs are flaws in our coding which cause unexpected behaviour.
A debugger will pause the code at set points called breakpoints and show the developer what variables are being held in memory, and what values those variables are holding on to. They essentially allow the developer to look inside of the code.
In sandbox environments like Replit we rarely have access to fully featured debuggers, so we usually rely on print statements instead. Print statements like console.log() are an essential tool for quickly debugging your code as you write it. Here are some reasons that you may use console.log() in a code challenge:
The below code contains some methods and syntaxes that you have not seen before, so don’t worry if you don’t completely understand them.
Challenge: there is a screening of a film at a cinema, and for each adult (age >15) in a group, a child (age <=5) gets in for free. Children cannot attend without at least one adult per group. Adult tickets are £10, children are £5. Write a function that takes in an array of ages for a group and returns a total price for tickets.
const adultTix = 10 const childTix = 5 groupAges = [18, 55, 5, 3, 1] const totalPrice = (group, adultPrice, childPrice) => { // sort “group” from high to low group.sort((a,b) => { return b-a }) // console log to verify that the array is sorted console.log(group) // loop to remove one child ticket from the array if current is an adult. group.forEach( customer => { // if the current customer is over 15 AND (&&) the last customer in the array is five or under, then remove that customer if (customer > 15 && group[group.length-1] <= 5) { // console log to check that this block of code is being run console.log("This block is being run!") group.pop() } }) // console log to check that the correct number of children have been removed console.log(group) // map to turn into money const tickets = group.map( customer => { // this is a shorthand way of writing if/else statements. Very handy for map statements. //If the customer is a child, return 5, else return 10 return (customer <= 5 ? 5 : 10) }) //console.log to check that the new array has been correctly populated console.log(tickets) // reduce to turn into one number const total = tickets.reduce( (runningTotal, current) => { return runningTotal + current }) return total } // this line runs the function, wrapped in a console.log so that the result is printed. console.log(totalPrice(groupAges,adultTix,childTix))
Prints:
[ 55, 18, 5, 3, 1 ] This block is being run! This block is being run! [ 55, 18, 5 ] [ 10, 10, 5 ] 25
Using console.log() throughout has enabled us to see the processing step by step, even in an overly complex function like this.
TIP: make sure that you remove your print statements before presenting any code as finished. As much as it is a good skill to be able to debug, it looks cluttered and unprofessional to leave print statements lying around. In production code, printing to the console could even be a security risk!
Now that you have seen a few simple coding challenges, we will present you some to try on your own. There are solutions available if you get stuck.
Challenge: Given an array, write a function which returns the array reversed. The function must work for any data type.
Example 1: [1,2,3,4,5,6,7,8,9,10] should return [10,9,8,7,6,5,4,3,2,1] Example 2: [“I”,”like”,”green”,”eggs”,”and”,”ham”] should return [“ham”,”and”,”eggs”,”green”,”like”,”I”]
Possible solutions are available here
Challenge: A shop wants a function to automatically find the item in stock which has the most capital tied up in stock (amount of stock * price) so that they can put that item on sale.
The function takes in an array of objects and outputs a single object.
Given data:
[ {item: "Raspberry Pi 4b", price: 40, stock: 50}, {item: "USB-C PSU", price: 15, stock: 200}, {item: "Dell laptop", price: 400, stock: 5}, {item: "FLIRC Pi4 case", price: 16, stock: 180}, ]
Should return:
{item: "USB-C PSU", price: 15, stock: 200}
Possible solutions are available here
Code challenges are really popular with developers of all levels, so there are lots out there to try!
CodeWars will scale up the challenge as you complete challenges, and it will show you how other people have approached the same problem.
Advent of Code publishes new coding challenges leading up to Christmas and there are lots of forum threads of people taking the challenges further in new and unexpected ways!
If you find that you learn best in a social/team setting, you can get involved with Hackathons! They run year-round and are a great opportunity to meet people and do some intense (but fun) upskilling.
TIP: A common pitfall for those that do coding challenges is the idea that a shorter answer is always better. In the real world, writing clean, easy to understand, well commented code is much more helpful to your colleagues than a wildly complex one-line solution. Save the one-liners for Code Wars!
When most users interact with their computer, they do so via the graphical user interface (GUI). They click on icons, shortcuts, folders, and menus to find their way around the computer and do everything from creating new files to opening a web browser. It’s all very intuitive and easy to understand; if you want to move a file from one folder to another, simply click and drag it to the desired location.
However, there is a more efficient and powerful way to interact with your computer and it’s one that’s essential for any programmer, software developer or test engineer such as yourself. That way is via the command line or CLI, a text-based interface that allows the user to do everything a GUI does as well as many more advanced operations.
However, there is a more efficient and powerful way to interact with your computer and it’s essential for any programmer, software developer or test engineer such as yourself. That way is via the command line or CLI, a text-based interface that allows the user to do everything a GUI does as well as many more advanced operations.
On Windows machines, the default command-line interface is called Command Prompt, or cmd.exe. On macOS, it’s Terminal. Both operate almost identically and for the most part, respond to the same commands.
Let’s walk through how to do some everyday operations using the command line. First, open cmd (type “cmd” into the Windows search bar) or Terminal (search “Terminal” in finder or Spotlight).
If you’re using Windows, you’ll see this: C:\Users\YOUR PC NAME HERE>
. On Mac, you may see ~
, which is just a shorthand for the home directory, or you may see the name of a folder. No doubt you’ve seen something like this before when saving a file or installing a piece of software. This is a file path, effectively an address to a particular location on your computer. In this case, it’s the file path of your current working directory, the place you’ll always start from when you open your command-line interface. As you navigate into different directories, you’ll see this current working directory update to reflect where you are now. Let’s see that in action.
First type dir
(ls
on Mac) and press enter. This command will list all of the folders inside your current working directory. Next type start .
(open .
) and hit enter. A window will open showing you the same location via the GUI. Compare the folder names in the new window to the list of directory names in cmd and you’ll see they’re all the same. (N.b. the .
in start .
is shorthand for your current working directory).
Next, let’s make a new folder using the command mkdir
. Type mkdir new_folder
and then enter. Now, using either the dir
(ls
) command or start .
(open .
), check to see that folder has been created.
Nice - we’ve made a new folder, so let’s get inside it. To change directories we use the command cd
. Type cd new_folder
then enter. You’ll see that the current working directory has changed, and now reads C:\Users\YOUR PC NAME HERE\new_folder
or new_folder
on MacOS.
Next, let’s make a file. We’re going to make an empty text file called "hello_world.txt”.
In cmd, we’ll do that by typing echo > hello_world.txt
and hitting enter. Now type “hello_world.txt” and the empty text file you just created will open up in Notepad. (In Terminal, this process is a little easier. Just type touch hello_world.txt
)
Let’s delete that file now. Type del /f hello_world.txt
(rm hello_world.txt
on Mac) and hit enter. Again, feel free to confirm it’s gone with dir
or start .
Okay, time to retrace our steps and return to where we started. Our current working directory is C:\Users\YOUR PC NAME HERE\new_folder>
or new_folder
. To return to our user folder type cd ..
. The ..
refers to the parent directory, i.e. the directory above that encloses the directory we are currently inside.
Next, let’s delete the folder we made earlier. (BE CAREFUL here - you don’t want to accidentally delete the wrong folder! 😉) Type rmdir new_folder
and that’s that taken care of.
And that’s all the basics of navigating file structures in the command line, as well as creating and deleting files and folders. One last tip: while typing a command, like cd new_folder
for instance, you can press tab while you’re typing the file or folder name to have cmd autocomplete it for you. If a different file appears first that shares the same letters, keep pressing tab to cycle the files till you find the one you want.
Visual Studio Code, otherwise known as VSCode or VSC is a text editor highly developed and optimised for writing code. It supports hundreds of programming languages and thousands of extensions to improve your efficiency.
VSCode is great tool to familiarise yourself with; it is used by a huge number of professionals every day. In fact, this site was developed using VSCode as a text editor!
To get set up, type "Visual Studio Code" into your search browser or go to https://code.visualstudio.com/.
The website should automatically detect the correct version for your operating system, but if for some reason it does not, simply click the down arrow to the right of the download button. This will display other versions for you to download.
Once downloading has finished you should have a file named something similar to "VSCodeUserSetup-{version}.exe." Agree to the license terms and select the options you would like. From there, you can launch VSC!
Downloading this on Mac should give you a .zip file. Double click it the same as when you’re downloading anything else. Drag "Visual Studio Code.app" to the "Applications" folder, so it is available in the "Launchpad". Then double click it to open VSC!
Git command line (cli) comes preinstalled on most Mac and Linux devices, to check if it is installed, type git version
into your “Terminal” if on Mac, or “Command Prompt or Git Bash” on Windows. If it is not installed simply search for “Git” on your search browser and find the downloads page, or enter https://git-scm.com/downloads into the URL. It is recommended that you install Git Bash and Git Credential Manager to make authenticating Git and Github easier.
From the official Git website, click the download for your respective operating system. Follow the same setup steps as VSCode from there.
We have already installed Git, and now we will look at Github. These are different tools by different vendors, so let's define each:
This section looks at setting up your GitHub account and getting it to talk to Git.
We will begin by visiting GitHub’s home page at: https://github.com
Click on the link to sign-up. On this page, you can enter your email address. You must then: create a password, create a unique username, select whether you would like to receive product updates and announcements via Email (Y-yes/N-no), and finally complete a puzzle to verify you are human.
Congratulations, you should now have a GitHub account and are ready to start some collaborative coding!
Now that you have set up your GitHub account you can connect it to Git, which should be installed on your device. If you are using Mac or Linux device open Terminal and if you are using Windows open the Command Prompt. From here we can check Git is correctly installed by typing: git --version
. This should give you the current version of Git installed on your device, if this is not the case you should go back to the previous section and make sure Git, Git Bash and GCM are installed.
To begin, we need to set some global variables for our local Git installation. Open up Git Bash and type the following:
git config --global user.email "hello@example.com"
Where the Email address within the quotation marks is replaced by the email address you used to set up your GitHub account.
Git will now use this mail address to link your future commits with your GitHub account. From here we can use another command:
git config --global user.name "Your Name".
This will set the author name of all your commits to be published under the name input in “Your Name”.
We can now try getting Git to talk to GitHub. This is the trickiest part, as there are several ways to go about setting this up, and GitHub has changed authentication methods overtime to make this more secure. In this case, we are going to set up communication between Git and GitHub over HTTPS (this is the standard protocol that you use to browse the web) with a Personal Access Token or PAT. Why not just use a password? As of August 2021, GitHub decided to remove support for passwords for authentication due to security concerns.
If you have installed Git Credential Manager with Git, then setting this up is very simple. When you go to do something that requires authentication, a browser window will open up and guide you through the authentication process. Then GCM will store the credentials for you, and you will never have to think about it again. That wasn't so bad!
If for whatever reason GCM is not working, you'll have to manually create a token in GitHub:
If you are still having issues with authenticating to GitHub, welcome to development! You may find some helpful guidance in the GitHub docs.
Your local installation of Git should now be able to communicate with Github. This means that you are now ready to start pushing code directly to GitHub from the command line.
When we work with Git on our machines, we:
git push
command is used to push the commit of changes made on your local machine to a remote repository such as GitHub.To start with, let’s create a new repository on GitHub. This is where we will push our local repository to later:
Now, let’s initialise a local git repository and add a readme file. So open up your command line window. The command prompt should default to C:\Users\’your_own_name’ on a Windows machine. For demonstration purposes, let’s initialise the git repository here in the default location. But first, we need to create a folder to contain our project. You can do this either by manually creating it through the file explorer or just input this command into the command prompt:
mkdir git_tutorial
Then you would need to move to the specific folder before we initialise the git repository so we use the command:
cd git_tutorial
Now that we are in our project folder, we can finally initialise the repository. To do that we use the command:
git init
Now that we have initialised our repository, we can now get started on creating our readme.md file for our repository. To open up VSCode in the current folder you can use the command:
code .
If this has not automatically set up when you installed VSCode, you can just open VSCode from the start menu/launchpad like any other app.
README.md
with the file extension .md standing for Markdown.So input:
# Example Header this is some content for my readme ``` code blocks go between triple backticks like this, or between triple tildas (~~~) ```
Or whatever you want to put as the title header for the readme file then input whatever text under the header. This would typically be a description of the project, how to run it and maybe some screenshots.
Now that we have finished typing in our README.md file, we can now save it. Go to File -> Save As -> browse to our repository location “C:\Users\’your_own_name’\git_tutorial” and remember to name the file README.md (with the captial letters).
We can now do our first commit to our repository. To do that we need to use several commands. First use:
git add . git status
Using ‘git add’ will add all the new files ready for the commit, and the .
is shorthand for "all". ‘git status’ will show a list of all the files staged to the first commit. You should see your README in this list highlighted in green.
Now for our first commit, we need to use:
git commit -m "your message"
The ‘-m’ flag is used for a message to set the commits where the full description is written. E.g. “what was changed”, “why was the change made” Remember to put your message in quotations otherwise the command won’t go through. For example:
git commit -m “First Commit”
Now we need to link this local repository to the repository created in GitHub. Return to the page on GitHub that you reached earlier. Beneath "...or push an existing repository from the command line" you should see:
git remote add origin https://github.com/youraccount/hello-world.git git branch -M main git push -u origin main
The first command adds the remote repository based on the URL name given and ‘origin’ is used as the remote name. A git remote is just a git repository that is hosted online. We have to give git a remote name so that it knows where to push to. The second command is saying that the main branch is defined as "main", which is the default anyway.
The third command “git push -u origin main” pushes the content to the remote repository. ‘Origin’ is the remote repository name, ‘-u’ flag is upstream which is the equivalent to ‘-set-upstream’ and the ‘main’ is the branch. After this point, if you are just pushing commits to the main branch, you can just shorten this to:
git push
After this, you should have successfully pushed all the changes to the remote repository in GitHub. You should see on GitHub the README.md file you created with the content you filled in from before.
TIP: the default branch on new github repositories used to be called
master
. This was changed to bemain
instead by Github in 2020. Since some people have older git installs, this can occasionally cause some issues when pushing a repo up, as git expects amaster
and can't find it. If this is happening to you, trygit push -u origin master
instead.
git init
- initialise a new repositorygit config --global user.name “John Smith”
- configure the author name to be used with your commits.git config --global user.email john@example.com
- configure the author email address to be used with your commits.git config -l
- check the configurationgit status
- check the repository statusgit add <filename> or git add .
- choose(stage) the files you want to take a snapshot of. You can choose specific files but normally you would want to take a snapshot of all the filesgit commit -m ‘placeholder’
- make the commit, this only affects the files that are currently staged. Every commit needs to have a short description of what has changed in single quotesgit branch
- Lists all the branches and places an asterisk against the one we are currently on.git checkout -b ‘placeholder name’
- Creates a new branch and switches to itgit checkout
- use to switch between branches, commits on different branches won’t show on the master branchgit merge placeholderBranch -m ‘placeholder’
- use to merge branches, first checkout branch you want to merge into then type the branch you’re merging, with a suitable note in single quotesgit push
- push your commits to the GitHub servergit push origin master
- This command pushes the commits on your master branchgit push --all origin
- push all branches using this commandgit clone ‘placeholder git link’
- This downloads the entire repository to your local computer as a clone so you can contribute to a project already pushed onto GitHubgit pull
- To fetch any changes made by other developers on the projectNow that you’re eating code challenges for breakfast, you’ll (hopefully) be getting interviews. Every company runs the interview process differently, but in general, you can expect:
Interviews are stressful, nobody likes them. Here are some tips that may help you relax.
Test Automation Engineer
Think you might have what it takes to join us? Get in touch
2i is an award-winning quality assurance and software testing consultancy company. Since our inception in 2005, we have matured into a thought-leading business that can, and does, support organisations of any sector or size. We have over 200 colleagues across the UK, with offices across Edinburgh (our Head Office), Glasgow, the Midlands and London.
If you think a career in tech might be your next move, or even if you just found this app useful, we would love to hear from you!