麻烦在Haskell中使用map

时间:2009-09-17 10:21:28

标签: haskell functional-programming

我正在尝试制作一个算法来解决Project Euler Problem 255

我提出了这个解决方案:

roundedSq n | (roundedSq n) == roundedSq (n-1) = n : roundedSq (n+1)
            | rem n 2 == 1  = n : floor ( ((2*10^((d-1) `div` 2)) + ceiling (n `div` (2*10^((d-1) `div` 2)) )) `div` 2 )
            | otherwise     = n : floor ( ((7*10^((d-2) `div` 2)) + ceiling (n `div` (7*10^((d-2) `div` 2)) )) `div` 2 )
        where
                d = length (map (digitToInt) (show (n)))

average a = (sum a) `div` (length a)
answer = average [map roundedSq [10E13..10E14]]

main = do
  print answer

但每次我尝试加载时,answer计算功能都会出错。 我做错了什么,这甚至会给我一个正确的解决方案,还是只会陷入困境?

4 个答案:

答案 0 :(得分:5)

answer = average [map roundedSq [10E13..10E14]]

您已将映射列表放入此处的一个元素列表中。我想也许你的意思是:

answer = average (map roundedSq [10E13..10E14])

答案 1 :(得分:2)

您的average存在问题。

average a = (sum a) `div` (length a)

sum使用整个列表。 length也使用整个列表。这意味着整个列表将生成并保存在内存中,而其中一个函数遍历它,并且在其他函数遍历它之前不会进行垃圾收集。

你传递average一个非常大的列表,所以你的内存不足。

解决方案:将average重写为仅遍历列表一次的函数,以便在生成列表时对其进行垃圾回收。

示例(未经测试):

average a = sum `div` length
  where (sum, length) = foldl' f (0, 0) a
        f (sum, length) i = (sum + i, length + 1)

请注意,这使用的foldl'来自Data.List,而不是foldlfoldl有自己的空间问题(比我更有知识的人可能希望评论)。

正如TobiasWärre指出的那样,

roundedSq n | (roundedSq n) == roundedSq (n-1) = n : roundedSq (n+1)

将导致无限循环:

  1. 我们要评估roundedSq n
  2. 如果(roundedSq n) == roundedSq (n-1)为真,我们将返回n : roundedSq (n+1)作为答案
  3. 我们需要评估(roundedSq n) == roundedSq (n-1)
  4. 我们需要评估roundedSq n
  5. 转到1。

答案 2 :(得分:1)

如果您希望平均值返回Fractional个数字,则需要使用此定义:

average a = (sum a) / (fromIntegral $ length a)

(/)Fractional除法运算符,而divIntegral除法运算符。请注意,您还需要使用fromIntegral,因为length会返回Int,而Fractional不是{{1}}类型类的一部分。

答案 3 :(得分:0)

由于

,你会陷入无限循环
roundedSq n | (roundedSq n) ...

编辑:有时似乎我脑子里有个洞。当然平均值还可以。

但是,由于您没有递减或递增所有对舍入的递归调用,您将永远不会触及“底部”并终止。