此递归函数如何更改“历史”变量?

格兰特

我感觉非常接近解决这个问题,但是我不太了解这个功能。

我了解了函数如何继续检查目标数字,如果目标数字过高,它将返回null并返回第二个“ ||” 应用运算符。

我不明白的是,一旦当前变量高于目标变量,它将开始返回历史记录变量,但没有额外的(+5)。这是怎么从字符串中取出的?

任何解释将不胜感激。希望这是有道理的。我是从Marijn Haverbeke的《 Eloquent Javascript》一书中摘录的


function findSolution(target) {
  function find(current, history) {
    if (current == target) {
      return history;
    } else if (current > target) {
      //console.log(`CURRENT AT NULL: ` + current);
      console.log(`HISTORY AT NULL:  ${history}`);
      return null;

    } else {
      console.log(`${history}`);
      return find(current + 5, `(${history} + 5)`) ||
        find(current * 3, `(${history} * 3)`);
    }
  }
  return find(1, "1");
}
console.log(findSolution(24));

// → (((1 * 3) + 5) * 3)
威克

您正在通过递归进行所谓的深度优先搜索每个人都在递归上有所不同。最终,某些东西会让您点击。

我想在您的代码中添加几个注释,以帮助其打印出更自然的文字记录。希望这会有所帮助。

但是我认为最重要的是可视化缩进中递归的深度。在递归深度优先搜索期间记录日志时,基本上就是在制作二叉树,其输出类似于:

Root
   Root > Left
   Root > Right

它开始像这样递归嵌套:

Root
   Root > Left
      Root > Left > Left
      Root > Left > Right
   Root > Right
      Root > Right > Left
      Root > Right > Right

您将创建探索的“ +5”和“ * 3”分支,而不是“左”和“右”路径。在递归中,您首先探索树的+5分支以寻找解决方案。如果找不到,则探索树的* 3分支。当什么都没找到时,仅表示答案不在您正在考虑的分支上,必须在树的前面进行其他选择。

当尝试两种方法都无法成功时,似乎会发生一些回溯。但是,实际上,这只是一个假设的结论,我们说“如果+5,我们能到达那里吗?” 或“如果我们* 3,我们可以到达那里吗?” 如果对两者的回答都是“否”,那么您将无法从自己所在的位置到达那里。您不必实际回溯,递归的好处在于您可以在搜索中找到所需的位置,因为有人将您作为“如果...的假设”的一部分来调用您。如果您的整个搜索都为空,则没有问题。您只是放弃了当前的搜索分支,而调用的“某人”将在其他分支上尝试其他操作。

递归的状态(您正在探索的分支)保留在调用堆栈中那就是我们实际上“备份”的地方。

history永远不会被修改。我们只是探索history通过递归构造的不同版本每个history都是其自己的副本,并且只会变长(在搜索树中的左或右分支)或被放弃,并且搜索将从history递归中的其他位置继续进行

因此,这是您的代码,其中包含缩进和每个步骤所进行操作的一些简短描述,希望可以更紧密地联系到递归。

function spaces(indent) {
  return '    '.repeat(indent);
}

function findSolution(target) {
  function nope(indent, history) {
    console.log(spaces(indent) + `Sadly we've exhausted all possible ways of getting there from this starting point.  We may still be able to get to ${target}, but not by starting from ${history}.`);
    return false;
  }
  function badnews(history) {
    console.log(`I've tried everything and there's just no way of getting to ${target}.  :(`);
    return false;
  }
  function find(current, which, history, indent) {
    if (current == target) {
      console.log(spaces(indent) + `${which}, and guess what...we finally found a solution! Because ${history} = ${current}.  So we can stop now. :)`);
      return history;
    } else if (current > target) {
      //console.log(`CURRENT AT NULL: ` + current);
      console.log(spaces(indent) + `${which}, we reached a dead end because ${history} = ${current} which is unfortunately already bigger than ${target}.`);
      return null;

    } else {
      console.log(spaces(indent) + `${which}, ${history} looks promising because it equals ${current}, which is still less than ${target}.  We'll try two ways of getting to ${target} from here.`);
      return find(current + 5, 'First, by adding 5', `(${history} + 5)`, indent+1) ||
        find(current * 3, 'Second, by multiplying by 3', `(${history} * 3)`, indent+1) ||
        nope(indent+1, history);
    }
  }
  return find(1, 'Initially', "1", 0) || badnews();
}
console.log(`${findSolution(24)}`);

输出以防万一,复制到下面。抱歉,没有压缩输出,因为缩进更为重要,因此您可以看到递归中有多少级,是什么导致回溯。如果您发现代码段控制台输出更具可读性,则可以运行该代码段。

Initially, 1 looks promising because it equals 1, which is still less than 24.  We'll try two ways of getting to 24 from here.
    First, by adding 5, (1 + 5) looks promising because it equals 6, which is still less than 24.  We'll try two ways of getting to 24 from here.
        First, by adding 5, ((1 + 5) + 5) looks promising because it equals 11, which is still less than 24.  We'll try two ways of getting to 24 from here.
            First, by adding 5, (((1 + 5) + 5) + 5) looks promising because it equals 16, which is still less than 24.  We'll try two ways of getting to 24 from here.
                First, by adding 5, ((((1 + 5) + 5) + 5) + 5) looks promising because it equals 21, which is still less than 24.  We'll try two ways of getting to 24 from here.
                    First, by adding 5, we reached a dead end because (((((1 + 5) + 5) + 5) + 5) + 5) = 26 which is unfortunately already bigger than 24.
                    Second, by multiplying by 3, we reached a dead end because (((((1 + 5) + 5) + 5) + 5) * 3) = 63 which is unfortunately already bigger than 24.
                    Sadly we've exhausted all possible ways of getting there from this starting point.  We may still be able to get to 24, but not by starting from ((((1 + 5) + 5) + 5) + 5).
                Second, by multiplying by 3, we reached a dead end because ((((1 + 5) + 5) + 5) * 3) = 48 which is unfortunately already bigger than 24.
                Sadly we've exhausted all possible ways of getting there from this starting point.  We may still be able to get to 24, but not by starting from (((1 + 5) + 5) + 5).
            Second, by multiplying by 3, we reached a dead end because (((1 + 5) + 5) * 3) = 33 which is unfortunately already bigger than 24.
            Sadly we've exhausted all possible ways of getting there from this starting point.  We may still be able to get to 24, but not by starting from ((1 + 5) + 5).
        Second, by multiplying by 3, ((1 + 5) * 3) looks promising because it equals 18, which is still less than 24.  We'll try two ways of getting to 24 from here.
            First, by adding 5, (((1 + 5) * 3) + 5) looks promising because it equals 23, which is still less than 24.  We'll try two ways of getting to 24 from here.
                First, by adding 5, we reached a dead end because ((((1 + 5) * 3) + 5) + 5) = 28 which is unfortunately already bigger than 24.
                Second, by multiplying by 3, we reached a dead end because ((((1 + 5) * 3) + 5) * 3) = 69 which is unfortunately already bigger than 24.
                Sadly we've exhausted all possible ways of getting there from this starting point.  We may still be able to get to 24, but not by starting from (((1 + 5) * 3) + 5).
            Second, by multiplying by 3, we reached a dead end because (((1 + 5) * 3) * 3) = 54 which is unfortunately already bigger than 24.
            Sadly we've exhausted all possible ways of getting there from this starting point.  We may still be able to get to 24, but not by starting from ((1 + 5) * 3).
        Sadly we've exhausted all possible ways of getting there from this starting point.  We may still be able to get to 24, but not by starting from (1 + 5).
    Second, by multiplying by 3, (1 * 3) looks promising because it equals 3, which is still less than 24.  We'll try two ways of getting to 24 from here.
        First, by adding 5, ((1 * 3) + 5) looks promising because it equals 8, which is still less than 24.  We'll try two ways of getting to 24 from here.
            First, by adding 5, (((1 * 3) + 5) + 5) looks promising because it equals 13, which is still less than 24.  We'll try two ways of getting to 24 from here.
                First, by adding 5, ((((1 * 3) + 5) + 5) + 5) looks promising because it equals 18, which is still less than 24.  We'll try two ways of getting to 24 from here.
                    First, by adding 5, (((((1 * 3) + 5) + 5) + 5) + 5) looks promising because it equals 23, which is still less than 24.  We'll try two ways of getting to 24 from here.
                        First, by adding 5, we reached a dead end because ((((((1 * 3) + 5) + 5) + 5) + 5) + 5) = 28 which is unfortunately already bigger than 24.
                        Second, by multiplying by 3, we reached a dead end because ((((((1 * 3) + 5) + 5) + 5) + 5) * 3) = 69 which is unfortunately already bigger than 24.
                        Sadly we've exhausted all possible ways of getting there from this starting point.  We may still be able to get to 24, but not by starting from (((((1 * 3) + 5) + 5) + 5) + 5).
                    Second, by multiplying by 3, we reached a dead end because (((((1 * 3) + 5) + 5) + 5) * 3) = 54 which is unfortunately already bigger than 24.
                    Sadly we've exhausted all possible ways of getting there from this starting point.  We may still be able to get to 24, but not by starting from ((((1 * 3) + 5) + 5) + 5).
                Second, by multiplying by 3, we reached a dead end because ((((1 * 3) + 5) + 5) * 3) = 39 which is unfortunately already bigger than 24.
                Sadly we've exhausted all possible ways of getting there from this starting point.  We may still be able to get to 24, but not by starting from (((1 * 3) + 5) + 5).
            Second, by multiplying by 3, and guess what...we finally found a solution! Because (((1 * 3) + 5) * 3) = 24.  So we can stop now. :)
(((1 * 3) + 5) * 3)

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

如何使此阶乘函数递归?

来自分类Dev

如何停止此递归函数?

来自分类Dev

如何编写此递归Haskell函数

来自分类Dev

如何编写此迭代函数以递归?

来自分类Dev

此递归函数如何返回正确答案?

来自分类Dev

JavaScript 构造函数侦听此变量更改

来自分类Dev

此递归函数的意义

来自分类Dev

此函数如何知道变量存在?

来自分类Dev

如何在函数外部访问此变量?

来自分类Dev

如何更改此函数的返回类型?

来自分类Dev

递归函数的变量值在PHP中未更改

来自分类Dev

如何在Swift中编写此递归函数?

来自分类Dev

如何使此递归函数更有效?

来自分类Dev

此递归数组置换函数如何在后台运行?

来自分类Dev

如何以非递归形式重写此函数?

来自分类Dev

谁能告诉我此函数的递归部分如何工作?

来自分类Dev

如何摆脱此递归Scheme函数产生的#<void>?

来自分类Dev

您如何利用Swift功能来重构此递归函数?

来自分类Dev

努力了解此递归函数

来自分类Dev

递归函数变量混淆

来自分类Dev

防止此变量更改

来自分类Dev

如何使用函数更改返回函数/更改变量?

来自分类Dev

如何在递归宏中更改参数变量值?

来自分类Dev

如何在不更改变量的情况下递归

来自分类Dev

如何在python“递归”函数中重置全局变量?

来自分类Dev

如何使内部递归函数在OCaml中达到原始变量?

来自分类Dev

如何在python“递归”函数中重置全局变量?

来自分类Dev

我对递归函数中变量如何工作的理解是否正确?

来自分类Dev

如何解决递归函数中的变量增量问题