Snail Array Challenge Solution JavaScript
Tags: challenge, webdev, 365daysofcoding, javascript
Published: 2021-01-05 23:22:56

Day 5 of 365 days of coding!

### [Link to the video](https://youtu.be/ynfNm1Zw4tU)

Today we are borrowing a challenge from [Codewars](https://www.codewars.com/kata/521c2db8ddc89b9b7a0000c1/javascript)! 

**Disclaimer:** This is not my challenge the original challenge is linked about. Also, there are MANY ways to solve this problem. These are a few answers that I wrote or find clever with explanations of why/how they work

**TLDR:** explanation of best solution at the bottom of the post and actual solutions at the bottom of each section

## The Problem
Create a function that accepts and array. Given an n x n array, return the array elements arranged from outermost elements to the middle element, traveling clockwise.

Examples: 
```javascript
        snail( [[1,2,3], [4,5,6],[7,8,9]]) // [1,2,3,6,9,8,7,4,5] 
        snail([[1,2,3], [8,9,4], [7,6,5]]) // [1,2,3,4,5,6,7,8,9]
        snail([[1,2,3,1], [4,5,6,4], [7,8,9,7], [7,8,9,7]]) // [1,2,3,1,4,7,7,9,8,7,7,4,5,6,8,9]
```
The image below may help. You can also go to the [Codewars](https://www.codewars.com/kata/521c2db8ddc89b9b7a0000c1/javascript) page for more information and to test out your solution

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/w9x5qde6glz3e3dtkntx.png)

## Solutions
So lets break down some possible solutions

possibility 1

    * create a variable for the final array

    * loop through the parent array - while array still has items in it

        * get the first row (first array in the array)

        * get the items at the end of each array (right side) 

        * get the bottom row from end to front (bottom row reversed)

        * get the items at the beginning of the arrays (left side)

possibility 2

    * create a variable for the final array

    * loop through the parent array - while array still has items in it

        * get the fist row

        * get the last item in each array

        * reverse the parent array and each array in the parent array

### Solution 1 - Readability and Performance
First we need to create out function that accepts an array
```javascript
const snail = (arr) => {
  //create a variable for the final array
  //loop through the parent array - while array still has items in it
    //get the first row (first array in the array)
    //get the items at the end of each array (right side) 
    //get the bottom row from end to front (bottom row reversed)
    //get the items at the beginning of the arrays (left side)
}
```
We have to create variable to push everything into to get our final array. We will instantiate this as an empty array that everything will get added to and if there is nothing to add it to we will return the [] at the end as expected
```javascript
const snail = (arr) => {
  let finalArray = []
  //loop through the parent array - while array still has items in it
    //get the first row (first array in the array)
    //get the items at the end of each array (right side) 
    //get the bottom row from end to front (bottom row reversed)
    //get the items at the beginning of the arrays (left side)
}
```
Now we need to add a while loop. If you are not familiar with them check out [this MDN page](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/while). We need to do a while loop here because we don’t know how many times the loop is going to have to go through to get the final answer. We are going to make the loop while array has a length as we will be removing items from each array as we loop. In the end the array will have nothing left in it so the length will be 0 and that is when we will end to loop execution.
```javascript
const snail = (arr) => {
  let finalArray = []
  while (arr.length){
    //get the first row (first array in the array)
    //get the items at the end of each array (right side) 
    //get the bottom row from end to front (bottom row reversed)
    //get the items at the beginning of the arrays (left side)
  }
}
```
We want to get the first array in the array of arrays (the first row) if you don’t know how [.shift()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/shift),  [.push()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/push), or the [spread operator](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax) works check out this MDN page but basically it takes the first item in an array.
```javascript
const snail = (arr) => {
  let finalArray = []
  while (arr.length){
    finalArray.push(...arr.shift())
    //get the items at the end of each array (right side) 
    //get the bottom row from end to front (bottom row reversed)
    //get the items at the beginning of the arrays (left side)
  }
}
```
We need to get all the items at the end of each array (the right side) if you are unfamiliar with [for loops](https://www.w3schools.com/js/js_loop_for.asp) or [.pop()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/pop) check out the links on each one before continuing.
```javascript
const snail = (arr) => {
  let finalArray = []
  while (arr.length){
    finalArray.push(...array.shift())
    for (var i = 0; i < arr.length; i++) {
        finalArray.push(arr[i].pop());
    }
    //get the bottom row from end to front (bottom row reversed)
    //get the items at the beginning of the arrays (left side)
  }
}
```
now we need to get the last array and reverse it (bottom line) if you are unfamiliar with .reverse() check out [this MDN page](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/reverse) before continuing. you will notice that I am giving it an empty array just in case there is no last array or nothing is there the .reverse will error if it doesn’t have at least an empty array so we are giving it an empty array if array doesn’t have something to pop.
```javascript
const snail = (array) =>{
  let finalArray = []
  while(array.length){
    finalArray.push(...array.shift())
    for (var i = 0; i < array.length; i++){
      finalArray.push(array[i].pop())
    }
    finalArray.push(...(array.pop() || []).reverse())
    //get the items at the beginning of the arrays (left side)
  }
}
```
All we have left is to get the left side so we need to get all of the first items from each array. You will notice that i is going to be the length of the array -1 because we don’t want to grab the first array. we will grab that in the next loop so we only want the first numbers from each array before the first one.
```javascript
const snail = (array) =>{
  let finalArray = []
  while(array.length){
    finalArray.push(...array.shift())
    for (var i = 0; i < array.length; i++){
      finalArray.push(array[i].pop())
    }
    finalArray.push(...(array.pop() || []).reverse())
    for (var i = array.length -1; i >= 0; i--){
      finalArray.push(array[i].shift())
    }
  }
}
```
Last but not least, we return that finalArray that we have been building
```javascript
const snail = (array) =>{
  let finalArray = []
  while(array.length){
    finalArray.push(...array.shift())
    for (var i = 0; i < array.length; i++){
      finalArray.push(array[i].pop())
    }
    finalArray.push(...(array.pop() || []).reverse())
    for (var i = array.length -1; i >= 0; i--){
      finalArray.push(array[i].shift())
    }
  }
  return finalArray
}
```
### Solution 2 - Clever and Less Lines of Code
This solution is one everyone loves on [Codewars](https://www.codewars.com/kata/521c2db8ddc89b9b7a0000c1/javascript) it is less performant and I don’t like the readability of it but it is less lines of code and very clever so I thought I would share it with you.

The first few lines are the same as the first solution
```javascript
const snail = (arr) => {
  var finalArray = [];
  while (arr.length) {
    finalArray.push(...arr.shift());
    //get the last item in each array
    //reverse the parent array and each array in the parent array
  }
}
```
The next part is very similar to the first solution and you can actually switch our the first for loop for this but we are going to use [.map()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map) to get the last number from each array (row) and push it into the finalArray
```javascript
const snail = (arr) => {
  var finalArray = [];
  while (arr.length) {
    finalArray.push(...arr.shift());
    arr.map(row => finalArray.push(row.pop()))
    //reverse the parent array and each array in the parent array
  }
}
```
This is where it gets really interesting. Instead of getting the bottom row reversed now we are going to reverse the whole array and each item in the arrays within the parent array and do all the same logic. This will flip everything so instead of getting the top row we are getting the bottom and instead of getting the right side we are getting the left. Then the loop continues
```javascript
const snail = (arr) => {
  var finalArray = [];
  while (arr.length) {
    finalArray.push(...arr.shift());
    arr.map(row => finalArray.push(row.pop()))
    arr.reverse().map(row => row.reverse());
  }
}
```
At the end we return our finalArray and TA DA! you have your solution 
```javascript
const snail = (arr) => {
  var finalArray = [];
  while (arr.length) {
    finalArray.push(...arr.shift());
    arr.map(row => finalArray.push(row.pop()))
    arr.reverse().map(row => row.reverse());
  }
  return finalArray
}
```
pretty cool huh?

## Conclusion
The second solution is pretty clever and has less lines but it is harder to read and it is not as performant. below is the [jsbench](jsbench.me) performance results using the examples above for anyone who is interested.
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/hn4d7tgx7rqgy8r89zdo.PNG)
I hope you had fun with this one! Please leave your solutions that you came up with in the comments section. If you have any challenge you would like to see done also leave that in the comments below you may see it come up! If you would like to get the challenge emailed to you every day in morning and a notification when the solution is posted subscribe [here](https://hellodevworld.com/misc/365-of-coding-announcement).