这段代码可以在没有显式递归的情况下编写吗? [项目欧拉#31扰流板]

时间:2012-11-21 16:34:49

标签: haskell

此功能是Project Euler问题解决方案的核心:

numWays tot (d:ds) = sum $ map (flip numWays ds . (tot -)) [0, d .. tot]
numWays tot []
    | tot == 0     = 1
    | otherwise    = 0

我想相信它可以在没有显式递归的情况下重写,但递归在地图下的事实阻碍了我找到它的努力。

1 个答案:

答案 0 :(得分:1)

import Data.List (genericLength)

numWays' tot = genericLength . filter (== 0) . foldl snoc [tot] where
        snoc tots d = concatMap f tots where
                f tot = map (tot -) [0, d .. tot]

我使用genericLength代替length,以便我的numWays'numWays(Num c, Num b, Enum b) => b -> [b] -> c)具有相同的类型。

这里的想法是,不是计算一个(零剩余总数)或零(对于非零残差总和)并对它们求和,我们将函数分解为一个递归函数,生成一个残差列表,然后(非递归地)计算该列表中有多少个零。

这样做的一点是它给我们留下了一个递归函数,我们可以更容易地从中删除递归。