I know.. The title isn't explaining well.. if you have a better title tell me in a comment..I'm making a prime numbers generator for fun and learning purposes..here's my code:
divisors x xs = [ y | y <- [1]++xs++[x], x `mod` y == 0]
isPrime x xs = divisors x xs == [1,x]
primeLst = [ x | x <- [2..], isPrime x primeLst]
As you can see.. I must use the already generated primes in a condition when generating a new one to reduce execution time.. and it's not working.. Is there a way of making it?
Let us start by looking at the divisors function. It is sort of correct, with only two issues:
What is the xs argument supposed to be? From the definition, it looks like it should be all the prime numbers below x - let's call these the candidate primes. So if x was 10, then the candidate primes should be [2,3,5,7]. However, this is not what the function gets as an argument. In your code, xs is the infinite list of primes.
Technically, the divisors doesn't return all divisors. divisors 16 [2,3,5,7,11,13] wouldn't return 8, for instance. But this is a minor nitpick.
So if we can call divisors with the right list of primes, then we should be ok, and the isPrime function would also be fine.
The problem is getting the list of candidate primes. For clarity, I will give the code first, and then explain:
primeLst = 2 : [ x | x <- [3..], isPrime x (takeWhile (\p -> p*p <= x) primeLst)]
I have made two changes:
I made sure that primeLst includes 2, by sticking it at the front.
I restricted the candidate primes by taking numbers from the infinite list of primes until I reached a number that was higher than the square root of the number I was testing for primeness. In doing this i changed the definition of the candidate primes slightly, so for instance the candidates for 26 are [2,3,5] instead of [2,3,5,7,11,13,17,19,23]. But it still works.
Two questions for you to think about:
Why does it still work with the new definition of candidate primes?
Why doesn't the following line of code work, even though it seems it should give the original definition of the candidate primes?
:
primeLst = 2 : [ x | x <- [3..], isPrime x (takeWhile (\p -> p < x) primeLst)]
The last question is hard, so if you have questions, post them in the comments.
dividedBy a b = a `mod` b == 0
isPrime x = null $ filter (x `dividedBy`) $ takeWhile (\y -> y * y <= x) primeLst
primeLst = 2:(filter isPrime [3..])
or, more verbose:
primeLst = 2:(filter isPrime [3..])
where
isPrime x = null $ primeDivisors x
primeDivisors x = filter (x `dividedBy`) $ potentialDivisors x
potentialDivisors x = takeWhile (\y -> y * y <= x) primeLst
a `dividedBy` b = a `mod` b == 0
Calculating at least one element of primeLst requires calculating isPrime 2 primeLst which requires calculating at least two elements of divisors 2 primeLst which requires calculating at least two elements of [1]++primeLst++[2], which requires calculating at least one element of primeLst. Not gonna happen.
You might be able to make something work that uses [1]++(primesLessThan x)++[x], but I don't see a straightforward way to define (primesLessThan x) in terms of primeLst which avoids computational circularity.
Related
I have two functions, add and iterate, in SML.
fun add(x,y) = x + y
fun iterate n f x = if n > 0 then iterate (n-1) f(f x) else x;
Using those two functions only, how do I write a multiply function that for example if typed:
multiply 5 6
returns 30.
Then building off of that I need a function called power that only uses iterate and multiply to raise the first argument to the power of the second. An example:
power 5 4
It should return 625.
Any help would be greatly appreciated!
So the trick is to use iterate to help you with applying add recursively. Since iterate is a list-combinator that takes a function as argument, perhaps it is simpler if you go about this in a very rudimentary way: For example, you could define add by recursively incrementing/decrementing by one:
(* Written using if-then-else *)
fun add x y =
if y = 0 then x else
if y > 0 then add (x+1) (y-1) else add (x-1) (y+1)
(* Written using mixture of pattern-matching and if-then-else *)
fun add x 0 = x
| add x y = if y > 0
then add (x+1) (y-1)
else add (x-1) (y+1)
Now, that's of course grossly inefficient and completely unnecessary because we already have +, but for the sake of demonstrating recursion on numbers, this is an example of how to progress with multiply and power (still under the assumption that we don't have iterate yet).
The general method here is recursion: Since the function takes two operands, use one as the "accumulating result" and the other as "counting variable". Because this is a simple problem, you can just use x and y as the complete environment for the function's task. In slightly larger problems you might introduce more arguments that work as temporary/intermediate results.
You can write multiply in a very similar way:
fun multiply x 0 = 0
| multiply x y = if y > 0
then x + multiply x (y-1)
else ~x + multiply x (y+1)
This function solves the task (although still without iterate).
(This multiply isn't tail-recursive because the outermost expression (x + ... or ~x + ...) aren't calls to multiply (since the call happens inside the operand of +). That may not be a problem to you, but if it were, you can't easily write ... then multiply (x + ...) (y - 1), since when we use x for the purpose of accumulating the result, any subsequent recursive call has increased x, which means we can no longer add x to... itself... because x means two things now: the accumulating result, and what needs to be added once per recursive call.)
Any way, to get the last step, you have to identify what iterate has in common with the add and multiply I made. When you can spot the common denominator, you can isolate it and call iterate instead. I would like to fix one whitespace "bug" that may confuse your interpretation of iterate:
fun iterate n f x = if n > 0
then iterate (n-1) f (f x)
else x; (* ^- this space! *)
Adding this space does not change the behavior of the function, but when reading f(f x) one is tempted to believe that it says "apply f to f x", which is the wrong interpretation. What this function actually says under then is "call iterate with three arguments: n-1, f and f x; because n-1 binds less tight than function application, and f x is function application (which is left-associative), we add parentheses around them; this is not necessary for f."
In add and multiply, y is being used as the counting variable, whereas in iterate it is n. So the names and positions have changed, which means that a multiply based on iterate has to place the x and y in the right place. As for determining a value for f: How about the function that adds x to its result? You can express this function either using a lambda, (fn z => ...), or using partial application of the function add.
Lastly, with power it is much the same problem:
fun power x 0 = 1
| power x n = if n > 0
then x * power x (n-1)
else raise Fail "Cannot express 1/x^n as integer"
Since there isn't a good solution for integers, you either have to switch to the real type to express 1/x^n, you can also flip the condition and get the case of n < 0 out of the picture before beginning recursion:
fun power x n =
if n < 0 then raise Fail "Cannot express 1/x^n as integer"
else let fun go result 0 = result
| go result i = go (result * x) (i-1)
in go 1 n
end
The inner function go looks terribly much like add above, except x has become result and 1 has become add, and + has become *, and there is no negative case (if y > 0 ... else ...).
So that means you can actually use iterate instead of go as long as you for iterate n f x find good values:
What should n be? (Something to count down.)
What should f be? (Something that performs the stepwise calculation.)
What should x be? (The thing that gets applied in the stepwise calculation.)
(...all in terms of iterate; they may be called something else in the context of the power function and the arguments it has in scope.)
I'll use a simple example for what I'm trying to do.
Say I have the list:
nums = []
Now I have the function:
allNums n = nums.append(n)
So if I run the function:
allNums 6
The list nums should have the values
[6]
I know nums.append doesn't work, but what code could replace that.
Simple Answer:
You can't do that. Haskell is a pure, functional language, that means:
A function does not have any side effect.
A function does always return the same result when called with the same parameters.
A function may or may not be called, but you don't have to care about that. If it wasn't called, it wasn't needed, but because the function does not have any side effects, you won't find out.
Complex answer:
You could use the State Monad to implement something that behaves a bit like this, but this is probably out of reach for you yet.
I'm suggesting to use an infinite list instead of appending to global variable.
It's true haskell is pure functional. But also it's lazy. Every part of data is not calculated until is really needed. It also applies to collections. So you could even define a collection with elements based on previous elements of same collection.
Consider following code:
isPrime n = all (\p -> (n `mod` p) /= 0 ) $ takeWhile (\p ->p * p <= n) primes
primes = 2 : ( filter isPrime $ iterate (+1) 3 )
main = putStrLn $ show $ take 100 primes
definition of isPrime is trivia when primes list is defined. It takes pack of primes which is less or equivalent to square root of examining number
takeWhile (\p ->p * p <= n) primes
then it checks if number have only non-zero remainders in division by all of these numbers
all (\p -> (n `mod` p) /= 0 )
the $ here is an application operator
Next using this definition we taking all numbers starting from 3:
iterate (+1) 3
And filtering primes from them.
filter isPrime
Then we just prepending the first prime to it:
primes = 2 : ( ... )
So primes becomes an infinite self-referred list.
You may ask: why we prepending 2 and just no starting filtering numbers from it like:
primes = filter isPrime $ iterate (+1) 2
You could check this leads to uncomputable expression because the isPrime function needs at least one known member of primes to apply the takeWhile to it.
As you can see primes is well defined and immutable while it could have as many elements as you'll need in your logic.
i m a newbie to haskell, currently i need a function 'f' which, given two integers, returns the number of prime numbers in between them (i.e., greater than the first integer but smaller than the second).
Main> f 2 4
1
Main> f 2 10
3
here is my code so far, but it dosent work. any suggestions? thanks..
f :: Int -> Int -> Int
f x y
| x < y = length [ n | n <- [x..y], y 'mod' n == 0]
| otherwise = 0
Judging from your example, you want the number of primes in the open interval (x,y), which in Haskell is denoted [x+1 .. y-1].
Your primality testing is flawed; you're testing for factors of y.
To use a function name as an infix operator, use backticks (`), not single quotes (').
Try this instead:
-- note: no need for the otherwise, since [x..y] == [] if x>y
nPrimes a b = length $ filter isPrime [a+1 .. b-1]
Exercise for the reader: implement isPrime. Note that it only takes one argument.
Look at what your list comprehension does.
n <- [x..y]
Draw n from a list ranging from x to y.
y `mod` n == 0
Only select those n which evenly divide y.
length (...)
Find how many such n there are.
What your code currently does is find out how many of the numbers between x and y (inclusive) are factors of y. So if you do f 2 4, the list will be [2, 4] (the numbers that evenly divide 4), and the length of that is 2. If you do f 2 10, the list will be `[2, 5, 10] (the numbers that evenly divide 10), and the length of that is 3.
It is important to try to understand for yourself why your code doesn't work. In this case, it's simply the wrong algorithm. For algorithms that find whether a number is prime, among many other sources, you can check the wikipedia article: Primality test.
I you want to work with large intervals, then it might be a better idea to compute a list of primes once (instead of doing a isPrime test for every number):
primes = -- A list with all prime numbers
candidates = [a+1 .. b-1]
myprimes = intersectSortedLists candidates primes
nPrimes = length $ myprimes
How would one implement a list of prime numbers in Haskell so that they could be retrieved lazily?
I am new to Haskell, and would like to learn about practical uses of the lazy evaluation functionality.
Here's a short Haskell function that enumerates primes from Literate Programs:
primes :: [Integer]
primes = sieve [2..]
where
sieve (p:xs) = p : sieve [x|x <- xs, x `mod` p > 0]
Apparently, this is not the Sieve of Eratosthenes (thanks, Landei). I think it's still an instructive example that shows you can write very elegant, short code in Haskell and that shows how the choice of the wrong data structure can badly hurt efficiency.
There are a number of solutions for lazy generation of prime sequences right in the haskell wiki. The first and simplest is the Postponed Turner sieve: (old revision ... NB)
primes :: [Integer]
primes = 2: 3: sieve (tail primes) [5,7..]
where
sieve (p:ps) xs = h ++ sieve ps [x | x <- t, x `rem` p /= 0]
-- or: filter ((/=0).(`rem`p)) t
where (h,~(_:t)) = span (< p*p) xs
The accepted answer from #nikie is not very efficient, is gets relatively slow after some thousands, but the answer of #sleepynate is much better. It took me some time to understand it, therefore here is the same code, but just with variables named more clearly:
lazyPrimes :: [Integer]
lazyPrimes = 2: 3: calcNextPrimes (tail lazyPrimes) [5, 7 .. ]
where
calcNextPrimes (p:ps) candidates =
let (smallerSquareP, (_:biggerSquareP)) = span (< p * p) candidates in
smallerSquareP ++ calcNextPrimes ps [c | c <- biggerSquareP, rem c p /= 0]
The main idea is that the candidates for the next primes already contain no numbers that are divisible by any prime less than the first prime given to the function. So that if you call
calcNextPrimes (5:ps) [11,13,17..]
the candidate list contains no number, that is divisible by 2 or 3, that means that the first non-prime candidate will be 5 * 5, cause 5* 2 and 5 * 3 and 5 * 4 are already eliminated. That allows you to take all candidates, that are smaller than the square of 5 and add them straight away to the primes and sieve the rest to eliminate all numbers divisible by 5.
primes = 2 : [x | x <- [3..], all (\y -> x `mod` y /= 0)
(takeWhile (<= (floor . sqrt $ fromIntegral x)) primes)]
With 2 in the list initially, for each integer x greater than 2, check if for all y in primes such that y <= sqrt(x), x mod y != 0 holds, which means x has no other factors except 1 and itself.
I am doing Project Euler question 55 on Lychrel numbers where the aim is to find the number of Lychrel numbers below 10,000 within 50 iterations. I came up with this:
revAdd n = (read $ reverse $ show n) + n
lychrel n | length xs == 50 = error "False"
| ((reverse $ show (revAdd n)) == (show (revAdd n))) = True
| otherwise = (lychrel (revadd n) ) : xs
answer = length [ x | x <- [1..10000] , lychrel x == True]
But I don't know how to define xs as the list of previous iterations upon n, which are when n is not a palindrome. How would I do this, and secondly would this work?
It becomes much easier if you separate your concerns into distinct steps.
Define a function that sums a number and its reverse.
Use iterate to repeat your number, starting from x.
Use take to limit your iteration to 50 steps.
Use all with a predicate to determine if any of these steps results in a palindrome.
You need to pass the list of iterations (or just the number of iterations) in as a parameter to lychrel, starting with [] in the call from answer and adding to it in the recursive call in the otherwise case. Look up "accumulating parameters" for more general background on this technique.