var spiralOrder = function(matrix, order = []) {
const [ rows, cols ] = [ (matrix.length - 1), (matrix[0].length - 1) ];
let [ top, bot, left, right ] = [ 0, rows, 0, cols ];
const isInBounds = () => ((left <= right) && (top <= bot));
while (isInBounds()) {
addTop(
matrix, top, bot, left, right, order
);
top++;
addRight(
matrix, top, bot, left, right, order
);
right--;
const hasRow = (top <= bot);
if (hasRow) {
addBot(
matrix, top, bot, left, right, order
);
bot--;
}
const hasCol = (left <= right);
if (hasCol) {
addLeft(
matrix, top, bot, left, right, order
);
left++;
}
}
return order;
};
var addTop = (matrix, top, bot, left, right, order) => {
for (let col = left; col <= right; col++) {
order.push(matrix[top][col]);
}
}
var addRight = (matrix, top, bot, left, right, order) => {
for (let row = top; row <= bot; row++) {
order.push(matrix[row][right]);
}
}
var addBot = (matrix, top, bot, left, right, order) => {
for (let col = right; left <= col; col--) {
order.push(matrix[bot][col]);
}
}
var addLeft = (matrix, top, bot, left, right, order) => {
for (let row = bot; top <= row; row--) {
order.push(matrix[row][left]);
}
}
var spiralOrder = (matrix, order = []) => {
const [ rows, cols ] = [ matrix.length, matrix[0].length ];
const cells = (rows * cols);
let [ top, bot, left, right ] = [ 0, (rows - 1), 0, (cols - 1) ];
while (order.length < cells) {
traverse(
matrix, top, bot, left, right, order
);
top++; bot--;
left++; right--;
}
return order;
}
var traverse = (matrix, top, bot, left, right, order) => {
addTop(matrix, top, bot, left, right, order);
addRight(matrix, top, bot, left, right, order);
addBot(matrix, top, bot, left, right, order);
addLeft(matrix, top, bot, left, right, order);
}
var addTop = (matrix, top, bot, left, right, order) => {
for (let col = left; (col <= right); col++) {
order.push(matrix[top][col]);
}
}
var addRight = (matrix, top, bot, left, right, order) => {
for (let row = (top + 1); (row <= bot); row++) {
order.push(matrix[row][right]);
}
}
var addBot = (matrix, top, bot, left, right, order) => {
for (let col = (right - 1); (left <= col); col--) {
const isOutOfBounds = top === bot;
if (isOutOfBounds) return;
order.push(matrix[bot][col]);
}
}
var addLeft = (matrix, top, bot, left, right, order) => {
for (let row = bot - 1; row >= top + 1; row--) {
const isOutOfBounds = left === right;
if (isOutOfBounds) return;
order.push(matrix[row][left]);
}
}
var spiralOrder = (matrix) => {
const order = initOrder(matrix);
spiral(matrix, order);
return order;
}
const initOrder = (matrix, VISITED = 101) => {
const order = [ matrix[0][0] ];
matrix[0][0] = VISITED;
return order;
}
var spiral = (matrix, order) => {
let [ row, col, direction, changeDirection ] = [ 0, 0, 0, 0 ];
while (changeDirection < 2) {
[ row, col, direction, changeDirection ] =
getPointers(matrix, row, col, direction, changeDirection, order);
}
}
const getPointers = (matrix, row, col, direction, changeDirection, order) => {
[ row, col, direction, changeDirection ] =
move(matrix, row, col, direction, changeDirection, order);
direction = ((direction + 1) % 4);
changeDirection += 1;
return [ row, col, direction, changeDirection ];
}
const move = (matrix, row, col, direction, changeDirection, order, VISITED = 101) => {
const [ rows, cols ] = [ matrix.length, matrix[0].length ];
while (canMove(matrix, row, rows, col, cols, direction)) {
[ row, col ] = getCell(row, col, direction);
order.push(matrix[row][col]);
matrix[row][col] = VISITED;
changeDirection = 0;
}
return [ row, col, direction, changeDirection ];
}
const canMove = (matrix, row, rows, col, cols, direction) => {
if (!isInBounds(row, rows, col, cols, direction)) return false;
return !hasSeen(matrix, row, col, direction)
}
const isInBounds = (row, rows, col, cols, direction) => {
const [ _row, _col ] = getCell(row, col, direction);
const isRowInBounds = ((0 <= _row) && (_row < rows));
const isColInBounds = ((0 <= _col) && (_col < cols));
return (isRowInBounds && isColInBounds);
}
const hasSeen = (matrix, row, col, direction, VISITED = 101) => {
const [ _row, _col ] = getCell(row, col, direction);
return (matrix[_row][_col] === VISITED);
}
const getDirection = (direction) => {
const directions = [ [0, 1], [1, 0], [0, -1], [-1, 0] ];
return directions[direction];
}
const getCell = (row, col, direction) => {
const [ _row, _col ] = getDirection(direction);
return [ (row + _row), (col + _col) ];
}