Finding primes using Sieve of Eratosthenes not working - Haskell - haskell

Here is the code I am trying to use: This should generate all primes up to 100
sieve_primes = [x | x<-[2..100], y<-[2..50], z <-[2..25], (x*z) `mod` y /= 0]

The code
isPrime n = length [x | x<-[2..n], n `mod` x == 0] == 1
computes all the factors just to count them. You don't need to count them: as soon as the second factor is found you can stop your search without checking for further ones.
So, either replace length ... == 1 with a custom predicate, or take 2 elements from the list comprehension before checking its length.

What you had in mind was probably
Prelude> [x| x<-[2..100], not $ elem x [y*z| y<-[2..50], z<-[2..25]]]
[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]
This is very slow. At least we can rearrange the pieces,
Prelude> [x| let sieve=[y*z| y<-[2..50], z<-[2..25]],
x<-[2..100], not $ elem x sieve]
[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]
This is still very slow, for any number much above even 1000 (where you'd use 500 and 250). Then again, why the 25 (250) limit? Your code follows the
primes = [x| x<-[2..], not $ elem x
[y*z| y<-[2..x`div`2], z<-[2..min y (x`div`y)]]]
idea, i.e. y*z = 2*y .. min (y*y) x, so with the known top limit (x <= n) it should be
primesTo n = [x| let sieve=[y*z| y<-[2..n`div`2], z<-[2..min y (n`div`y)]],
x<-[2..n], not $ elem x sieve]
(incidentally, max (min y (n/y)) {y=2..n/2} = sqrt n, so we could've used 10 instead of 25, (and 31 instead of 250, for the 1000)).
Now 1000 is not a problem, only above ~ 10,000 we again begin to see that it's slow (still), running at n2.05..2.10 empirical orders of growth (quick testing interpreted code in GHCi at n = 5000, 10000, 15000).
As for your second (now deleted) function, it can be rewritten, step by step improving its speed, as
isPrime n = length [x | x<-[2..n], n `mod` x == 0] == 1
= take 1 [x | x<-[2..n], n `mod` x == 0] == [n]
= [x | x<- takeWhile ((<=n).(^2)) [2..n], n `mod` x == 0] == []
= and [n `mod` x > 0 | x<- takeWhile ((<=n).(^2)) (2:[3,5..n])]
now, compiled, it can get first 10,000 primes in few tenths of a second.

Related

Creating list with multiple conditions in haskell

Define the sequence (bn)n=1,2,… such that bn=3 when n is divisible by 3, and bn=4(n+1)^2 in other cases.
Define a function that for an argument n creates the list of n initial numbers of the sequence (bn)n=1,2,… .
so far I have two lists with condition 1 and condition 2:
divisible3 n = [x | x <- [1..n], x `mod` 3 == 0]
notdivisible3 n = [x*x*4+8*x+4 | x <- [1..n], x `mod` 3 /= 0]
I want it to be one list like:
list n = [x | x <- [1..n], condition1, condition 2]
You should write an if ... then ... else ... in the "yield" part of the list comprehension, not a filter. So something like:
list n = [ if n `mod` 3 == 0 then … else … | x <- [1..n]]
where I leave the … parts as an exercise.

How to use list comprehension in Haskell?

I am trying to teach myself Haskell and I am doing random exercises.
I was supposed to write a code that will do this 6 = [1*1 + 3*3 + 5*5]= 35
So I had to filter out all odd numbers and then calculate the sum if I multiply every single one with itself.
sumquad n = (potenzsum(filter odd (ones n)))
where
potenzsum [x] = x*x
potenzsum [x,y] = x*x + y*y
potenzsum (x:xs) = x + potenzsum xs
ones 0 = []
ones x = [ 1 .. x]
This code works ;)
Now I am supposed to do the same thing but with list comprehension (I am allowed to use this list [1...n]
I could only think of this... Could someone help me?
power1 xs = [x*x | x <- xs]
Actually, you did half the job by [x * x | x <- xs], just replace xs by odd numbers from the previous example:
[x * x | x <- filter odd (ones 6))]
And you'll receive a list of squares: [1, 9, 25], which can be summed by function sum:
f n = sum [x * x | x <- filter odd (ones n))]
it evaluates to 35
One more note regarding list comprehension: the iterated elements can be filtered out by specifying conditions, which are called guards. Thus, the code above can be refactored into:
f n = sum [x * x | x <- [1..n], odd x]

Testing if an inputted Int is a perfect number

I've been looking into perfect numbers, and I found this interesting bit of code on rosettacode:
perfect n = n == sum [i | i <- [1..n-1], n `mod` i == 0]
Now, I understand what a perfect number is, and I know which numbers are considered perfect, however I'm struggling to work out which parts of this code do what.
I understand that it's working out the factors of the inputted number, and combining them together to see if it matches the input itself, but I'm not sure how it's doing this.
If anyone could possibly break down this bit of code in a beginner-friendly manner I'd be very appreciative.
n == sum [i | i <- [1..n-1], n `mod` i == 0]
^^^^^^^^^
For i from 1 to n-1 (that is, [1, 2, 3, 4 ... n-1])
n == sum [i | i <- [1..n-1], n `mod` i == 0]
^^^^^^
And only for those values where i evenly divides n. Discarding values that do not match this requirement.
n == sum [i | i <- [1..n-1], n `mod` i == 0]
^^^
Include i in the result list.
n == sum [i | i <- [1..n-1], n `mod` i == 0]
^^^^
Add the elements of this list together.
n == sum [i | i <- [1..n-1], n `mod` i == 0]
^^^^
And return True iff the total equals n.
[i | i <- [1..n-1], n `mod` i == 0]
Starting from the middle, you can read it like this: for each element i of the [1..n-1] list, check if n `mod` i equals 0. If it does, include i in the result list (that's the part to the left of the |. Without using the list comprehension syntax, that might be written using the filter function:
filter (\i -> n `mod` i == 0)
The elements of the resulting list are then added with sum, and, finally, the sum is tested for equality with n.

Determine a prime number with right fold

I found this solution on the internet and I need some help understanding it:
isPrime' :: Integer -> Bool
isPrime' n = foldr (\x acc -> (n `rem` x) /= 0 && acc) True primes
where primes = 2 : filter isPrime' [3,5..]
A couple of things:
My understanding is that if the accumulator for a fold function is a Boolean it has to be set in the lambda function itself. Something like:
(\x acc -> if (n `rem` x /= 0) then False else acc) True primes
But here it is not the case.
Also, the range being used for primes does not have a terminating number. I know the reason this works is because of Haskell's lazy evaluation, but how exactly is that working here?
Lastly, this function does not seem like it would return the proper Boolean. A prime number is one that has no other divisors but itself and 1. So shouldnt the lambda read:
(\x acc -> if (n `rem` x) == 0 then False else acc) True primes
I am thoroughly confused. Please help me out.
At least for me, your code doesn't finish. It is missing the stop condition, which can be seen in a similar solution from the wiki:
isPrime n = n > 1 &&
foldr (\p r -> p*p > n || ((n `rem` p) /= 0 && r)) True primes
primes = 2 : filter isPrime [3,5..]
Here you can see, that the condition p*p > n produces True, when there is no possible prime factor left. Because of lazy execution the right part of || is not evaluated and the foldr stops.
having
primes = [p1, p2, p3, ..., pn, ...]
calculating
isPrime' n = foldr (\x acc -> (n `rem` x) /= 0 && acc) True primes
is as if calculating
isPrime' n = rem n p1 /= 0 && (
rem n p2 /= 0 && (
rem n p3 /= 0 && (
..........
rem n pk /= 0 && (
.......... ..... ))))
For composite ns this works – one of the rem expressions will be 0, the inequality is false, and the whole expression is false too, because && is short-circuiting, lazy in its 2nd argument.
For prime ns this will cause a problem: none of the rem expressions will be 0, by definition of a prime, until we reach a prime p_i == n itself among the primes. But it's not there yet, as we haven't detected it as being prime yet - we're just doing it right now. To test whether it is prime, we must know that it is prime - clearly a bad situation.
A value will be demanded from primes which is not there yet. This is known as "black hole". It causes an error, and calculation aborts (or becomes stuck).
To put it differently, it is as if the definition
primes = 2 : filter isPrime' [3,5..]
were defined as
primes = 2 : [ n | n <- [3,5..]
, and [rem n p /= 0 | p <- takeWhile (< n) primes]]
The problem is that to stop when n is prime, takeWhile (< n) must reach a prime p above or equal to n in primes, but it's not there yet. "Black hole".
The famous "sieve" code gets around this problem by "transposing" the workflow,
primes = map head . iterate (\(x:xs)-> filter ((/=0).(`rem`x)) xs) $ [2..]
thus making it work while retaining its computational inefficiency (the lesser problem of your code), testing its candidates by too many primes needlessly (where each prime is tested by all its preceding primes instead of just those not above its square root), making it unnecessarily slow.
This is mitigated by putting a properly early stop to the testing, with
primes = 2 : [ n | n <- [3,5..]
, and [rem n p /= 0 | p <- takeWhile ((<= n).(^2)) primes]]
which, back in terms of your definition, is equivalent to
isPrime' n = p1*p1 > n || rem n p1 /= 0 && (
p2*p2 > n || rem n p2 /= 0 && (
p3*p3 > n || rem n p3 /= 0 && (
..........
pk*pk > n || rem n pk /= 0 && (
.......... ..... ))))
You can write this down as a foldr-based definition now (which can be seen in another answer here).
The expression
(n `rem` x) /= 0
clearly produces a Bool result. The parameter acc is already a Bool value. So
(n `rem` x) /= 0 && acc
is a logical-AND of two Bool values, which clearly produces a Bool result. Where is the confusion?
The input list is infinite, consisting only of odd numbers. So long as you can produce a result after examining only a finite number of values, laziness makes everything fine.

Why does my prime factorization function append 1 to the result?

I am creating a function to factorize any given number in haskell. And so i have created this:
primes :: [Integer]
primes = 2:(sieve [3,5..])
where
sieve (p:xs) = p : sieve [x |x <- xs, x `mod` ((p+1) `div` 2 ) > 0]
factorize 2 = [2]
factorize x
| divisible x = w:(factorize (x `div` w))
| otherwise = [x]
where
divisible :: Integer -> Bool
divisible y = [x |x <- (2:[3,5..y]), y `mod` x == 0] /= []
firstfactor :: Integer -> [Integer] -> Integer
firstfactor a (x:xs)
| a `ifdiv` x = x
| otherwise = firstfactor a xs
firstfactor a _ = a
ifdiv x y = mod x y == 0
w = firstfactor x primes
The function works fine, but appends 1 to the end of the list, for example factorize 80 would give this list: [2,2,2,2,5,1] My question is, why does this happen?
This comes up from two parts of the code. Firstly, factorize 1 is [1]. Secondly, since x is always divisible by itself, your very final call will always have w == x, so the recursion will be w:(factorize (w `div` w)) which is always w:(factorize 1).
To solve this, you can just add an extra base case to throw out the factors of 1:
factorize 1 = []
factorize ...
Also, you can drop the factorize 2 = [2] case because it gets subsumed by the otherwise case you already have.
factorize 1 = [] makes sense mathematically, because 1 has no prime factors (remember that 1 is not a prime number itself!). This follows the same logic behind product [] = 1—1 is the identity for multiplication, which makes it the "default" value when you have nothing to multiply.

Resources