3

私は現在、友好的なペアを計算するプログラムに取り組んでいます (Project Euler Problem 21 )。私はすでに解決策を見つけましたが、私のプログラムの欠陥は、数値がペアであることが既にわかっているかどうかに関係なく、セット [1..] のすべての数値を評価することであることに気付きました。

つまり、現在評価中の 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..]

例として:

take 4 amicables

戻り値:

[220,284,284,220]

私はHaskellと関数型プログラミングにかなり慣れていないので、明らかな解決策であれば許してください。

4

2 に答える 2

5

問題は、両方の友好的な番号を出力して安全な作業をしようとすることです。しかし、実際には、あなたの関数は友好的であるかどうかにかかわらず、両方の数値を計算するため、あまり安全ではありません。なぜこのようにしないのですか:

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..]
于 2011-05-31T11:37:49.190 に答える
2

おそらく、ヘルプのわずかな変更getAmicablePairですか?

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

...つまり、最初の要素が小さいペアを取得するだけです

于 2011-05-31T11:34:42.653 に答える