Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
List 是否从[1..]的映射中排除计算结果?_List_Haskell_Infinite_Fold - Fatal编程技术网

List 是否从[1..]的映射中排除计算结果?

List 是否从[1..]的映射中排除计算结果?,list,haskell,infinite,fold,List,Haskell,Infinite,Fold,我目前正在做一个计算友好对的程序(欧拉项目)。我已经找到了解决方案,但是我注意到我的程序中的一个缺陷是它计算集合[1..]的所有数字,不管我们是否已经找到了一对数字 i、 e.如果当前评估的220和284是它的一对,但是当map函数到达284时,它不应该再次评估它 import Data.List properDivisors :: (Integral a) => a -> [a] properDivisors n = [x | x <- [1..n `div` 2],

我目前正在做一个计算友好对的程序(欧拉项目)。我已经找到了解决方案,但是我注意到我的程序中的一个缺陷是它计算集合[1..]的所有数字,不管我们是否已经找到了一对数字

i、 e.如果当前评估的220和284是它的一对,但是当map函数到达284时,它不应该再次评估它

import Data.List

properDivisors :: (Integral a) => a -> [a]
properDivisors n = [x | x <- [1..n `div` 2],
                        n `mod` x == 0 ]

amicablePairOf :: (Integral a) => a -> Maybe a
amicablePairOf a
    | a == b = Nothing
    | a == dOf b = Just b
    | otherwise = Nothing
        where dOf x = sum (properDivisors x)
              b = dOf a

getAmicablePair :: (Integral a) => a -> [a]
getAmicablePair a = case amicablePairOf a of
            Just b -> [a,b]
            Nothing -> []


amicables = foldr (++) [] ams
    where ams = map getAmicablePair [1..]
返回:

[220,284,284,220]

我对Haskell和函数式编程相当陌生,所以如果这是一个显而易见的解决方案,请原谅。

也许对
getAmicablePair
稍作修改会有帮助吗

getAmicablePair :: (Integral a) => a -> [a]
getAmicablePair a = case amicablePairOf a of
            Just b -> if a < b then [a,b] else []
            Nothing -> []
getAmicablePair::(积分a)=>a->[a]
Getanicablepair a=案例友好对a
只要b->如果a[]

。。。所以你只需要得到第一个元素较小的配对,你的问题是,你要通过输出两个友好的数字来保证工作的安全。但事实上,你不太安全,因为你的函数仍然计算这两个数,不管它们是否友好。为什么不这样做:

import Data.List

divSum :: (Integral a) => a -> [a]
divSum n = sum (filter (\a -> a `mod` n == 0) [1..n `div` 2])

isAmicable :: (Integral a) => a -> Bool
isAmicable a = a /= b && a == c where
  b = divSum a
  c = divSum b

amicables = filter isAmicable [1..]

很好的解决方案,但是问题是程序仍然会对这对进行两次评估,只是不会在第二次显示它。我知道如何使用“nub”函数从Data.List中删除重复项,但是我想通过只对一对进行一次计算来提高效率。@Axilus-你说得对。。。但是您不能使用
map
,因为
map
不能引用早期的计算。@Axilus:我怀疑您只计算一次就可以提高效率。首先,您必须在已经生成的所有友好数字列表中进行查找,这样您的函数就不再在常量空间中运行(假设您立即使用结果)。此外,所有数字中只有一小部分是友好的,所以你也不会赢得任何东西。这种友好关系是对称的吗?如果是,Fuzzxxl的解决方案是好的。如果不是。。。那么我怀疑避免这些计算是否明智。@phynfo:amicable意味着两个数字有一种特殊的关系,即它们的除数之和等于另一个数字。所以它确实是对称的。1000000000以下的友好数字只有1427个,因此不值得为这么小的一部分避免计算。一个好的优化方法是检查,如果数字不足,那么总数是否已经包含在列表中。这将有一段时间是安全的,因为人们可以在大约50%的数字中避免第二次求和。Don Knuth有句名言:»过早的选择是万恶之源。«通常,最好的方法是以直接的方式编写代码,然后进行分析。如果结果不令人满意,试着对代码进行优化。最好的方法是以一种简单的方式编写代码,然后在需要时进行概要分析。如果你得到了答案,谁在乎过去花了多长时间
import Data.List

divSum :: (Integral a) => a -> [a]
divSum n = sum (filter (\a -> a `mod` n == 0) [1..n `div` 2])

isAmicable :: (Integral a) => a -> Bool
isAmicable a = a /= b && a == c where
  b = divSum a
  c = divSum b

amicables = filter isAmicable [1..]