RosettaCodeData/Task/Zig-zag-matrix/JavaScript/zig-zag-matrix-3.js

61 lines
1.5 KiB
JavaScript

(n => {
// diagonals :: n -> [[n]]
function diagonals(n) {
let diags = (xs, iCol, iRow) => {
if (iCol < xs.length) {
let xxs = splitAt(iCol, xs);
return [xxs[0]].concat(diags(
xxs[1],
iCol + (iRow < n ? 1 : -1),
iRow + 1
));
} else return [xs];
}
return diags(range(0, n * n - 1), 1, 1);
}
// Recursively read off n heads of diagonal lists
// rowsFromDiagonals :: n -> [[n]] -> [[n]]
function rowsFromDiagonals(n, lst) {
if (lst.length) {
let [edge, rest] = splitAt(n, lst);
return [edge.map(x => x[0])]
.concat(rowsFromDiagonals(n,
edge.filter(x => x.length > 1)
.map(x => x.slice(1))
.concat(rest)
));
} else return [];
}
// GENERIC FUNCTIONS
// splitAt :: Int -> [a] -> ([a],[a])
function splitAt(n, xs) {
return [xs.slice(0, n), xs.slice(n)];
}
// range :: From -> To -> Maybe Step -> [Int]
// range :: Int -> Int -> Maybe Int -> [Int]
function range(m, n, step) {
let d = (step || 1) * (n >= m ? 1 : -1);
return Array.from({
length: Math.floor((n - m) / d) + 1
}, (_, i) => m + (i * d));
}
// ZIG-ZAG MATRIX
return rowsFromDiagonals(n,
diagonals(n)
.map((x, i) => (i % 2 || x.reverse()) && x)
);
})(5);