user6895092 user6895092 - 2 months ago 14
Javascript Question

how to spirally traverse a matrix recursively - javascript

Please look at this JSFiddle: https://jsfiddle.net/hc2jcx26/

I am trying to spirally traverse a matrix

output
(any size) so that it prints each element in spiral order to
console.log
every 2 seconds:

var output = [[0, 1, 2, 3],
[4, 5, 6, 7]];

function spiralOrder(output) {
var rows = output.length;
var columns = output[0].length;
var top = 0;
var down = rows - 1;
var left = 0;
var right = columns - 1;
var result = [];

var side = 'top';
var i;

while(top <= down && left <= right) {

if (side === 'top') {

(function myLoop (i) {
setTimeout(function () {
console.log(output[top][i]);
if (++i <= right) myLoop(i); //READ LEFT TO RIGHT FROM TOP, IS THIS NOT CORRECT?
}, 2000)
})(left);

top++;
side = 'right';
continue;
}
if (side === 'right') {

(function myLoop (i) {
setTimeout(function () {
console.log(output[i][right]);
if (++i <= down) myLoop(i); //READ TOP TO BOTTOM FROM RIGHT
}, 2000)
})(top);

right--;
side = 'bottom';
continue;
}
if (side === 'bottom') {

(function myLoop (i) {
setTimeout(function () {
console.log(output[down][i]);
if (--i >= left) myLoop(i); //READ RIGHT TO LEFT FROM BOTTOM
}, 2000)
})(right);

down--;
side = 'left';
continue;
}
if (side === 'left') {

(function myLoop (i) {
setTimeout(function () {
console.log(output[i][left]);
if (--i >= top) myLoop(i); //READ BOTTOM TO TOP FROM LEFT
}, 2000)
})(down);

left++;
side = 'top';
continue;
}
}
}


I am expecting this output:

0
1 //after 2 seconds delay
2 //after 2 seconds delay
3 //etc.
7
6
5
4


But I am not getting this with the code above. The output is all over the place and doesn't even have the right number of elements. I am using recursion to add a delay in my loop after every iteration (through
setTimeout
), but I do not think I am setting the variables correctly. But when I look at the code, it makes sense to me. What am I missing here?

Answer

This is my approach to your problem. I didn't use recursivity though.

var matrix1 = [
    [1, 2, 3, 4],
    [5, 6, 7, 8],
    [9, 10, 11, 12],
    [13, 14, 15, 16]
], matrix2 = [
    [1, 2, 3],
    [4, 5, 6],
    [7, 8, 9],
    [10, 11, 12]
], matrix3 = [
    [0, 1, 2, 3],
    [4, 5, 6, 7]
], matrix4 = [
    [1, 2, 3],
    [4, 5, 6],
    [7, 8, 9]
];

(function (matrix) {
    var i,
        nRows = matrix.length,
        nCols = matrix[0].length,
        rowLimit = nRows - 1,
        colLimit = nCols - 1,
        rounds = 0,
        printedElements = 0,
        nElements = nRows * nCols,
        timeoutLapse = 2000;

    function print(val) {
        printedElements += 1;
        setTimeout(function () {
            console.log(val);
        }, printedElements * timeoutLapse);
    }

    do {
        for (i = rounds; i <= colLimit - rounds; i += 1) {// from left to right
            print(matrix[rounds][i]);
        }

        for (i = rounds + 1; i <= rowLimit - rounds; i += 1) {// from top to bottom
            print(matrix[i][colLimit - rounds]);
        }

        for (i = colLimit - rounds - 1; i >= rounds; i -= 1) {// from right to left
            print(matrix[rowLimit - rounds][i]);
        }

        for (i = rowLimit - rounds - 1; i >= rounds + 1; i -= 1) {// from bottom to top
            print(matrix[i][rounds]);
        }
        rounds += 1;
    } while (printedElements < nElements);

})(matrix4);

I added some examples in order to test it. I just print out elements of the matrix every two seconds following the spiral pattern. When all the elements have been printed out, the loop finishes.

Here's the fiddle (you'll have to open the console in order to see the results). Hope it helps.