Six Steps to Tackle Any Algorithm
Published: 2022-01-30 21:10:41

One of the best things about programming is experiencing that moment when everything clicks, the program works, and the problem is solved. I love that feeling and I don't think I'm alone. 

You know what sucks though? That moment when the code doesn't work, you have no idea why, and you're being timed. That's not a good feeling and, again, I don't think I'm alone. 

I recently started a software engineering bootcamp at [Flatiron](https://flatironschool.com/) and have had a steady diet of both feelings over the past few weeks. However, as part of the curriculum I recently received an algorithm for solving algorithms. At first I thought the extra work was, well, just extra work, but having a mental framework to leverage when the way forward isn't clear has proved to be invaluable. 

[Here](https://www.codewars.com/kata/523f5d21c841566fde000009/train/javascript) is a coding challenging I worked through on [Codewars](www.codewars.com). Honestly, this is a challenge I would have passed on until recently, but armed with a handy problem solving framework I managed to solve it. 

Here's how I broke down the problem, step by step. 


## 1. Rewrite the Problem in Your Own Words

Here is the question as written on Codewars: 

> Your goal in this kata is to implement a difference function, which subtracts one list from another and returns the result.

> It should remove all values from list a, which are present in list b keeping their order.

Rewriting helps clarify several things, in particular the input and output data types. I've found it's helpful to look at any test conditions, if provided, to see if there are special circumstances to consider (e.g., blank arrays, invalid inputs, etc). I rewrote the problem as follows:

> You are given two arrays of numbers as inputs. Take each number in the second array and remove all instances of that number from the first array. Return an array of the remaining numbers. 


## 2. Write Your Own Test Cases.

This doesn't mean you actually have to write code for unit tests. Simply writing a few instances of the input and expected output of a function can help ensure all expectations of the challenge are considered. 

```
function arrayDiff(a, b) {

}

arrayDiff([1,2,2,2,3,4], [2])
// returns [1,3,4]

arrayDiff([1,2,3,3,4,4], [3,4])
// returns [1,2]
```


## 3. Pseudocode the solution.

Personally, this is one of the most valuable steps for me. Writing out how to approach the problem step by step in plain english provides an outline for how to go about solving the problem. This is especially critical as the complexity of the challenge increases. 

Another reason to pseudocode is to demonstrate how you would approach a problem even if you can't ultimately solve it. If I were given a problem I'm unable to solve in an interview, *I'd rather show the interviewer what I know than sit there in a catatonic stupor.* 

```
/*
1. Iterate through the first array and look for the first value of the second array (maybe a for loop?).
  a. If the value exists in the first array, delete it (maybe using splice?). 
2. Repeat the process for each value in the second array (I might need a nested loop here). 
3. Return a single array of values.
*/ 
```


## 4. Code a solution.

Now that we have an outline, it's time to put some code together. Here's what I had for my first attempt at completing step 1:

```
function arrayDiff(a, b) {
  for ( i = 0; i < a.length; i++) {
    if (a[i] === b[0]) {
      a.splice([i], 1)
    }
  }
  console.log(a)
}

arrayDiff([1,2,2,2,3,4], [2])
// returns [1,2,3,4]
```

This looked promising at first, but I wasn't getting consistent results using my tests. I found that using `splice()` this way allowed for repeats to slip through the cracks because of the way the placement of values in the array shift every time `splice()` is used. To prevent this I iterated through the array backwards:

```
function arrayDiff(a, b) {
  for ( i = a.length -1; i > -1; i = i - 1) {
    if (a[i] === b[0]) {
      a.splice([i], 1)
    }
  }
  console.log(a)
}

arrayDiff([1,2,2,2,3,4], [2])
// returns [1,3,4]
```

This solves step 1 for me, but the function does not allow for the b array to be longer than one number. All I need to do at this point is figure out how to loop through the second array. This was my attempt:

```
function arrayDiff(a, b) {
  for ( j = 0; j < b.length; j++)
    for ( i = a.length -1; i > -1; i = i - 1) {
      if (a[i] === b[j]) {
        a.splice([i], 1)
      }
    }
  console.log(a)
}

arrayDiff([1,2,3,3,4,4], [3,4])
// returns [1,2]
```

It works! At this point I have code that does it's job, but there are two more steps before I'm ready to submit. 


## 5. Clean Up the Code

A quick review of the function helps to ensure indentations and variable names are clear and clean. I don't have any variables to worry about but my `i` and `j` variables really should be switched. Also, I can iterate through the loop backwards by changing `j = j - 1` to `j--`. I'll also change my `console.log` to `return`.

```
function arrayDiff(a, b) {
  for ( i = 0; i < b.length; i++)
    for ( j = a.length -1; j > -1; j--) {
      if (a[j] === b[i]) {
        a.splice([j], 1)
      }
    }
  return a
}
```


## 6. Consider Optimization

At this point in my learning I'm just beginning to explore optimization. I wasn't a fan of using a nested loop and I was fairly sure there was a better way to go about solving this. 

One of the things I love most about Codewars is the feedback you get after submitting a correct solution. I've had many *forehead slap* moments after seeing a solution much easier than my own. 

Here's what Codewars provided as the top answer under "Best Practices": 

```
function array_diff(a, b) {
  return a.filter(e => !b.includes(e));
}
```

This was definitely a forehead slap moment. I hadn't considered using `filter()` in conjunction with `includes()`. Also, this was also the first time I've seen the bang operator used with an array method. 

I'll just go ahead and repeat this process a few thousand times and I think I'll be well on my way to increasing my proficiency as a programmer.