我有一个数组,让我们说
var array = [ [1, 0, 0, 0, 0, 0, 0],
[0, 1, 0, 0, 0, 1, 0],
[0, 0, 1, 0, 1, 0, 0],
[0, 0, 0, 1, 0, 0, 0],
[0, 0, 1, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0]
]
我想创建一个找到任何匹配的数字,其中一个数字在对角线上出现四次。
目前我正在使用
function checkDiagonal(array, bottomToTop) {
var Ylength = array.length;
var Xlength = array[0].length;
var maxLength = Math.max(Xlength, Ylength);
var temp;
var returnArray = [];
for (var k = 0; k <= 2 * (maxLength - 1); ++k) {
temp = [];
for (var y = Ylength - 1; y >= 0; --y) {
var x = k - (bottomToTop ? Ylength - y : y);
if (x >= 0 && x < Xlength) {
temp.push(array[y][x]);
}
}
if(temp.length > 0) {
returnArray.push(temp.join(''));
}
}
return returnArray;
}
然而,并不总能找到所有解决方案
答案 0 :(得分:2)
有趣的案例。实际上很难找到/写一个简单的方法。 我试图了解你的脚本,但发现它有点难以跟踪/调试,所以试图重现你在我自己的脚本中所做的并设法获得所需的结果。它比你的代码行更多,但它有一些变量与一些注释一起声明,所以它更容易理解(对于其他人,将来)。
希望这会有所帮助:
function checkDiagonal(array, matchCount) {
var result = [];
if(array.length >= matchCount) {
// Search towards bottom-right.
result = result.concat(getDiagonalResult(array, matchCount, 1));
// Search towards top-right.
result = result.concat(getDiagonalResult(array, matchCount, -1));
} else {
// No use searching if not enough rows are present.
}
return result;
}
function getDiagonalResult(array, matchCount, direction) {
var result = [];
// Specific from and to points to only search in possible rows (e.g. no use searching top-right on first row).
var yFrom, yTo;
// Search direction (bottom-right vs top-right).
switch(direction) {
// Bottom-right.
case 1:
yFrom = 0;
yTo = (array.length - matchCount);
break;
// Top-right.
case -1:
yFrom = (matchCount - 1);
yTo = (array.length - 1);
break;
}
// Loop through all 'rows'.
for(var y = yFrom; y <= yTo; y++) {
// Loop through all 'columns'.
for(var x = 0; x <= (array[y].length - matchCount); x++) {
// Current value to match on.
var originalValue = array[y][x];
var matches = [];
// Get matches.
for(var i = 0; i < matchCount; i++) {
// Search direction (row up or down).
var yDirection = (i * direction);
var value = array[y+yDirection][x+i];
if(value === originalValue) {
matches.push(value);
}
}
if(matches.length == matchCount) {
result.push(matches.join(""));
}
}
}
return result;
}
var array = [
[1, 0, 0, 0, 0, 0, 0],
[0, 1, 0, 0, 0, 1, 0],
[0, 0, 1, 0, 1, 0, 0],
[0, 0, 0, 1, 0, 0, 0],
[0, 0, 1, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0]
];
console.log(checkDiagonal(array, 4));
答案 1 :(得分:0)
我会通过旋转每个子阵列来预处理数组,以便形成对角线的数字相互排列。首先定义函数以在任一方向上通过n
元素旋转单个数组:
const rotateLeft = (array, n) => array.slice(n).concat(array.slice(0, n));
const rotateRight = (array, n) => rotateLeft(array, -n);
并且可以通过在任一方向上不断增加的数量来旋转每个子阵列:
const rotateAllLeft = array => array.map(rotateLeft);
const rotateAllRight = array => array.map(rotateRight);
你的阵列现在看起来像这样,垂直排列的那些:
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]
]
问题现在减少到寻找垂直线。要做到这一点,首先转置数组是最容易的,你可以这样做:
const transpose = array => array[0].map((_, i) => array.map(row => row[i]));
我们现在将编写一个小函数,它接受一个数组并返回另一个数组,其值为&#34;运行&#34;具有特定价值:
const run = (array, val, cnt = 0) => array.map(elt => cnt = elt === val ? ++cnt : 0;
对于[1, 1, 1, 1, 0, 0]
,这将返回[1, 2, 3, 4, 0, 0]
。 4
表示到此为止的四个1
值。
编写小函数来测试单个数组中某个最小长度的特定值的运行,或者在任何子数组中运行某个最小长度的特定值:
const hasRunOf = (array, val, n) => run(array, val).some(len => len >= n);
const hasAnyRunOf = (array, val, n) => array.some(subarray => hasRunOf(subarray, val, n));
现在,您可以使用
测试是否存在任何四个或更多个游戏hasAnyRunOf(transpose(rotateAllLeft(array)), 1, 4) ||
hasAnyRunOf(transpose(rotateAllRight(array)), 1, 4)
捕获关于对角线运行的确切位置的信息留作练习。
答案 2 :(得分:0)
这是最好的,因为它来自我。它仅在n
大小的组中计算每个元素一次。换句话说,组中存在的元素不能存在于另一个元素中。
这是一个游戏,使用最佳数量的x
和y
起始索引,然后计算从对角线向前和向后居住的起点开始的每个元素的索引。显然,我们应该在正确的x
和y
索引处开始和停止,我们可以在对角线上找到n
个元素。这将减少n
增长后要完成的工作量。因此,每组12个元素的100x100阵列的计算速度要快于每组4个元素的数组。
function getDiagonals(a,rep){
var xLen = a[0].length, // x dimension
yLen = a.length, // y dimension
xMin = rep-1, // minimum x value to start testing from
xMax = xLen-rep, // maximum x value to test up until
yMin = rep-1, // minimum y value to start testing from
yMax = yLen-rep, // maximum y value to test up until
minDim = Math.min(yLen,xLen), // the smallest dimensison
quadros = [], // the resutls array
temp1 = [], // utility array #1
temp2 = [], // utility array #2
item1, // current element on the slash test
item2; // current element on the backslash test
for (var x = xMin; x < xLen; x++){
for(var y = 0; y <= x && y < minDim; y++){
item1 = a[y][x-y]; // slash test on x axis
item2 = a[yLen-1-y][x-y]; // backslash test on x axis
temp1[0] === item1 ? temp1.length < rep-1 ? temp1.push(item1)
: (temp1.push(item1), quadros.push(temp1), temp1 = [])
: temp1 = [item1];
temp2[0] === item2 ? temp2.length < rep-1 ? temp2.push(item2)
: (temp2.push(item2), quadros.push(temp2), temp2 = [])
: temp2 = [item2];
}
temp1 = [];
temp2 = [];
}
for (var y = 1; y <= yMax; y++){
for(var x = xLen-1; x >= xLen - minDim + y; x--){
item1 = a[y-x+xLen-1][x]; // slash test on y axis
item2 = a[yLen-y-xLen+x][x];// backslash test on y axis
temp1[0] === item1 ? temp1.length < rep-1 ? temp1.push(item1)
: (temp1.push(item1), quadros.push(temp1), temp1 = [])
: temp1 = [item1];
temp2[0] === item2 ? temp2.length < rep-1 ? temp2.push(item2)
: (temp2.push(item2), quadros.push(temp2), temp2 = [])
: temp2 = [item2];
}
temp1 = [];
temp2 = [];
}
return quadros;
}
var arr = [ [1, 0, 0, 0, 0, 0, 0],
[0, 1, 0, 0, 0, 1, 0],
[0, 0, 1, 0, 1, 0, 0],
[0, 0, 0, 1, 0, 0, 0],
[0, 0, 1, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0]
],
brr = Array(100).fill().map(_ => Array(100).fill().map(e => ~~(Math.random()*2))),
result = getDiagonals(arr,4);
console.log(JSON.stringify(result),result.length);
result = getDiagonals(brr,12);
console.log(JSON.stringify(result),result.length);