# CoDEVIANT #21 (10/11/20) — Spiral Motion

--

So I’ve got a neat doozy of a problem to write about here.

We are to write a problem that takes a two-dimensional array and returns an array of the values when the values are read in a spiral motion.

So…I got a confession to make. I couldn’t figure out how to solve it by myself. After a number of failed attempts, I swallowed my pride and consulted the experts. But I learned a lot and I’m excited to share some knowledge with you!

Before I share the answer, I want to give an example of the kind of information we’ll be providing as an argument to the function.

Assuming we pass in:

`[`

[1, 2, 3, 4],

[12, 13, 14, 5],

[11, 16, 15, 6],

[10, 9, 8, 7]

]

The function should push values to a new array like so

[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]

Notice that we avoid repeating any of the values. We achieve this by the following steps:

- Read the top row from left to right, including the far right value.
- Read the far right column omitting the very top value and including the very bottom value.
- Read the bottom row from right to left omitting the right-most value and including the left-most value.
- Rad the far left column, omitting the far left bottom value and the far left top value.

What we’re going to do is read the perimeter like this, then once we finish the outer perimeter, we (if there is one present) move into the inner perimeter.

Here’s the solution:

`function spiralTraverse(array) {`

// Write your code here.

let results = []

let startCol = 0

let startRow = 0

//endRow signifies the start places of each row up and down the verticle side of the block

let endRow = array.length - 1

//endCol signifies the start places of each column across the top of the block

let endCol = array[0].length - 1

while(startCol <= endCol && startRow <= endRow) {

//top

for(let col = startCol; col <= endCol ; col++) {

results.push(array[startRow][col])

console.log('top', results)

}

//right

for(let row = startRow + 1; row <= endRow; row++) {

results.push(array[row][endCol])

console.log('right', results)

}

//bottom

for(let column = endCol - 1; column >= startCol; column --) {

if(startRow === endRow) break

results.push(array[endRow][column])

console.log('bottom', results)

}

//left

for(let row = endRow - 1; row > startRow; row --) {

if(startCol === endCol) break

results.push(array[row][startCol])

console.log(results)

}

startCol++

startRow++

endCol--

endRow--

}

return results

}

First we create an empty array called *results*. Then we create some pointers signifying the coordinates that we’re going to use to point to the value in the two-dimensional array that we want to push into *results*.

`let results = []`

let startCol = 0

let startRow = 0

//endRow signifies the start places of each row up and down the verticle side of the block

let endRow = array.length - 1

//endCol signifies the start places of each column across the top of the block

let endCol = array[0].length - 1

We are going to create a while-loop that will be active as long as *startCol *is less than OR equal to *endCol ***AND ***startRow* is less than OR equal* *to *endRow. *At the end of each iteration of this while loop, *startCol* and *startRow* will be incremented by one. *endCol* and *endRow* will be decremented by one. This prevents the while-loop from running infinitely.

`while(startCol <= endCol && startRow <= endRow) {`

...

startCol++

startRow++

endCol--

endRow--

}

Next we are going to set up for-loops that will read the values from the perimeter in the directions discussed above (lengths too). They are:

- top // left to right
- right //top to bottom
- bottom // left to right
- left //bottom to top

**top**

`for(let col = startCol; col <= endCol; col++) {`

results.push(array[startRow][col])

}

We say that *col* equals whatever *startCol* is at that moment. We keep the for-loop going as long as *col* is less-than or equal-to *endCol *at that moment. After each loop, *col* increments by one. Then we push whatever value is at **array***[startRow], [col]***.**It would be like

array[0][0] //

**,**

*(1)*array[0][1] //

**,**

*(2)*array[0][2] //

**,**

*(3)*array[0][3] //

*(4)***right**

`for(let row = startRow + 1; row <= endRow; row++) {`

results.push(array[row][endCol])

}

We say that *row* equals *startRow* plus 1. This for-loop stays active so long as *row* is less-than or equal-to *endRow. *After each iteration, row increments by one. We then push the value of whatever **array***[row][endCol] *is into *results*.

array[1][3] // (**5)**

array[2][3] // (**6)**

array[3][3] // (**7)**

**bottom**

`for(let column = endCol - 1; column >= startCol; column --) {`

if(startRow === endRow) break

results.push(array[endRow][column])

console.log('bottom', results)

}

We say that *column* equals *endCol* minus one. The for-loop stays active as long as *column* is larger than or equal to *startCol*. After each iteration, *column* decrements by one. To avoid repeated integers, we say that if *startRow* equals *endRow*, then we break the loop. Meaning we jump out of it and move along with what’s going on in the parent while-loop. Anyways, in most cases we push whatever value we get from **array**[endRow][column].

At the start the values we’ll be pushing are:

array[3][2] // **(8)**array[3][1] //

**(9)**

array[3][0] //

**(10)**

**left**

`for(let row = endRow - 1; row > startRow; row --) {`

if(startCol === endCol) break

results.push(array[row][startCol])

console.log(results)

}

We then say that *row* equals *endRow* minus 1. The for-loop keeps running as long as *row* is larger than *startRow. *Each iteration has *row* decrementing by one. If *startCol* and *endCol* equal eachother, then the for-loop breaks. In most other cases, we push the value at **array**[row][startCol] into *results*:

array[2][0] // (**11)**array[3][0] //

**(12)**

At this point, the *startRow* and *startColumn *values increase by one. Then the *endRow* and *endColumn* values decrease by one. This makes it so that we can establish a new inner-perimeter so we can push the inner values into our *results *array.

And that’s basically how this problems works. It’s a pretty cool one and, on the outset, seems like a really impressive problem to be able to solve.

Stay frosty…