【问题标题】:Creating a recursive tacit function in J在 J 中创建递归默认函数
【发布时间】:2014-08-01 22:38:18
【问题描述】:

我是 J 的新手,我一直在尝试创建一个斐波那契函数作为练习(始终是我在学习语言时创建的第二个函数)。我只是无法弄清楚我这样做的方式到底出了什么问题。我试图将其定义为默认,但如果参数大于 1,它就会挂起。

fib =: [ ` (($: (]-1)) + ($: (]-2))) @. (>&1)

我也尝试过显式创建它,效果很好。

fib =: 3 : 'if. y>1 do. (fib (y-1)) + (fib (y-2)) else. y end.'

我试图通过将 3 替换为 13 来创建一个默认值,但它引发了错误。

   fib =: 13 : 'if. y>1 do. (fib (y-1)) + (fib (y-2)) else. y end.'
|spelling error
|   if. y>1 do. (fib (y-1)) + (fib (y-2)) else. y end.
|   ^
|   fib=:    13 :'if. y>1 do. (fib (y-1)) + (fib (y-2)) else. y end.'

所以,我要求有人解释我在这里到底做错了什么。

【问题讨论】:

    标签: recursion j tacit-programming


    【解决方案1】:

    这里有一个我认为更清晰、更简洁的替代方案:

    fibn =: (-&2 +&$: -&1)^:(1&<) M."0
    

    与更规范的(伪代码)定义进行比较:

    fib(n) = fib(n-1) + fib(n-2) if n > 2 else n
    

    首先,不要将[ ` 与使用动名词的@. (&gt;&amp;1) 一起使用,最好使用^:(1&amp;&lt;)。对于f(n) if cond(n) else n,使用^: 连词更惯用; ^:0 表示“什么都不做”,^:1 表示“只做一次”,所以意图很明确。 @. 更适合不平凡的行为。

    其次,使用&amp; 键/组合连接显着简化了火车。 [:] 的重复使用相当混乱和不透明。使用&amp;重构将相关操作放在一起:首先将n拆分为两个,即n-2n-1,然后将这两个数字的fibn相加。

    最后,"0 用于列表处理,M. 用于记忆。从性能的角度来看,M. 相当重要,因为规范定义的直接实现将过度调用fib(2)。借助内置的记忆副词,您可以拥有自己的蛋糕(一个简单的定义)并吃掉它(良好的表现)。

    此特定定义的来源:f0b on this page

    【讨论】:

    • 这就是我现在要做的。我的回答显示了我是如何找到我的解决方案的,我知道这是错误的。无论如何,感谢您花时间写这篇文章。
    • 没问题。我看到了时间戳,所以我猜你可能会得到显着改善并且个人不需要这个建议,但我认为把这个留给任何新手都会很好。
    • 我会将此作为公认的答案,因为它确实有一些很好的信息。
    【解决方案2】:

    好的,我找到了。我通过默认生成器只运行了递归块并得到了这个块。

       13 : '(f y-1) + (f y-2)'
    ([: f 1 -~ ]) + [: f 2 -~ ]
    

    然后我将它插入到原始片段中,得到了这个。

    fib =: [ ` (([: $: 1 -~ ]) + [: $: 2 -~ ]) @. (>&1)
    

    这就像一个魅力。我还在末尾插入了" 0 以使其接受列表。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-09-28
      • 2011-05-13
      • 2016-12-13
      • 1970-01-01
      • 1970-01-01
      • 2012-11-03
      • 2020-09-20
      • 2022-01-12
      相关资源
      最近更新 更多