给出一个示例输入:
[
{"id":1,"currentBlack":1,"currentWhite":0,"max":1},
{"id":2,"currentBlack":0,"currentWhite":1,"max":1},
]
输出输入的所有可能状态,其中currentBlack和currentWhite可以具有从初始值到最大值范围内的任何值。
此示例的正确输出:
[
[
{"id":1,"currentBlack":1,"currentWhite":0,"max":1},
{"id":2,"currentBlack":0,"currentWhite":1,"max":1},
],
[
{"id":1,"currentBlack":1,"currentWhite":1,"max":1},
{"id":2,"currentBlack":0,"currentWhite":1,"max":1},
],
[
{"id":1,"currentBlack":1,"currentWhite":1,"max":1},
{"id":2,"currentBlack":1,"currentWhite":1,"max":1},
],
[
{"id":1,"currentBlack":1,"currentWhite":0,"max":1},
{"id":2,"currentBlack":1,"currentWhite":1,"max":1},
]
]
实际输入的最大值在1到8之间,输入数组中的对象数量会更多。我的尝试低于(评论很多):
function allPossibleCounts(pieceCounts) {//pieceCounts is the input
var collection = []; //used to collect all possible values
recursiveCalls(pieceCounts); //runs recursive function
return collection; //returns result
function recursiveCalls(pieceCounts) {
//if pieceCounts is already in collection then return, not yet implemented so duplicates are currently possible
collection.push(pieceCounts);//inputs a potential value
console.log(JSON.stringify(pieceCounts));//this is successfully logs the correct values
console.log(JSON.stringify(collection));//collection isn't correct, all values at the top of the array are copies of each other
for (let n in pieceCounts) {//pieceCounts should be the same at the start of each loop within each scope, aka pieceCounts should be the same at the end of this loop as it is at the start
subBlackCall(pieceCounts);
function subBlackCall(pieceCounts) {
if (pieceCounts[n].currentBlack < pieceCounts[n].max) {
pieceCounts[n].currentBlack++;//increment
recursiveCalls(pieceCounts);
subBlackCall(pieceCounts);//essentially you're either adding +1 or +2 or +3 ect all the way up to max and calling recursiveCalls() off of each of those incremented values
pieceCounts[n].currentBlack--;//decrement to return pieceCounts to how it was at the start of this function
}
}
subWhiteCall(pieceCounts);
function subWhiteCall(pieceCounts) {
if (pieceCounts[n].currentWhite < pieceCounts[n].max) {
pieceCounts[n].currentWhite++;
recursiveCalls(pieceCounts);
subWhiteCall(pieceCounts);
pieceCounts[n].currentWhite--;
}
}
}
}
}
但是目前我的尝试输出了这个不敬虔的复制数组
[[{"id":1,"currentBlack":1,"currentWhite":1,"max":1},{"id":2,"currentBlack":1,"currentWhite":1,"max":1}],[{"id":1,"currentBlack":1,"currentWhite":1,"max":1},{"id":2,"currentBlack":1,"currentWhite":1,"max":1}],[{"id":1,"currentBlack":1,"currentWhite":1,"max":1},{"id":2,"currentBlack":1,"currentWhite":1,"max":1}],[{"id":1,"currentBlack":1,"currentWhite":1,"max":1},{"id":2,"currentBlack":1,"currentWhite":1,"max":1}],[{"id":1,"currentBlack":1,"currentWhite":1,"max":1},{"id":2,"currentBlack":1,"currentWhite":1,"max":1}]]
修改:工作代码:https://pastebin.com/qqFTppsY
答案 0 :(得分:1)
pieceCounts[n]
始终引用一个对象。您应该重新创建pieceCount
以保存到集合中作为不同的对象。例如,您可以添加
pieceCounts = JSON.parse(JSON.stringify(pieceCounts)); // just clone
在recursiveCalls
函数的开头。
答案 1 :(得分:1)
为了避免转换为JSON并返回,我建议使用Object.assign
与数组上的map
一起执行更深层次的副本:
function allPossibleCounts(pieceCounts) {
var result = [],
current = deeperCopy(pieceCounts);
function deeperCopy(arr) {
return arr.map( row => Object.assign({}, row) );
}
function recurse(depth) {
// depth: indication of which value will be incremented. Each "row" has
// 2 items (black/white), so when depth is even, it refers to black, when
// odd to white. Divide by two for getting the "row" in which the increment
// should happen.
var idx = depth >> 1, // divide by 2 for getting row index
prop = depth % 2 ? 'currentWhite' : 'currentBlack', // odd/even
row = pieceCounts[idx];
if (!row) { // at the end of the array
// Take a copy of this variation and add it to the results
result.push(deeperCopy(current));
return; // backtrack for other variations
}
for (var value = row[prop]; value <= row.max; value++) {
// Set the value of this property
current[idx][prop] = value;
// Collect all variations that can be made by varying any of
// the property values that follow after this one
recurse(depth+1);
// Repeat for all higher values this property can get.
}
}
recurse(0); // Start the process
return result;
}
// Sample input
var pieceCounts = [
{"id":1,"currentBlack":1,"currentWhite":0,"max":1},
{"id":2,"currentBlack":0,"currentWhite":1,"max":1},
];
// Get results
var result = allPossibleCounts(pieceCounts);
// Output
console.log(result);
&#13;
.as-console-wrapper { max-height: 100% !important; top: 0; }
&#13;
我们的想法是使用递归:想象一下,除了第一个属性之外,所有属性的变化都可以解决问题。生成这些,然后将第一个属性值更改为下一个可能的值。再次重复所有变化的产生等。所有这些结果的组合将是第一个属性值也应该变化的解决方案。
这是递归的理想情况。当没有剩余属性值时,递归停止:在这种情况下,只有一个解决方案;将所有值设置为原样的那个。它可以添加到结果列表中。
可以像下面这样枚举属性:
row currentBlack currentWhite
---------------------------------
0 0 1
1 2 3
2 4 5
3 6 7
...
n 2n-2 2n-1
我们可以将该数字称为 depth ,并在更深层递归的每一步增加它。给定深度,变化的属性定义为:
depth is even => currentBlack
depth is odd => currentWhite
row number = depth / 2 (ignoring the remainder)