50 lines
1.5 KiB
Haskell
50 lines
1.5 KiB
Haskell
module ProjectEuler
|
|
( isPrime,
|
|
primeSieve,
|
|
lcmm,
|
|
digitSum,
|
|
sumProperDivisors,
|
|
countDivisors,
|
|
isPandigital,
|
|
)
|
|
where
|
|
|
|
import Data.Char (digitToInt)
|
|
import Data.List (nub)
|
|
import Data.List.Ordered (minus, unionAll)
|
|
|
|
isPrime :: (Integral n) => n -> Bool
|
|
isPrime 1 = False
|
|
isPrime 2 = True
|
|
isPrime 3 = True
|
|
isPrime n =
|
|
n > 0 && odd n && n `mod` 3 /= 0 && null [x | x <- candidates, n `mod` x == 0 || n `mod` (x + 2) == 0]
|
|
where
|
|
candidates = [5, 11 .. limit]
|
|
limit = floor (sqrt (fromIntegral n)) + 1
|
|
|
|
primeSieve :: (Integral n) => [n]
|
|
primeSieve = 2 : 3 : [5, 7 ..] `minus` unionAll [[p * p, p * p + 2 * p ..] | p <- tail primeSieve]
|
|
|
|
lcmm :: (Integral n) => [n] -> n
|
|
lcmm values
|
|
| length values == 2 = lcm (head values) (last values)
|
|
| otherwise = lcm (head values) (lcmm (tail values))
|
|
|
|
digitSum :: (Integral a, Show a) => a -> Int
|
|
digitSum n = sum $ map digitToInt $ show n
|
|
|
|
sumProperDivisors :: (Integral a) => a -> a
|
|
sumProperDivisors n = sum [if x /= y then x + y else x | x <- [2 .. floor $ sqrt $ fromIntegral n], let { y = n `div` x }, n `mod` x == 0] + 1
|
|
|
|
countDivisors :: (Integral a) => a -> Int
|
|
countDivisors n = length $ nub $ concat [[x, n `div` x] | x <- [1 .. limit], n `mod` x == 0]
|
|
where
|
|
limit = floor $ sqrt $ fromIntegral n
|
|
|
|
isPandigital :: Integer -> Bool
|
|
isPandigital n = n_length == length (nub n_char) && '0' `notElem` n_char && digitToInt (maximum n_char) == n_length
|
|
where
|
|
n_char = show n
|
|
n_length = length n_char
|