1

我正在使用 Project Euler 问题来学习 Haskell,并且我在许多这些问题中发现了一个反复出现的主题,我需要找到一个值n来为函数提供一些属性(通常是最小值或最大值)f n。当我建立一个解决方案时,我经常发现创建一个对列表很方便(n, f n)。这有助于我快速查看我的逻辑是否有任何错误,因为我可以检查问题陈述中给出的示例。然后我“过滤”出给出解决方案的单对。我对问题 47 的解决方案就是一个例子:

-- Problem 47

import Data.List
import ProjectEuler

main = do
    print (fst (head (filter (\(n, ds) -> (all (==consecutiveCount) ds)) 
                       (zip ns (map (map length) 
                                    (map (map primeDivisors) consecutives))))))
    where consecutiveCount = 4
          consecutive n start = take n [start..]
          consecutives = map (consecutive consecutiveCount) ns
          ns = [1..]

在我看来,有一个更“haskelly”的方式来做到这一点。在那儿?

4

2 回答 2

6

使用maximumByfromData.Listcomparingfrom Data.Ord,例如

maximumBy (comparing snd) [(n, f n) | n <- ns]

这将为f每个n. 如果f计算成本低廉,您可以使用更简单的

maximumBy (comparing f) ns
于 2012-09-05T02:14:38.193 回答
0

好吧,你可以把你的函数写成

main = print $ fst $ head 
         [ (x,ds) | x <- [1..]
                  , let ds=map primeDivisors [x..x+3], all ((==4).length) ds]

您可以认为使用Control.Arrow's(&&&)或“扇出”“更像 Haskelly”

   filter (all ((==4).length).snd) 
          . map (id &&& (\x-> map primeDivisors [x..x+3])) $ [1..]

为了能够调整代码以首先尝试简单的示例,您通常会将其设为函数,对感兴趣的变量进行抽象,如下所示:

test n m = [ x | x <- [1..], all (==n) $ map (length.primeDivisors) [x..x+m-1]]

搜索m具有n不同质因数的连续数。实际上没有必要在最终代码中进行分解。

于 2012-09-05T14:27:31.043 回答