How to resolve the algorithm Spiral matrix step by step in the JavaScript programming language
How to resolve the algorithm Spiral matrix step by step in the JavaScript programming language
Table of Contents
Problem Statement
Produce a spiral array.
A spiral array is a square arrangement of the first N2 natural numbers, where the numbers increase sequentially as you go around the edges of the array spiraling inwards.
For example, given 5, produce this array:
Let's start with the solution:
Step by Step solution about How to resolve the algorithm Spiral matrix step by step in the JavaScript programming language
Spiral Array
First Approach
The first approach to creating a spiral array is a bit more complex. It uses a combination of loops and conditional statements to build the array.
spiralArray = function (edge) {
var arr = Array(edge),
x = 0, y = edge,
total = edge * edge--,
dx = 1, dy = 0,
i = 0, j = 0;
while (y) arr[--y] = [];
while (i < total) {
arr[y][x] = i++;
x += dx; y += dy;
if (++j == edge) {
if (dy < 0) {x++; y++; edge -= 2}
j = dx; dx = -dy; dy = j; j = 0;
}
}
return arr;
}
Implementation Details:
- The code initializes an array
arr
of sizeedge
, representing the spiral array. - It sets initial positions for
x
andy
and initializes variables for tracking the number of elements (total
), the direction changes (dx
anddy
), and the current index (i
andj
). - It iterates to initialize rows in the
arr
array. - The main loop runs until all elements are filled in the spiral.
- It assigns the current index
i
to the current position inarr
and incrementsi
. - It moves in the current direction and updates
x
andy
accordingly. - It checks if the current row has been completed (
j == edge
). If so, it adjusts the direction and movement based on the current position in the spiral. - It returns the completed
arr
array.
Second Approach
The second approach uses a recursive function to generate the spiral array. It rotates the spiral by 90 degrees clockwise with each recursive call.
(function (n) {
// Spiral: the first row plus a smaller spiral rotated 90 degrees clockwise
function spiral(lngRows, lngCols, nStart) {
return lngRows ? [range(nStart, (nStart + lngCols) - 1)].concat(
transpose(
spiral(lngCols, lngRows - 1, nStart + lngCols)
).map(reverse)
) : [
[]
];
}
// rows and columns transposed (for 90 degree rotation)
function transpose(lst) {
return lst.length > 1 ? lst[0].map(function (_, col) {
return lst.map(function (row) {
return row[col];
});
}) : lst;
}
// elements in reverse order (for 90 degree rotation)
function reverse(lst) {
return lst.length > 1 ? lst.reduceRight(function (acc, x) {
return acc.concat(x);
}, []) : lst;
}
// [m..n]
function range(m, n) {
return Array.apply(null, Array(n - m + 1)).map(function (x, i) {
return m + i;
});
}
})(5);
Implementation Details:
- The code defines a recursive function
spiral
that takes three parameters:lngRows
(length of rows),lngCols
(length of columns), andnStart
(starting index). - The
range
function creates a range of numbers[m, n]
. - The
transpose
function transposes rows and columns for 90-degree rotation. - The
reverse
function reverses the order of elements for 90-degree rotation. - The
spiral
function generates the first row and concatenates it with the transposed and reversed smaller spiral generated by the recursive call. - It recursively rotates the spiral by 90 degrees until the desired size is reached.
Third Approach
The third approach uses a different approach to generate the spiral array. It maintains two queues, one for the current row and one for the next row, and iteratively fills the array.
(() => {
"use strict";
// ------------------ SPIRAL MATRIX ------------------
// spiral :: Int -> [[Int]]
const spiral = n => {
const go = (rows, cols, start) =>
Boolean(rows) ? [
enumFromTo(start)(start + pred(cols)),
...transpose(
go(
cols,
pred(rows),
start + cols
)
).map(reverse)
] : [
[]
];
return go(n, n, 0);
};
// ---------------------- TEST -----------------------
// main :: () -> String
const main = () => {
const
n = 5,
cellWidth = 1 + `${pred(n ** 2)}`.length;
return unlines(
spiral(n).map(
row => (
row.map(x => `${x}`
.padStart(cellWidth, " "))
)
.join("")
)
);
};
// --------------------- GENERIC ---------------------
// enumFromTo :: Int -> Int -> [Int]
const enumFromTo = m =>
n => Array.from({
length: 1 + n - m
}, (_, i) => m + i);
// pred :: Enum a => a -> a
const pred = x => x - 1;
// reverse :: [a] -> [a]
const reverse = xs =>
"string" === typeof xs ? (
xs.split("").reverse()
.join("")
) : xs.slice(0).reverse();
// transpose :: [[a]] -> [[a]]
const transpose = rows =>
// The columns of the input transposed
// into new rows.
// Simpler version of transpose, assuming input
// rows of even length.
Boolean(rows.length) ? rows[0].map(
(_, i) => rows.flatMap(
v => v[i]
)
) : [];
// unlines :: [String] -> String
const unlines = xs =>
// A single string formed by the intercalation
// of a list of strings with the newline character.
xs.join("\n");
// MAIN ---
return main();
})();
Implementation Details:
- The code defines a recursive function
spiral
that takes three parameters:rows
,cols
, andstart
. - The
enumFromTo
function creates a range of numbers[m, n]
. - The
pred
function subtracts 1 from a given number. - The
reverse
function reverses the order of elements. - The
transpose
function transposes rows and columns. - The
unlines
function joins a list of strings into a single string with newline characters. - The
main
function generates the spiral array and formats it for output.
Source code in the javascript programming language
spiralArray = function (edge) {
var arr = Array(edge),
x = 0, y = edge,
total = edge * edge--,
dx = 1, dy = 0,
i = 0, j = 0;
while (y) arr[--y] = [];
while (i < total) {
arr[y][x] = i++;
x += dx; y += dy;
if (++j == edge) {
if (dy < 0) {x++; y++; edge -= 2}
j = dx; dx = -dy; dy = j; j = 0;
}
}
return arr;
}
// T E S T:
arr = spiralArray(edge = 5);
for (y= 0; y < edge; y++) console.log(arr[y].join(" "));
(function (n) {
// Spiral: the first row plus a smaller spiral rotated 90 degrees clockwise
function spiral(lngRows, lngCols, nStart) {
return lngRows ? [range(nStart, (nStart + lngCols) - 1)].concat(
transpose(
spiral(lngCols, lngRows - 1, nStart + lngCols)
).map(reverse)
) : [
[]
];
}
// rows and columns transposed (for 90 degree rotation)
function transpose(lst) {
return lst.length > 1 ? lst[0].map(function (_, col) {
return lst.map(function (row) {
return row[col];
});
}) : lst;
}
// elements in reverse order (for 90 degree rotation)
function reverse(lst) {
return lst.length > 1 ? lst.reduceRight(function (acc, x) {
return acc.concat(x);
}, []) : lst;
}
// [m..n]
function range(m, n) {
return Array.apply(null, Array(n - m + 1)).map(function (x, i) {
return m + i;
});
}
// TESTING
var lstSpiral = spiral(n, n, 0);
// OUTPUT FORMATTING - JSON and wikiTable
function wikiTable(lstRows, blnHeaderRow, strStyle) {
return '{| class="wikitable" ' + (
strStyle ? 'style="' + strStyle + '"' : ''
) + lstRows.map(function (lstRow, iRow) {
var strDelim = ((blnHeaderRow && !iRow) ? '!' : '|');
return '\n|-\n' + strDelim + ' ' + lstRow.map(function (v) {
return typeof v === 'undefined' ? ' ' : v;
}).join(' ' + strDelim + strDelim + ' ');
}).join('') + '\n|}';
}
return [
wikiTable(
lstSpiral,
false,
'text-align:center;width:12em;height:12em;table-layout:fixed;'
),
JSON.stringify(lstSpiral)
].join('\n\n');
})(5);
[[0,1,2,3,4],[15,16,17,18,5],[14,23,24,19,6],[13,22,21,20,7],[12,11,10,9,8]]
(() => {
"use strict";
// ------------------ SPIRAL MATRIX ------------------
// spiral :: Int -> [[Int]]
const spiral = n => {
const go = (rows, cols, start) =>
Boolean(rows) ? [
enumFromTo(start)(start + pred(cols)),
...transpose(
go(
cols,
pred(rows),
start + cols
)
).map(reverse)
] : [
[]
];
return go(n, n, 0);
};
// ---------------------- TEST -----------------------
// main :: () -> String
const main = () => {
const
n = 5,
cellWidth = 1 + `${pred(n ** 2)}`.length;
return unlines(
spiral(n).map(
row => (
row.map(x => `${x}`
.padStart(cellWidth, " "))
)
.join("")
)
);
};
// --------------------- GENERIC ---------------------
// enumFromTo :: Int -> Int -> [Int]
const enumFromTo = m =>
n => Array.from({
length: 1 + n - m
}, (_, i) => m + i);
// pred :: Enum a => a -> a
const pred = x => x - 1;
// reverse :: [a] -> [a]
const reverse = xs =>
"string" === typeof xs ? (
xs.split("").reverse()
.join("")
) : xs.slice(0).reverse();
// transpose :: [[a]] -> [[a]]
const transpose = rows =>
// The columns of the input transposed
// into new rows.
// Simpler version of transpose, assuming input
// rows of even length.
Boolean(rows.length) ? rows[0].map(
(_, i) => rows.flatMap(
v => v[i]
)
) : [];
// unlines :: [String] -> String
const unlines = xs =>
// A single string formed by the intercalation
// of a list of strings with the newline character.
xs.join("\n");
// MAIN ---
return main();
})();
You may also check:How to resolve the algorithm Polynomial long division step by step in the D programming language
You may also check:How to resolve the algorithm Array length step by step in the Avail programming language
You may also check:How to resolve the algorithm Convert seconds to compound duration step by step in the Phix programming language
You may also check:How to resolve the algorithm Find the intersection of a line with a plane step by step in the Racket programming language
You may also check:How to resolve the algorithm Strip comments from a string step by step in the Factor programming language