Sieve of Eratosthenes in Haskell - haskell

I'm solving some classic problems in Haskell to develop my functional
skills and I have a problem to implement an optimization suggested at this "Programming Praxis" site:
I have three solutions to this problem and the third one is too slow
compared to the second solution. Can someone suggest some improvements to
my code?
My implementations are:
-- primeira implementação
primes n
| n < 2 = []
| n == 2 = [2]
| n `mod` 2 == 0 = primes'
| otherwise = if (find (\x -> n `mod` x == 0) primes') == Nothing then
n:primes'
else
primes'
where primes' = primes (n - 1)
-- segunda implementação
primes' :: Integer -> [Integer]
primes' n = sieve $ 2 : [3,5..n]
where sieve :: [Integer] -> [Integer]
sieve [] = []
sieve l#(x:xs)
| x*x >= n = l
| otherwise = x : sieve list'
where list' = filter (\y -> y `mod` x /= 0) xs
-- terceira implementação
primes'' :: Integer -> [Integer]
primes'' n = 2 : sieve 3 [3,5..n]
where sieve :: Integer -> [Integer] -> [Integer]
sieve _ [] = []
sieve m l#(x:xs)
| m*m >= n = l
| x < m*m = x : sieve m xs
| otherwise = sieve (m + 2) list'
where list'= filter (\y -> y `mod` m /= 0) l

Looks to me like the problem with your third revision is how you choose the next element to sift on.
You indiscriminately increment by 2. The problem is that you then sift on unnecessary numbers.
for example, in this version your eventually going to pass 9 as m, and you're going to do an extra recursion to filter on 9, even though it isn't even in the list, and thus you should have never picked it in the first place (since it would have been removed in the very first filter on 3)
Even though the second version doesn't start the filtering past the square of the number it sifts on, it never chooses an unnecessary sifting value.
In other words, I think you end up sifting on every odd number between 3 and n. Instead you should be sifting on every odd number that hasn't already been removed by a previous pass.
I think to correctly implement the optimization of starting the sieve at the square of the current sift value, you have to retain the front of the list while sifting on the back where back contains the elements >= the square of the sift value. I think this would force you to use concatenations, and I'm not so sure that the optimization is good enough to cancel out the overhead induced by using ++.

First of all, mod is slow so use rem in situations where it doesn't matter (when you aren't dealing with negatives, basically). Secondly, use Criterion to show (to yourself) what is faster and what changes are actually optimizations. I know I'm not giving a full answer to you question with this, but its a good place for you (and other potential answerers) to start, so here's some code:
import List
import Criterion.Main
main = do
str <- getLine
let run f = length . f
input = read str :: Integer
defaultMain [ bench "primes" (nf (run primes) input)
, bench "primes'" (nf (run primes') input)
, bench "primes''" (nf (run primes'') input)
, bench "primesTMD" (nf (run primesTMD) input)
, bench "primes'TMD" (nf (run primes'TMD) input)
, bench "primes''TMD" (nf (run primes''TMD) input)
]
putStrLn . show . length . primes'' $ (read str :: Integer)
-- primeira implementação
primes n
| n < 2 = []
| n == 2 = [2]
| n `mod` 2 == 0 = primes'
| otherwise = if (find (\x -> n `mod` x == 0) primes') == Nothing then
n:primes'
else
primes'
where primes' = primes (n - 1)
primesTMD n
| n < 2 = []
| n == 2 = [2]
| n `mod` 2 == 0 = primes'
| otherwise = if (find (\x -> n `rem` x == 0) primes') == Nothing then
n:primes'
else
primes'
where primes' = primesTMD (n - 1)
-- segunda implementação
primes' :: Integer -> [Integer]
primes' n = sieve $ 2 : [3,5..n]
where sieve :: [Integer] -> [Integer]
sieve [] = []
sieve l#(x:xs)
| x*x >= n = l
| otherwise = x : sieve list'
where list' = filter (\y -> y `mod` x /= 0) xs
primes'TMD :: Integer -> [Integer]
primes'TMD n = sieve $ 2 : [3,5..n]
where sieve :: [Integer] -> [Integer]
sieve [] = []
sieve l#(x:xs)
| x*x >= n = l
| otherwise = x : sieve list'
where list' = filter (\y -> y `rem` x /= 0) xs
-- terceira implementação
primes'' :: Integer -> [Integer]
primes'' n = 2 : sieve 3 [3,5..n]
where sieve :: Integer -> [Integer] -> [Integer]
sieve _ [] = []
sieve m l#(x:xs)
| m*m >= n = l
| x < m*m = x : sieve m xs
| otherwise = sieve (m + 2) list'
where list'= filter (\y -> y `mod` m /= 0) l
primes''TMD :: Integer -> [Integer]
primes''TMD n = 2 : sieve 3 [3,5..n]
where sieve :: Integer -> [Integer] -> [Integer]
sieve _ [] = []
sieve m l#(x:xs)
| m*m >= n = l
| x < m*m = x : sieve m xs
| otherwise = sieve (m + 2) list'
where list'= filter (\y -> y `rem` m /= 0) l
Notice the improved runtime of the variants using rem:
$ ghc --make -O2 sieve.hs
$./sieve
5000
...
benchmarking primes
mean: 23.88546 ms, lb 23.84035 ms, ub 23.95000 ms
benchmarking primes'
mean: 775.9981 us, lb 775.4639 us, ub 776.7081 us
benchmarking primes''
mean: 837.7901 us, lb 836.7824 us, ub 839.0260 us
benchmarking primesTMD
mean: 16.15421 ms, lb 16.11955 ms, ub 16.19202 ms
benchmarking primes'TMD
mean: 568.9857 us, lb 568.5819 us, ub 569.4641 us
benchmarking primes''TMD
mean: 642.5665 us, lb 642.0495 us, ub 643.4105 us
While I see you are doing this for your own education, its worth noting the related links of Primes on Haskell.org and the fast Primes package on hackage.

This is not optimized but expressive implementation: check video Sieve of Eratosthenes in haskell
import qualified Data.Set as Set(fromList,difference)
kr n l = (*n) <$> [2..l `div` n]
g n = difference (fromList [2..n]) (fromList $ concat $ ((flip kr) n) <$> [2..n])

Related

Breaking out of If-Then when a certain requirement is met in Haskell

I am given the assignment of coding a hailstone sequence in Haskell. I must be given an integer and create a list of integers ending with the last number 1, eg.
-- > hailstone 4
-- [4,2,1]
-- > hailstone 6
-- [6,3,10,5,16,8,4,2,1]
-- > hailstone 7
-- [7,22,11,34,17,52,26,13,40,20,10,5,16,8,4,2,1]
My answer should have just one 1 at the end, however I do not know how to break out of the loop once reaching 1.
hailstone :: Integer -> [Integer]
hailstone = takeWhile (>=1) . (iterate collatz)
where collatz n = if n == 1
then 1
else if even n
then n `div` 2
else 3*n+1
I end up with infinite 1's at the end of this. How can I fix this?
You can use a function like takeUntil :: (a -> Bool) -> [a] -> [a] from the utility-ht package [hackage]. This function will:
Take all elements until one matches. The matching element is returned, too. This is the key difference to takeWhile (not . p). It holds takeUntil p xs == fst (breakAfter p xs).
So we can use that to include the 1:
import Data.List.HT(takeUntil)
hailstone :: Integer -> [Integer]
hailstone = takeUntil (== 1) . iterate collatz
where collatz 1 = 1
collatz n | even n = div n 2
| otherwise = 3 * n + 1
or we can implment takeUntil ourself:
takeUntil :: (a -> Bool) -> [a] -> [a]
takeUntil p = go
where go [] = []
go (x:xs) | p x = [x]
| otherwise = x : go xs
or with a fold:
takeUntil :: (a -> Bool) -> [a] -> [a]
takeUntil p = foldr (\x y -> x : if p x then [] else y) []
For negative numbers, the collatz can get stuck in an infinite loop:
Prelude> hailstone (-7)
[-7,-20,-10,-5,-14,-7,-20,-10,-5,-14,-7,-20,-10,-5,-14,-7,-20,-10,-5,-14,
We thus might want to change the condition for all numbers less than or equal to 1:
hailstone :: Integer -> [Integer]
hailstone = takeUntil (<= 1) . iterate collatz
where collatz 1 = 1
collatz n | even n = div n 2
| otherwise = 3 * n + 1
All this use of takeUntil, iterate, breaking out has a very imperative feel for me (do something with the numbers until you reach 1 - and then how the hell do I stop? what is the Haskell equivalent of a break statement.....?)
There is nothing wrong with that, and it wil work eventually, but when using Haskell, is often better to think a bit more declaratively: the tail of a hailstone sequence (other than [1]) is another (shorter) hailstone sequence, so hailstone n = n : hailstone (f n) for some f
Thus:
hailstone n
| n == 1 = [1]
| even n = n : hailstone (n `div` 2)
| otherwise = n : hailstone (3*n + 1)
The sole classic library function that seems to offer some hope is unfoldr. It uses the Maybe monad, and returning Nothing is what stops the recursion.
unfoldr :: (b -> Maybe (a, b)) -> b -> [a]
You have to pick the proper function argument:
import Data.List
hailstone :: Integer -> [Integer]
hailstone n =
let next nn = if (even nn) then (div nn 2) else (3*nn+1)
unfn nn = if (nn==1) then Nothing else let nx = next nn in Just (nx,nx)
in
n : (unfoldr unfn n)
main = do
putStrLn $ "hailstone 7 is: " ++ show (hailstone 7)
That way, the stopping criterion is clearly separated from the successor function.

Haskell: How to find the number of integer solutions to equation for use in Sieve of Atkin?

I am currently trying to implement the Sieve of Atkin in Haskell
In step 3 on the Wikipedia article on the Sieve of Atkin I need to find the number of Integer solutions to multiple equations.
However my solution to the first of these equations (4x² + y² = n, x > 0, y > 0
with n being a entry in a list of positive Integers) produces an infinite loop upon a query with any n.
This is my code for this part of the problem so far:
eq1 :: Integer -> Integer
eq1 n = eq1_ n []
eq1_ :: Integer -> [(Integer, Integer)] -> Integer
eq1_ n list | (x > 0) && (y > 0) && (n == 4*(x^2) + (y^2)) && (notElem ((x,y)) list) = eq1_ n ([(x, y)] ++ list)
| otherwise = toInteger (length list)
where
x = floor (sqrt (fromIntegral ((n - y^2) `div` 4)))
y = floor (sqrt (fromIntegral (n - 4*(x^2))))
It is loaded just fine by WinGHCi, but when I query e.g. eq1 0 it just stays in an infinite loop and has to be interrupted before producing an answer. I suspect it goes in a loop between the two assignments of x and y.
How can I prevent this? Is this even possible?
Edit: Realised where the infinite loop must be.
I'm going to start by reformatting your code a tad to make it more readable. Line breaks are helpful! Also, the order of operations can reduce the weight of parentheses. Side note:
f x | e1 && e2 && e3 = e4
can also be written
f x | e1
, e2
, e3
= e4
which may be easier on the eyes.
eq1 :: Integer -> Integer
eq1 n = eq1_ n []
eq1_ :: Integer -> [(Integer, Integer)] -> Integer
eq1_ n list
| x > 0 &&
y > 0 &&
n == 4*x^2 + y^2 &&
notElem (x,y) list
= eq1_ n ([(x, y)] ++ list)
| otherwise
= toInteger (length list)
where
isqrt = floor . sqrt . fromIntegral
x = isqrt $ (n - y^2) `div` 4
y = isqrt $ n - 4*(x^2)
Now I can immediately see that the logic is wonky. Given n, you calculate x and y. Then you either stop or call the function recursively. On the recursive call, however, you're guaranteed to stop! So even if you were otherwise right, you'd definitely have a semantic problem, always returning 0 or 1.
But as you've seen, that's not the only problem. You're also defining x in terms of y and y in terms of x. Now there are important situations where such mutual recursion is useful. But when the mutually recursive values are "atomic" things like integers, you're sure to get an infinite loop. Haskell won't solve the equations for you; that's your job!
Here's my suggestion:
Start with a brute force list comprehension solution:
sols n
= [(x,y)
|x <- takeWhile (\p -> 4 * p^2 < n) [1..]
,y <- takeWhile (\q -> f x y <= n) [1..]
,f x y = n]
where
f x y = 4*x^2+y^2
Next, you can use an approximate integer square root to narrow the search space for y:
sols n
= [(x,y)
|x <- takeWhile (\p -> 4 * p^2 < n) [1..]
,y <- takeWhile
(\q -> f x y <= n)
[floor(sqrt(fromIntegral(n-4*x^2)))..]
,f x y = n]
where
f x y = 4*x^2+y^2

Number of loops in recursion

I would like to count the number of positive integers/elements in the list. This returns the elements with positive values, how can I count the elements? would like to construct something like count(array(...)).
I would like to see a version with i++ and foldl. That would be very helpful.
countPositivesRec :: [Int] -> [Int]
countPositivesRec [] = []
countPositivesRec (x:xs) | x >= 0 = x : tl
| otherwise = tl
where tl = countPositivesRec xs
Here's a hint: follow the same recursion scheme as before, but return an int at every step.
countPositivesRec :: [Int] -> Int
---
countPositivesRec [] = 0 -- no positives in the empty list
countPositivesRec (x:xs) | x >= 0 = ??
| otherwise = ??
where tl = countPositivesRec xs
One you solve this, it can be rewritten using foldr, if you want.
If you really want to use foldl instead, I would suggest you start by defining a function f such that
f (f (f 0 x0) x1) x2
evaluates to the number of positives in x0,x1,x2. Then you can use foldl f 0 inputList
The function you've written is filter (>=0). As Paul pointed out, the only step remaining is to count and length does that. We can transform the function step by step:
countPositivesRec :: [Int] -> [Int]
countPositivesRec [] = []
countPositivesRec (x:xs) | x >= 0 = x : tl
| otherwise = tl
where tl = countPositivesRec xs
Observe that xs is only used in the transformed form tl. That's what makes this a right fold.
onlypos1 = foldr maybekeep []
where maybekeep x tl | x >= 0 = x : tl
| otherwise = tl
This operation is known as a filter, keeping only some parts:
onlypos2 = filter dowekeep
where dowekeep x = x >= 0
onlypos3 = filter (\x -> x >= 0)
onlypos4 = filter (>= 0)
But this is of course only one of many possible approaches. For instance, strictness analysis can lead to the conclusion that length is better implemented as foldl' (\a _ -> succ a) 0 than foldr (\_ a -> succ a) 0. Indeed, that is its basic form in the Prelude:
length = foldl' (\c _ -> c+1) 0
We see that the combining function of length ignores the value of one argument, merely requires it to be there. This can naturally be merged with our condition that only some elements count:
lengthFilter1 = length . filter
lengthFilter2 pred = foldl' predCount 0
where predCount c x = if pred x then c+1 else c
countNonNegative = lengthFilter2 nonNegative
where nonNegative x = x >= 0
Incidentally, 0 isn't positive. It's non-negative.
In the end, Haskell's lazy lists mean we can use them to fuse traversals; length . filter (>=0) will only read the input list once, because the only reason it's processing results from filter is that length consumes them. The filtered list never exists as a fully expanded structure, unlike e.g. Python or PHP. This form is likely one of the most readable, but others exist, e.g.:
countNonNegatives xs = sum [1 | x <- xs, x >= 0]
You have
filtering p cons x r = if | p x -> cons x r | otherwise -> r
countPositives = length
. filter (> 0)
= foldr (\x r -> r + 1) 0 -- r++
. foldr (filtering (> 0) (:) ) []
= foldr (filtering (> 0) (\x r -> r + 1)) 0
(since folds fuse by composing their reducer transformers, a-la "fold replaces the cons with a reducer operation, so why create the cons in the first place if it gonna be replaced anyway"), and
filtering (> 0) (\x r -> r + 1) x r
= if | (> 0) x -> (\x r -> r + 1) x r | otherwise -> r
= if | x > 0 -> r + 1 | otherwise -> r
and thus, a version with fold and increment that you wanted,
countPositives = foldr (\x r -> if | x > 0 -> r + 1 | otherwise -> r) 0 -- r++
You can take it from here.

find primes number starting at 2 Haskell

Write a function called isPrime that determines if an Integer is a prime number (evenly
divisible only by itself and one). For reference, here’s a list of the primes less than 100:
[2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97]
What are the 1000th through 1020th prime numbers? (starting at 2)
isPrime :: [Integer]
isPrime = sieve [2..1020]
where
sieve (p:xs)
| p*p <= 1020 = p : sieve [x|x <- xs, x `mod` p > 0]
| otherwise = (p:xs)
I tried this code, but it prints primes 2 through 1020.
I want to show 1000 through 1020 starting at 2
Instead of generating primes up to 1020, to emit the 1000th through 1020th primes, you can generate the first 1020 primes and emit only the last 21 of them.
Using a naive unbounded sieve, we can write the following
minus :: Ord a => [a] -> [a] -> [a]
minus (x:xs) (y:ys) = case (compare x y) of
LT -> x : minus xs (y:ys)
EQ -> minus xs ys
GT -> minus (x:xs) ys
minus xs _ = xs
primes :: [Integer]
primes = eratos [2..]
where
eratos [] = []
eratos (p:xs) = p : eratos (xs `minus` [p, p+p..])
primesFromTo from to = drop (from-1) $ take to primes
Then find primesFromTo 1000 1020:
*Main> primesFromTo 1000 1020
[7919,7927,7933,7937,7949,7951,7963,7993,8009,8011,8017,8039,8053,8059,8069,8081,8087,8089,8093,8101,8111]
As an aside, the naming (isPrimes) is a bit questionable for a list of primes...

Prime factors in Haskell

I'm new to Haskell.
How to generate a list of lists which contains prime factors of next integers?
Currently, I only know how to generate prime numbers:
primes = map head $ iterate (\(x:xs) -> [y | y<-xs, y `mod` x /= 0 ]) [2..]
A simple approach to determine the prime factors of n is to
search for the first divisor d in [2..n-1]
if D exists: return d : primeFactors(div n d)
otherwise return n (since n is prime)
Code:
prime_factors :: Int -> [Int]
prime_factors 1 = []
prime_factors n
| factors == [] = [n]
| otherwise = factors ++ prime_factors (n `div` (head factors))
where factors = take 1 $ filter (\x -> (n `mod` x) == 0) [2 .. n-1]
This obviously could use a lot of optimization (search only from 2 to sqrt(N), cache the prime numbers found so far and compute the division only for these etc.)
UPDATE
A slightly modified version using case (as suggested by #user5402):
prime_factors n =
case factors of
[] -> [n]
_ -> factors ++ prime_factors (n `div` (head factors))
where factors = take 1 $ filter (\x -> (n `mod` x) == 0) [2 .. n-1]
Until the dividend m < 2,
take the first divisor n from primes.
repeat dividing m by n while divisible.
take the next divisor n from primes, and go to 2.
The list of all divisors actually used are prime factors of original m.
Code:
-- | prime factors
--
-- >>> factors 13
-- [13]
-- >>> factors 16
-- [2,2,2,2]
-- >>> factors 60
-- [2,2,3,5]
--
factors :: Int -> [Int]
factors m = f m (head primes) (tail primes) where
f m n ns
| m < 2 = []
| m `mod` n == 0 = n : f (m `div` n) n ns
| otherwise = f m (head ns) (tail ns)
-- | primes
--
-- >>> take 10 primes
-- [2,3,5,7,11,13,17,19,23,29]
--
primes :: [Int]
primes = f [2..] where f (p : ns) = p : f [n | n <- ns, n `mod` p /= 0]
Update:
This replacement code improves performance by avoiding unnecessary evaluations:
factors m = f m (head primes) (tail primes) where
f m n ns
| m < 2 = []
| m < n ^ 2 = [m] -- stop early
| m `mod` n == 0 = n : f (m `div` n) n ns
| otherwise = f m (head ns) (tail ns)
primes can also be sped up drastically, as mentioned in Will Ness's comment:
primes = 2 : filter (\n-> head (factors n) == n) [3,5..]
This is a good-performanced and easy-to-understand implementation, in which isPrime and primes are defined recursively, and primes will be cached by default. primeFactors definition is just a proper use of primes, the result will contains continuous-duplicated numbers, this feature makes it easy to count the number of each factor via (map (head &&& length) . group) and it's easy to unique it via (map head . group) :
isPrime :: Int -> Bool
primes :: [Int]
isPrime n | n < 2 = False
isPrime n = all (\p -> n `mod` p /= 0) . takeWhile ((<= n) . (^ 2)) $ primes
primes = 2 : filter isPrime [3..]
primeFactors :: Int -> [Int]
primeFactors n = iter n primes where
iter n (p:_) | n < p^2 = [n | n > 1]
iter n ps#(p:ps') =
let (d, r) = n `divMod` p
in if r == 0 then p : iter d ps else iter n ps'
And the usage:
> import Data.List
> import Control.Arrow
> primeFactors 12312
[2,2,2,3,3,3,3,19]
> (map (head &&& length) . group) (primeFactors 12312)
[(2,3),(3,4),(19,1)]
> (map head . group) (primeFactors 12312)
[2,3,19]
Haskell allows you to create infinite lists, that are mutually recursive. Let's take an advantage of this.
First let's create a helper function that divides a number by another as much as possible. We'll need it, once we find a factor, to completely eliminate it from a number.
import Data.Maybe (mapMaybe)
-- Divide the first argument as many times as possible by the second one.
divFully :: Integer -> Integer -> Integer
divFully n q | n `mod` q == 0 = divFully (n `div` q) q
| otherwise = n
Next, assuming we have somewhere the list of all primes, we can easily find factors of a numbers by dividing it by all primes less than the square root of the number, and if the number is divisible, noting the prime number.
-- | A lazy infinite list of non-trivial factors of all numbers.
factors :: [(Integer, [Integer])]
factors = (1, []) : (2, [2]) : map (\n -> (n, divisors primes n)) [3..]
where
divisors :: [Integer] -> Integer -> [Integer]
divisors _ 1 = [] -- no more divisors
divisors (p:ps) n
| p^2 > n = [n] -- no more divisors, `n` must be prime
| n' < n = p : divisors ps n' -- divides
| otherwise = divisors ps n' -- doesn't divide
where
n' = divFully n p
Conversely, when we have the list of all factors of numbers, it's easy to find primes: They are exactly those numbers, whose only prime factor is the number itself.
-- | A lazy infinite list of primes.
primes :: [Integer]
primes = mapMaybe isPrime factors
where
-- | A number is prime if it's only prime factor is the number itself.
isPrime (n, [p]) | n == p = Just p
isPrime _ = Nothing
The trick is that we start the list of factors manually, and that to determine the list of prime factors of a number we only need primes less then its square root. Let's see what happens when we consume the list of factors a bit and we're trying to compute the list of factors of 3. We're consuming the list of primes, taking 2 (which can be computed from what we've given manually). We see that it doesn't divide 3 and that since it's greater than the square root of 3, there are no more possible divisors of 3. Therefore the list of factors for 3 is [3]. From this, we can compute that 3 is another prime. Etc.
I just worked on this problem. Here's my solution.
Two helping functions are
factors n = [x | x <- [1..n], mod n x == 0]
isPrime n = factors n == [1,n]
Then using a list comprehension to get all prime factors and how many are they.
prime_factors num = [(last $ takeWhile (\n -> (x^n) `elem` (factors num)) [1..], x) | x <- filter isPrime $ factors num]
where
x <- filter isPrime $ factors num
tells me what prime factors the given number has, and
last $ takeWhile (\n -> (x^n) `elem` (factors num)) [1..]
tells me how many this factor is.
Examples
> prime_factors 36 -- 36 = 4 * 9
[(2,2),(2,3)]
> prime_factors 1800 -- 1800 = 8 * 9 * 25
[(3,2),(2,3),(2,5)]
More elegant code,use 2 and odd numbers to divide the number.
factors' :: Integral t => t -> [t]
factors' n
| n < 0 = factors' (-n)
| n > 0 = if 1 == n
then []
else let fac = mfac n 2 in fac : factors' (n `div` fac)
where mfac m x
| rem m x == 0 = x
| x * x > m = m
| otherwise = mfac m (if odd x then x + 2 else x + 1)
Here's my version. Not as concise as the others, but I think it's very readable and easy to understand.
import Data.List
factor :: Int -> [Int]
factor n
| n <= 1 = []
| even n = 2 : factor(div n 2)
| otherwise =
let root = floor $ sqrt $ fromIntegral n
in
case find ((==) 0 . mod n) [3, 5.. root] of
Nothing -> [n]
Just fac -> fac : factor(div n fac)
I'm sure this code is ugly enough to drive a real Haskell programmer to tears, but it works in GHCI 9.0.1 to provide prime factors with a count of each prime factor.
import Data.List
factors n = [x | x <- [2..(n`div` 2)], mod n x == 0] ++ [n]
factormap n = fmap factors $ factors n
isPrime n = case factormap n of [a] -> True; _ -> False
primeList (x:xs) = filter (isPrime) (x:xs)
numPrimes n a = length $ (factors n) `intersect` (takeWhile ( <=n) $ iterate (a*) a)
primeFactors n = primeList $ factors n
result1 n = fmap (numPrimes n) (primeFactors n)
answer n = ((primeFactors n),(result1 n))
Example:
ghci> answer 504
([2,3,7],[3,2,1])
The answer is a list of prime factors and a second list showing how many times each
prime factor is in the submitted number.

Resources