【问题标题】:How to memoize recursive collatz function with the elements returned in an array?如何使用数组中返回的元素来记忆递归 collat​​z 函数?
【发布时间】:2018-12-23 23:47:18
【问题描述】:

我有一个记忆函数,它将记忆返回和的递归函数,例如数字,但不是我的 collat​​z 函数,它返回一个数组。我在记忆功能中的地图将有不同的键但相同的值,并且不会记忆功能的每一步。我试图尽可能保持这种可组合性。

collat​​z 中的控制台日志记录以检查它是否已运行将按预期第一次注销。

我已经在指数递归函数上对此进行了测试,使用不同的 keymaker 函数并且它可以正确记忆。

const memoized = (fn, keymaker = JSON.stringify) => {
    const lookupTable = new Map();
    return function (...args) {
      const key = keymaker.call(this, args);
      return lookupTable[key] || (lookupTable[key] = fn.apply(this, args));
    }
  };

  const ignoreOthers = ([...values])=>{
    return JSON.stringify(values.shift())
  }


  const memCollatz = memoized((n,arr=[]) =>{
    //console.log('ran')
    if (n<=1) return arr.concat(1)
    else if(n %2 === 0) return memCollatz(n / 2,arr.concat(n))
    else return memCollatz((n*3)+1,arr.concat(n))
  },ignoreOthers)

  console.log(memCollatz(5))
  console.log(memCollatz(6))
  console.log(memCollatz(6))

   
/*
   Map {
    '1': [ 5, 16, 8, 4, 2, 1 ],
    '2': [ 5, 16, 8, 4, 2, 1 ],
    '3': [ 5, 16, 8, 4, 2, 1 ],
    '4': [ 5, 16, 8, 4, 2, 1 ],
    '5': [ 5, 16, 8, 4, 2, 1 ],
    '6': [ 5, 16, 8, 4, 2, 1 ],
    '8': [ 5, 16, 8, 4, 2, 1 ],
    '10': [ 5, 16, 8, 4, 2, 1 ],
    '16': [ 5, 16, 8, 4, 2, 1 ] } 
 */

运行上述控制台日志后,这就是我的地图的样子,但应该将n 作为键并记住每个步骤。

【问题讨论】:

  • const memCollatz = memoized(const memCollatz const 这里出现错误,是错字吗?也许你可以让它成为一个可运行的 sn-p?
  • 是的,这是一个错字,对不起。我将研究如何使它可运行。

标签: javascript recursion memoization


【解决方案1】:

由于您在 memCollat​​z 中构建 arr 的方式,代码执行将如下所示:

memCollatz(5) | arr = [] | map is empty
memCollatz(16) | arr = [5] | map is empty
memCollatz(8) | arr = [5, 16] | map is empty
memCollatz(4) | arr = [5, 16, 8] | map is empty
memCollatz(2) | arr = [5, 16, 8, 4] | map is empty
memCollatz(1) | arr = [5, 16, 8, 4, 2] | map is empty

最后一次调用 memCollat​​z(1) 是第一个实际返回的东西,所以

{1: [5, 16, 8, 4, 2, 1]}

被添加到查找地图

现在,因为 memCollat​​z(2) 只是返回 memCollat​​z(1) 返回的任何内容,另一个 进入

{2: [5, 16, 8, 4, 2, 1]}

已添加到地图中

再次,因为 memCollat​​z(4) 只是返回 memCollat​​z(2) 返回的任何内容,另一个条目

{4: [5, 16, 8, 4, 2, 1]}

已添加到地图中

...等等。

要解决这个问题,您需要避免这种“传递”行为,即确保 memCollat​​z(1) 返回的内容与 memCollat​​z(2) 不同,等等。

这是一个例子:

  const memCollatz = memoized((n) =>{
    if (n<=1) return [1];
    else if(n %2 === 0) return [n].concat(memCollatz(n / 2))
    else return [n].concat(memCollatz((n*3)+1))
  },ignoreOthers)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-05-29
    • 1970-01-01
    • 1970-01-01
    • 2014-10-31
    • 1970-01-01
    • 2012-11-26
    • 1970-01-01
    相关资源
    最近更新 更多