【问题标题】:Lazy Catalan Numbers in HaskellHaskell 中的惰性加泰罗尼亚数字
【发布时间】:2019-08-30 21:12:53
【问题描述】:

如何有效地生成无限加泰罗尼亚数字列表?我现在所拥有的工作相当快,但在我看来应该有更好的方法。

c 1 = 1
c n = sum (zipWith (*) xs (reverse xs)) : xs
    where xs = c (n-1)

catalan = map (head . c) [1..]

我尝试改用fix,但 lambda 不够懒惰,无法终止计算:

catalan = fix (\xs -> xs ++ [zipWith (*) xs (reverse xs)])

我意识到(++) 并不理想

这样更好的方法存在吗?可以使该功能足够懒惰吗?第 nth 有一个明确的公式,我知道,但我宁愿避免它。

【问题讨论】:

  • 你的 c 函数没有编译,因为它的价值。但是,假设您确实将其调整为工作形式,我认为您要查找的内容并不完全清楚。 “更好”是什么意思——它只是你追求的速度吗?在这个问题的上下文中,你认为“懒惰”是什么意思?

标签: haskell recursion numbers catalan


【解决方案1】:

Catalan numbers [wiki] 可以通过以下方式归纳定义:

C0 = 1Cn+1=(4n+2)×Cn子>/(n+2).

所以我们可以这样实现:

catalan :: Integral i => [i]
catalan = xs
    where xs = 1 : zipWith f [0..] xs
          f n cn = div ((4*n+2) * cn) (n+2)

例如:

Prelude> take 10 catalan
[1,1,2,5,14,42,132,429,1430,4862]

【讨论】:

  • @WillNess: 但这不是一个直接的公式,因为我们不会为n+1 计算c 而不会为c 计算c :)
  • @WillNess:老实说,我没有在问题中看到这一点,它说他们想要避免一个明确的公式,比如c n = div (nCr (2*n) n) (n+1)。你在哪里读到其他非明确的应该避免的?
【解决方案2】:

我猜您正在寻找一个使用基本递归关系之一的所有加泰罗尼亚数字的惰性、无限、自引用列表。毕竟,这与斐波那契数字有关。但是,如果您想回答您的特定问题,指定您所指的递归关系会有所帮助。我猜这就是你的意思:

cat :: Integer -> Integer
cat 1 = 1
cat n = sum [ cat i * cat (n - i) | i <- [1 .. n - 1] ]

如果是这样,到自引用形式的转换如下所示:

import Data.List (inits)

cats :: [Integer]
cats = 1 : [ sum (zipWith (*) pre (reverse pre)) | pre <- tail (inits cats) ]

这比斐波那契的例子复杂得多,因为重复是指列表中所有以前的条目,而不仅仅是最近的固定数字。使用Data.List 中的inits 是获取每个位置前缀的最简单方法。我在那里使用了tail,因为它的第一个结果是空列表,这在这里没有帮助。其余的是对递归关系的直接重写,我没有太多要说的。除了...

它的表现会很糟糕。我的意思是,它比我的cat 函数的指数递归调用要好,但是有很多列表操作正在进行,即分配然后丢弃大量内存单元。这种递归关系不太适合列表数据类型的递归结构。您可以探索很多方法来提高效率,但最终它们都会变得非常糟糕。对于这种特殊情况,如果您想要性能,则采用封闭式解决方案是可行的方法。

【讨论】:

    【解决方案3】:

    Apparently,你想要的是

    > cats = 1 : unfoldr (\ fx -> let x = sum $ zipWith (*) fx cats in Just (x, x:fx)) [1]
    
    > take 10 cats
    [1,1,2,5,14,42,132,429,1430,4862]
    

    这避免了前缀的重复反转(如在链接的答案中),通过将状态作为反转的前缀展开,同时进入状态并产生下一个元素。

    我们不必维护非反转前缀,因为使用加泰罗尼亚语列表压缩反转前缀本身会处理加泰罗尼亚语前缀的长度。

    你确实说过你想避免直接公式。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-02-26
      • 1970-01-01
      • 1970-01-01
      • 2012-04-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多