I would pre-process the array by turning each submachine so that the numbers forming the diagonal line are under each other. First, define functions for rotating a single array with n
elements in any direction:
const rotateLeft = (array, n) => array.slice(n).concat(array.slice(0, n)); const rotateRight = (array, n) => rotateLeft(array, -n);
and functions for turning each submachine to increasing amounts in any direction:
const rotateAllLeft = array => array.map(rotateLeft); const rotateAllRight = array => array.map(rotateRight);
Now your array will look like this: those lined up vertically:
var array = [ [1, 0, 0, 0, 0, 0, 0], [1, 0, 0, 0, 1, 0, 0], [1, 0, 1, 0, 0, 0, 0], [1, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 1, 0], [0, 0, 0, 0, 0, 0, 0] ]
Now the problem boils down to finding vertical lines of units. The easiest way to do this is to transfer an array, which you can do with:
const transpose = array => array[0].map((_, i) => array.map(row => row[i]));
Now we will write a small function that takes one array and returns another array whose values represent the length of the “runs” of a certain value:
const run = (array, val, cnt = 0) => array.map(elt => cnt = elt === val ? ++cnt : 0;
For [1, 1, 1, 1, 0, 0]
this will return [1, 2, 3, 4, 0, 0]
. 4
indicates the mileage of four values of 1
to this point.
Write small functions to check if a certain value of a certain minimum length is executed in one array or a certain value of a certain minimum length runs in any subarray:
const hasRunOf = (array, val, n) => run(array, val).some(len => len >= n); const hasAnyRunOf = (array, val, n) => array.some(subarray => hasRunOf(subarray, val, n));
Now you can check for any run of four or more with
hasAnyRunOf(transpose(rotateAllLeft(array)), 1, 4) || hasAnyRunOf(transpose(rotateAllRight(array)), 1, 4)
Capturing information about exactly where the diagonal run took place remains in the form of an exercise.