Javascript 无overun的递归
我一直在寻找递归的真实例子。记住,编程向导,我是艺术家,在Photoshop脚本(scriptus操作方式)中,它通常用于在所有层和子层上循环 我正在编写一个(简单的)递归脚本来解决一个四位数的组合锁。你知道,从1开始,然后尝试2,然后3等等,直到找到解决方案。为了简化示例中的内容,第二个数字是正确的,因此我们知道不必更改它。初始状态也是从零开始的,但我们知道在最终解中没有零Javascript 无overun的递归,javascript,recursion,Javascript,Recursion,我一直在寻找递归的真实例子。记住,编程向导,我是艺术家,在Photoshop脚本(scriptus操作方式)中,它通常用于在所有层和子层上循环 我正在编写一个(简单的)递归脚本来解决一个四位数的组合锁。你知道,从1开始,然后尝试2,然后3等等,直到找到解决方案。为了简化示例中的内容,第二个数字是正确的,因此我们知道不必更改它。初始状态也是从零开始的,但我们知道在最终解中没有零 尝试必须与解决方案相匹配,并且加起来等于10,以便 解决问题 这看起来有点像stoppid,但我想把解决方案分为两部
- 尝试必须与解决方案相匹配,并且加起来等于10,以便 解决问题
var puzzle = [0,2,0,0]; // source
var solution = [1,2,3,4];
var s = superCopy(puzzle); // working array
drawPuzzle(s);
solvePuzzle(s, puzzle);
var total = checkTotal(s, solution);
var solution = checkSolution(s, solution);
function checkTotal(arr, source)
{
var c = 0;
// count the total
for (var i = 0; i < arr.length; i++)
{
c += arr[i];
}
if (c == 10)
{
alert("Total OK")
return true;
}
}
function checkSolution(arr, source)
{
// check the solution
for (var i in arr)
{
if (arr[i] != source[i]) return false
return true;
}
}
function solvePuzzle(arr, source)
{
for (var i = 0; i < arr.length; i++)
{
// check the source
var sourceCell = source[i];
//alert("checking source " + sourceCell)
//if it's a zero we can change it
if (arr[i] == 0)
{
cell = arr[i];
cell+=1;
if (cell > 4) cell = 0;
arr[i] = cell;
}
}
// check the solution
for (var i in arr)
{
// overflow time!
if (arr[i] != source[i]) solvePuzzle(arr, source)
else
{
alert("All done!")
}
}
}
function drawPuzzle(arr)
{
var p = "";
var c = 0;
for (var i = 0; i < arr.length; i++)
{
if (arr[i] == 0) p += "-"
else p += arr[i];
c+=1;
}
alert(p);
}
function superCopy(arr)
{
// returns a true copy of an array
tempArr = new Array();
for (var i = 0; i < arr.length; i++)
{
if (arr[i] == 0) tempArr[i] = 1 // changed, thanks Nostradamnit!
else tempArr[i] = arr[i]
}
return tempArr
}
var-puzzle=[0,2,0,0];//来源
var溶液=[1,2,3,4];
var s=超级副本(拼图);//工作阵列
抽签游戏;;
解谜;
var total=检查总计(s,溶液);
var溶液=检查溶液(s,溶液);
功能检查总计(arr,源)
{
var c=0;
//数一数总数
对于(变量i=0;i4)单元格=0;
arr[i]=单元;
}
}
//检查解决方案
用于(arr中的var i)
{
//溢出时间!
if(arr[i]!=source[i])解算拼图(arr,source)
其他的
{
警报(“全部完成!”)
}
}
}
函数(arr)
{
var p=“”;
var c=0;
对于(变量i=0;i
脚本不完整。这就是我到目前为止所知道的,它会出现溢出错误。注意:solvePuzzle和checkTotal函数没有被调用,因为我意识到solvePuzzle需要调用自己,并制定解决方案……这是当我遇到溢出问题并感到有点困惑时
我意识到这种类型的问题与“修复我的代码”的风险非常接近,所以我准备为此悬赏。谢谢。乍一看,您的超级副本功能似乎有缺陷。创建一个空数组,然后将其0索引(不存在)与输入数组进行比较。这就是“溢出”的原因吗?问题似乎是您在同一次迭代中多次调用
solvePuzzle(arr,source)
:
for (var i in arr)
{
// overflow time!
if (arr[i] != source[i]) solvePuzzle(arr, source)
else
{
alert("All done!")
}
}
因此,迭代数组中的每个项,如果它不等于源
项,则再次调用solvePuzzle
。但是,如果您有多个不匹配的项,solvePuzzle
将在同一数组中多次调用。对于每次呼叫,它都会被再次调用多次。因此,函数调用呈指数增长,最终导致堆栈溢出
您可能打算做的是:
var areArraysEqual = true;
for (var i in arr)
{
if (arr[i] != source[i]) {
areArraysEqual = false;
break;
}
}
if (areArraysEqual) {
alert("All done!");
} else {
solvePuzzle(arr, source);
}
我还没有看过你的解决方案,但我确实为自己编写了一个递归解决方案来解决这个问题。也许它可以作为一个指导方针
var solution = [1,2,3,4];
function checkSolution(arr) {
return solution.every(function(item, index){ return item === arr[index]; });
}
function increment(arr) {
for (var i=0; arr[i] === 9; i++) {
arr[i] = 0;
}
arr[i]++;
return arr;
}
function solvePuzzle(arr) {
if (isNaN(arr[arr.length-1])) {
return null;
}
if (checkSolution(arr)) {
return arr;
}
return solvePuzzle(increment(arr));
}
var solution = solvePuzzle([1,1,1,1]);
console.log(solution); // [1,2,3,4]
您的代码有几个问题。首先,checkSolution函数在匹配的第一个数字处停止。您可能希望它在返回true之前检查每个数字,因此您应该将
返回true
移到for循环之外。只有当所有的数字都匹配时,它才能到达那里
另一个缺陷是超焦函数,正如Nostrandamnit指出的那样,它有一个有缺陷的条件
您的下一个问题是solvePuzzle,这里有:
if (arr[i] == 0)
{
cell = arr[i];
cell+=1;
if (cell > 4) cell = 0;
arr[i] = cell;
}
问题是,因为arr[i]
是0,而您只添加1,所以单元格永远不会是4。所以你的if永远不会开火。这就是无限循环的位置:它只会以1递增0的值,所以在所有0变为1之后,它就再也不会前进了,并且您会不断检查“1111”是否是解决方案
现在溢出:您不应该为每个单元格调用solvePuzzle,这是指数增长的:
for (var i in arr)
{
// overflow time!
if (arr[i] != source[i]) solvePuzzle(arr, source)
else
{
alert("All done!")
}
}
而且,您永远不会再次检查结果,因此循环永远不会结束。您可能希望将此更改为:
if(checkTotal(arr) && checkSolution(arr, source))
{
alert("All done!");
return;
}
solvePuzzle(arr, source);
作为旁注(不是引起bug的原因):您的checkTotal函数没有使用源参数,因此您可能可以省略它。此外,solvePuzzle中还有一个叫做cell的流氓变量,在本例中这不是什么大问题,但最好将var放在它前面,这样它就不会变成全局变量。此外,还有一个从未使用过的sourceCell变量。可能有点离题,但我认为我创建了最简单的递归示例
哎呀!我错过了。我现在已经修复了超级副本。不,错误发生在solvePuzzle(s,puzzle)上,我认为您将进入一个无限循环,因为solvePuzzle中的第一个for不起任何作用。第一个for中的if检查arr[i]==0,但superCopy函数确保所有等于0的索引都更改为1,因此此条件永远不存在,然后继续在未更改的数组上递归,继续不将其更改为无穷大。重新审视一下你的逻辑;)
var str = "9785";
function rec(a, b)
{
var c=0;
if(b==-1)
return "";
if(a!=str.charAt(b))
return rec(a+1, b);
else
{
return rec(0,b-1)+""+a;
}
}
var ans = rec(0,str.length-1)