Learn to Code!
Looking for your next step?
Learn to Code!

Introduction

Why should you learn to code?

All kinds of people can do it

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.

Code is everywhere

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 is not just for developers

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.

Completing a coding challenge is typically the first interview step at a tech company. They are also pretty fun.

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.

Write your first code

Over the next six lessons, you'll learn everything you need to start tackling code challenges

Lesson 1: JavaScript and Node

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.

Lesson 2: Variables, print statements and comments

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:

  • We declared a variable using “let”, gave it a name of “myName” and gave it a value of “Lewis”.
  • We only need to use “let” when first declaring the variable, after that, we can refer to it by its name.
  • We then printed the variable called “myName” to the console. The console log shows the value of myName.

Try changing “Lewis” to your name and running the code again

Variables:

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.

Constants:

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

Lesson 3: Data types, operators, and string concatenation

Data Types:

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:

Number:

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

String:

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:

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:

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:

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:

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)

String concatenation and string length:

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

Lesson 4: Basic functions and principles for using them

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:

  • We are defining the function using the “function” keyword and giving it the name of “multiplier”
  • “number1” and “number2” are parameters. We use parameters as placeholders for whatever data we pass into the function when we call it. You can think of parameters as the function’s input.
  • We return the results of multiplying number1 and number2 together. Return statements are very important, as they pass results back out of the function so that they can be used.
  • When we call the function, we are passing in two numbers to be multiplied. The data that you pass in is referred to as an argument.
  • In this case, we are assigning the output of the function to a constant, but we could also just place it inside of the console.log().

There are a few principles to stick to when writing functions:

1. Functions should be reusable

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

2. A function should cover a single task

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)    } }
3. Function names should be descriptive

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

Lesson 5: Arrays, Objects and Methods

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:

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:

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

Lesson 6: Loops, ifs, and Comparators

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)

Comparators:

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

Combining comparators

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))

Truthy and Falsy

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

Lesson 7: Guided Coding Challenge

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]

1. Firstly, create the function definition and add the visitor height array and minimum height value as parameters. This makes the function more reusable if, for example, the minimum height were to change.
function checkQueueHeights(visitorHeights,minimumHeight){ }
2. Create a new empty array for the result.
function checkQueueHeights(visitorHeights,minimumHeight){    const result = [] }
3. Now, we create our loop. We are iterating over an array, so a “for of” loop is “best practice” although “for in” would work too.
function checkQueueHeights(visitorHeights,minimumHeight){    const result = []    for (visitor of visitorHeights) {    } }
4. Now we add the logic that evaluates whether the visitor is tall enough and adds a true value to the results if they are.
function checkQueueHeights(visitorHeights,minimumHeight){    const result = []    for (visitor of visitorHeights) {       if (visitor >= minimumHeight) {          // adds boolean true value to the result array          result.push(true)       }    } }
5. What if the if statement resolves as false? Let’s add an else, and add a false value to the results
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)       }    } }
6. Now to complete the function, we need to return the completed array of Boolean values. This will come at the end of the function, outside of the loop.
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 }
7. Finally, we need to call the function with some arguments in order to see the results.
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.

Part 1a: Extra Credit and Points for Style

Some useful tips and tricks

Extras

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:

  1. Your code challenges will look really slick
  2. These techniques will appear in lots of code examples. If you understand other people’s code, then you can steal copy bits that are useful to you!

Arrow functions

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.

Class Methods & Callbacks

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)

ES6

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.

Code Challenges

Pseudocode: like code but not

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 }

Why console.log() is your best friend

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:

  1. To check that a block of code runs
  2. To check on the value of a variable as it moves through code

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!

Coding challenge 1

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

Coding challenge 2

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

Finding more code challenges

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!

Publishing Your Work to Github

Create an online portfolio of your work for employers

Lesson 1: Command-line Interfaces

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.

Lesson 2: Installing VS Code and Git CLI

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.

Windows:

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!

Mac:

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

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.

Lesson 3: Setting up a GitHub account and connecting it to Git

We have already installed Git, and now we will look at Github. These are different tools by different vendors, so let's define each:

  • Git is a version control software (VCS) which is used to track changes to code from the command line. Because it uses branching It allows any number of developers to download a piece of code, work on it and contribute changes without breaking the original. Because all of your changes are tracked by Git, it is very hard to break your code, as long as you keep committing! Git is fully open-source.
  • Github is a code hosting platform that uses Git as the base, and then adds lots of interesting features on top. GitHub lets you push your Git repositories to the web, where others can download them and collaborate. It also allows you to share and display your work as a developer, which is what we are looking at in this chapter! Many developers use GitHub as a showcase of their coolest projects. Github is owned by Microsoft.

This section looks at setting up your GitHub account and getting it to talk to Git.

Signing up for GitHub:

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!

Getting GitHub to talk to Git:

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:

  1. Log in to GitHub and click on the avatar icon on the top-right of the page to bring up a drop-down menu.
  2. Select "Settings"
  3. Scroll down the page and click on "Developer Settings", then "personal access tokens".
  4. Click on the "generate new token" button
  5. Give the token a name and set the expiration to a fairly long setting.
  6. Set the scopes for the token. You will certainly want to check the "repo" box.
  7. Click "Generate token" and copy the token displayed. Make sure that you save it somewhere as you will need it and cannot view it again on GitHub.
  8. From the command line, when you are pushing or pulling to GitHub you will be prompted for a username and password. The token is the password, not the one that you used to sign up for GitHub. Pushing and pulling will be covered in the next lesson.

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.

Lesson 4: Pushing to Github and adding a Readme

When we work with Git on our machines, we:

  1. initialise a repository at the root folder of whatever project we are working on
  2. When we have made some progress, we make a commit. This is like a snapshot on the project as it is. Git has some tools that allow us to go back and forth between commits if we find that we have made a mistake and need to go back.
  3. The 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:

  1. Go to GitHub.com and log in.
  2. Somewhere on the left hand side of the screen should be a green button which says "new".
  3. If you are offered a template, select "no template" and give the repo a name of "hello world".
  4. Ensure that all of the checkboxes are unticked, especially "add a README file" and click "Create repository".
  5. You should now see a page with several lines that you can copy and paste into the command line to push a local repo up to GitHub. We will come back to this page 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.

  1. In VSCode, on the top left click File -> New File.
  2. Give the file a name of README.md with the file extension .md standing for Markdown.
  3. Open up your README. These files are written in Markdown, which allows you to use symbols to decorate text. For example, you can create headers with the ‘#’ symbol before the text. For more information regarding Markdown and all the syntax, you could use, check out https://www.markdownguide.org/cheat-sheet/.

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).

Staging

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.

Committing

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 be main 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 a master and can't find it. If this is happening to you, try git push -u origin master instead.

Extra: Reference List of Git Commands

  • git init - initialise a new repository
  • git 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 configuration
  • git status - check the repository status
  • git 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 files
  • git 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 quotes
  • git 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 it
  • git checkout - use to switch between branches, commits on different branches won’t show on the master branch
  • git 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 quotes
  • git push - push your commits to the GitHub server
  • git push origin master - This command pushes the commits on your master branch
  • git push --all origin - push all branches using this command
  • git 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 GitHub
  • git pull - To fetch any changes made by other developers on the project

Nail the tech Interview

Tech interviews have some unique challenges, here are some tips to make the best of them

Now 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:

  • A conversation with two interviewers lasting around thirty minutes to an hour (sometimes longer if you are asked to complete a code challenge during the interview)
  • A portion of the interview where you discuss yourself and your background. You’re likely to be asked some generic “competency” questions. These generally relate to things like the role you take in teams, how you learn best, what projects you have worked on etc. At a junior level, you can expect this section to take up the bulk of the interview.
  • A portion of the interview where you answer some technical questions. These are intended to gauge your understanding, but also how well you can explain complex concepts. At a junior level these are usually relatively simple, so don’t worry too much!
  • Some companies may ask you to complete a coding challenge during the interview. If this is the case, they will usually give you some time to complete the task alone.
  • If you completed a coding challenge before the interview, you may be asked to do a walkthrough of the code. Take it line by line, and clearly explain what each line does.

Some tips for a successful interview:

  • Don’t worry about being too formal. Tech is generally a fairly casual industry, so just be yourself and be friendly. Remember that we want to work with people that we like!
  • Do your homework on the company and the role. Understand what the company does, and what you would be doing there. Make some notes that you can refer to about some of the company’s clients, the tech that they use, where their office is, and who their CEO is. Being able to bring any of these up shows that you are genuinely interested.
  • Have some answers in your pocket. Competency and tech questions don’t change too much from company to company, so look up some lists of interview questions online and have a few prepped answers ready to go with examples from your life/career.
  • Ask questions. Come to the interview prepared with 5 or so relevant questions (but not “how much does it pay?”) and take notes during the interview so that you can ask some based on your conversation.
  • Honesty is important. If you don’t know something, that’s fine! At a junior level, most employers will provide training, and showing a willingness to learn is more important than knowing a tech already. On the other hand, if an interviewer gets the feeling that they are being lied to, there’s no way that you’ll be getting the job!
  • Being humble !== putting yourself down. You can be honest about shortcomings without being negative. For example, instead of saying “I’m bad at Java”, say “Java is something that I would like to get better at”.
  • Present yourself well. There’s no need to wear anything too formal but try not to look like you just rolled out of bed (even if you just did). If you’re interviewing remotely, check how your room looks on the webcam. If it’s anything short of an Architectural Digest cover, just stick a background filter on.

Interviews are stressful, nobody likes them. Here are some tips that may help you relax.

  • Prepare as best you can. It may sound obvious but being prepared will genuinely help you relax. If the company has not told you what to expect on the day, you can always ask!
  • Make sure that you have lots of water. Try and have a jug as well as a glass. Water will keep your voice clear, and you can always take a sip if you need to buy a moment before answering a question.
  • Remember that interviewers are just people! We want you to do well in the interview, so try not to feel like it is a combative situation.

Career Changers at 2i

Carla Chiodi

Carla Chiodi

Test Automation Engineer

Changing my career was the right choice to pursue my passion for learning and problem-solving, with the bonus of career progression and professional development.
Craig McLeod

Craig McLeod

Test Automation Engineer

With a background in life sciences degree and food and beverage QC, I thought that my path was set, but I picked up coding as a hobby and something was sparked in me. I discovered that a career change was not only possible but that this new industry brought together so many things I enjoyed: problem solving, designing, creating and having real pride in tangible efforts.
Lewis Saunders

Lewis Saunders

Test Automation Engineer

Coming from an arts background, I was amazed at how many skills transferred over to tech, and by how much I was able to bring to the table right away.

Think you might have what it takes to join us? Get in touch



Let's 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!