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