I need to implement a recursive function that returns 1 if the number is prime or 0 otherwise. The homework problem says that I can't use '%' mod. Haskell should be something like this... I'm not sure.
isprime x = prime(x sqrt(x))
prime x i = | i==1 = 1
| mod(x i)==0 = 0
| otherwise = prime(x i-1)
mod num div | num<div = n
| otherwise = mod(num-div div)
I tested an algorithm in C because I don't have a Haskell compiler on my Mac, but there's something wrong because it's returning false positive on primes-1. idk why.
int main (int argc, const char * argv[]){
int a=0,b=31;
printf("\n Prime numbers between %d and %d \n",a,b);
for(int a=0; a<=b; a++){
if(isPrime(a)==0){
printf("%d, ",a);
}
}
return 0;
}
int isPrime(int x){
return prime(x, sqrt(x));
}
int prime(int x, int i){
if(i==0){
return 0;
}
else if(mod(x,i)==1){
return 1;
}
else{
return prime(x, i-1);
}
}
int mod(int num, int div){
if(num<div) return num;
else return mod(num-div, div);
}
The algorithm is returning this:
Prime numbers between 0 and 31
0, 1, 2, 3, 4, 6, 8, 12, 14, 18, 20, 24, 30,
Program ended with exit code: 0
Your basic idea is fine. In Haskell you can use lists instead of iteration. Here's what you need to look into:
Install and play with ghci.
If you have no idea how to do anything in Haskell, visit Learn You a Haskell for Great Good http://learnyouahaskell.com/
List comprehensions. Lean what [n^2 | n <- [1..10]] means and play with similar lists.
Look up functions like sqrt on hoogle http://www.haskell.org/hoogle/
Because Haskell is statically typed you will need to convert some numerical types between Integer and Float. Look up Float -> Integer and Integer -> Float when you do. DON'T use unsafeCoerce - it's unsafe and will break things badly.
Use hoogle to look up [Bool] -> Bool. Why did I suggest that? How would [Bool] help, and how would you make one anyway? (Revise list comprehension again.)
Come back with more specific questions once you've found out more and had a go.
Always start your assignments early, especially if you've missed classes!
You were set this homework not because the department was stuck for a way of deciding whether 102659473841923461 is prime, but because they want you to learn some Haskell. Try not to try to solve the problem without doing the learning - it'll only make the next assignment even harder! (This is why I've resisted the temptation to translate the "pseudocode" in another answer into Haskell.)
(apparently, there's a new policy regarding homework, viz. "If you don't want a fully vetted, complete and testable answer, Stack Overflow is not the place to ask - by Tim Post", so here goes).
Basically, your code is almost correct (1 is not a prime), sans some syntax issues.
isprime x = prime x (floor $ sqrt $ fromIntegral x) where
prime x i | i==1 && x > 1 = 1
| x == i*div x i = 0
| otherwise = prime x (i-1)
-- mod x i = x - i*div x i
-- mod x i == 0 = x == i*div x i
fromIntegral is just some adaptor which lets us use an Integral value as an argument to sqrt which expects a Floating argument. Try using :i sqrt or :i Integral etc. at the GHCi prompt (also read some documentation google around).
But algorithmically there's place for improvement. First of all, it's much better to try out the divisors in the other direction, from 2 up to the number's sqrt, because any given number is more likely to have a smaller factor than a larger one. Second, after trying out 2, there's no need to try out any other even number as a possible divisor. This gives us
isprime x | x == 2 = 1
| x < 2 || even x = 0
| otherwise = go 3
where
r = floor $ sqrt $ fromIntegral x
go i | i > r = 1
| x == i*div x i = 0 -- really, | rem x i == 0 = 0
| otherwise = go (i+2)
This would normally be written down using Bools, and a higher-order function like and which captures the recursions and testing pattern (so it is not recursive anymore):
isprime x = if isPrime x then 1 else 0
isPrime x = x==2 || x>2 && odd x &&
and [rem x d /= 0 | d <- [3,5..floor $ sqrt $ fromIntegral x]]
There's some redundancy in there still: after we've tested by 3, there's no need to test by any of its multiples too (just like we did with 2 and evens). We really just need to test by prime factors:
isPrime x = x>1 && and
[rem x d /= 0 | d <- takeWhile (<= (floor $ sqrt $ fromIntegral x)) primes]
primes = filter isPrime [2..]
= 2 : filter isPrime ([3..] `minus` [4,6..])
= 2 : filter isPrime [3,5..]
= 2 : 3 : filter isPrime ([5,7..] `minus` [9,15..])
= 2 : 3 : 5 : filter isPrime (([7,9..]`minus`[9,15..])`minus`[25,35..])
...........
Here we see the emergence of the sieve of Eratosthenes, P = {3,5, ...} \ U {{p2, p2 + 2p, ...} | p in P} (w/out the 2).
see also:
http://en.wikipedia.org/wiki/Haskell_features#Prime_numbers
http://en.wikipedia.org/wiki/Sieve_of_Eratosthenes
http://www.haskell.org/haskellwiki/Prime_numbers
I don't know Haskell, and I don't want to hand you the answer, but I can offer a method.
if you check all the numbers from 2 to sqrt(n), and none of them are factors of n, then n is prime.
So maybe a function call with the following pseudo code might work:
def isPrime(n):
return isPrimeHelper(n,sqrt(n))
def isPrimeHelper(n,counter):
if counter == 1 return True
if n % counter == 0 return False
else return isPrime(n,counter-1)
Related
The task is to generate list with numbers, whose digits are only 2,4,6.
Example:[2,4,6,22,24,26,42,44,46,62,64,66,222,224,226,...]
I have already solved this task via brute force:
numberHasOnly246 :: Integer -> Bool
numberHasOnly246 0 = False
numberHasOnly246 n = result
where
result = helper True (abs n)
helper :: Bool -> Integer -> Bool
helper result n
| (div n 10 == 0) = condition && result
| (div n 10 > 0) = helper (condition && result) (div n 10)
where
condition = mod n 10 == 4 || mod n 10 == 6 || mod n 10 == 2
series246 :: [Integer]
series246 = numbers[1..]
where
numbers(e : ls) = e : (numbers [ x | x <- ls, (numberHasOnly246 x == True)])
But it seems that this solution is too slow.
Also, I've read, that there is tying the knot method for generating infinite lists in Haskell, but here I cannot find how to solve it via tying the knot. Is this method suitable here?
Instead of a generate-and-test approach, you can only generate numbers that are valid.
For a single digit this is thus:
digits :: [Int]
digits = [2, 4, 6]
for numbers, we can make use of recursion here:
numbers = [ 10*t + d | t <- (0:numbers), d <- digits ]
Here t is thus the values we multiply with 10, and we start with 0. d are the digits that we then can append. This thus gives us:
Prelude> numbers
[2,4,6,22,24,26,42,44,46,62,64,66,222,224,226,242,244,246,262,264,266,422,424,426,442, …
I want to refresh a variable value, each time I make a recursion of a function. To make it simple I will give you an example.
Lets say we give to a function a number (n) and it will return the biggest mod it can have, with numbers smaller of itself.
{- Examples:
n=5 `mod` 5
n=5 `mod` 4
n=5 `mod` 3
n=5 `mod` 2
n=5 `mod` 1
-}
example :: Integer -> Integer
example n
| n `mod` ... > !The biggest `mod` it found so far! && ... > 0
= !Then the biggest `mod` so far will change its value.
| ... = 0 !The number we divide goes 0 then end! = 0
Where ... = recursion ( I think)
I don't know how I can describe it better. If you could help me it would be great. :)
You can write it as you described:
example :: Integer -> Integer
example n = biggestRemainder (abs n) 0
where
biggestRemainder 0 biggestRemainderSoFar = biggestRemainderSoFar
biggestRemainder divisor biggestRemainderSoFar = biggestRemainder (divisor - 1) newBiggestRemainder
where
thisRemainder = n `mod` divisor
newBiggestRemainder = case thisRemainder > biggestRemainderSoFar of
True -> thisRemainder
False -> biggestRemainderSoFar
This function can also be written more easily as
example2 :: Integer -> Integer
example2 0 = 0
example2 n = maximum $ map (n `mod`) [1..(abs n)]
I am trying to learn Haskell and I am stuck at a problem with recursion. What i need to do is find wether a number is prime or not. This is my attempt so far. but it does not work. It gives "False" for non prime numbers, but it gets stuck on an infinite loop when the number is prime.
isPrime :: Int -> Bool
isPrime num = primeTest num 2
where
primeTest :: Int -> Int -> Bool
primeTest num x
| x == num = True
| num `mod` x == 0 = False
| otherwise = primeTest num (x + 1)
where
x = 2
You dont need
where
x = 2
This is why it is running into an infinite loop. For example, Consider the input 2, num mod x will return 0, so it will return False. Consider input 5, num mod x will return 1 (since x is 1 in this case). So, it goes to the otherwise part, where primeTest num (x + 1) is called with assigning x = 2. So, always this loop will run infinitely, with the x value 3.
The where x=2 at the end causes every instance of x after primeTest num x to be 2, regardless of the value that was passed to primeTest in the x "slot." Get rid of the where x=2.
Consider the modified Euler problem #4 -- "Find the maximum palindromic number which is a product of two numbers between 100 and 9999."
rev :: Int -> Int
rev x = rev' x 0
rev' :: Int -> Int -> Int
rev' n r
| n == 0 = r
| otherwise = rev' (n `div` 10) (r * 10 + n `mod` 10)
pali :: Int -> Bool
pali x = x == rev x
main :: IO ()
main = print . maximum $ [ x*y | x <- nums, y <- nums, pali (x*y)]
where
nums = [9999,9998..100]
This Haskell solution using -O2 and ghc 7.4.1 takes about 18
seconds.
The similar C solution takes 0.1 second.
So Haskell is 180 times
slower. What's wrong with my solution? I assume that this type of
problems Haskell solves pretty well.
Appendix - analogue C solution:
#define A 100
#define B 9999
int ispali(int n)
{
int n0=n, k=0;
while (n>0) {
k = 10*k + n%10;
n /= 10;
}
return n0 == k;
}
int main(void)
{
int max = 0;
for (int i=B; i>=A; i--)
for (int j=B; j>=A; j--) {
if (i*j > max && ispali(i*j))
max = i*j; }
printf("%d\n", max);
}
The similar C solution
That is a common misconception.
Lists are not loops!
And using lists to emulate loops has performance implications unless the compiler is able to eliminate the list from the code.
If you want to compare apples to apples, write the Haskell structure more or less equivalent to a loop, a tail recursive worker (with strict accumulator, though often the compiler is smart enough to figure out the strictness by itself).
Now let's take a more detailed look. For comparison, the C, compiled with gcc -O3, takes ~0.08 seconds here, the original Haskell, compiled with ghc -O2 takes ~20.3 seconds, with ghc -O2 -fllvm ~19.9 seconds. Pretty terrible.
One mistake in the original code is to use div and mod. The C code uses the equivalent of quot and rem, which map to the machine division instructions and are faster than div and mod. For positive arguments, the semantics are the same, so whenever you know that the arguments are always non-negative, never use div and mod.
Changing that, the running time becomes ~15.4 seconds when compiling with the native code generator, and ~2.9 seconds when compiling with the LLVM backend.
The difference is due to the fact that even the machine division operations are quite slow, and LLVM replaces the division/remainder with a multiply-and-shift operation. Doing the same by hand for the native backend (actually, a slightly better replacement taking advantage of the fact that I know the arguments will always be non-negative) brings its time down to ~2.2 seconds.
We're getting closer, but are still a far cry from the C.
That is due to the lists. The code still builds a list of palindromes (and traverses a list of Ints for the two factors).
Since lists cannot contain unboxed elements, that means there is a lot of boxing and unboxing going on in the code, that takes time.
So let us eliminate the lists, and take a look at the result of translating the C to Haskell:
module Main (main) where
a :: Int
a = 100
b :: Int
b = 9999
ispali :: Int -> Bool
ispali n = go n 0
where
go 0 acc = acc == n
go m acc = go (m `quot` 10) (acc * 10 + (m `rem` 10))
maxpal :: Int
maxpal = go 0 b
where
go mx i
| i < a = mx
| otherwise = go (inner mx b) (i-1)
where
inner m j
| j < a = m
| p > m && ispali p = inner p (j-1)
| otherwise = inner m (j-1)
where
p = i*j
main :: IO ()
main = print maxpal
The nested loop is translated to two nested worker functions, we use an accumulator to store the largest palindrome found so far. Compiled with ghc -O2, that runs in ~0.18 seconds, with ghc -O2 -fllvm it runs in ~0.14 seconds (yes, LLVM is better at optimising loops than the native code generator).
Still not quite there, but a factor of about 2 isn't too bad.
Maybe some find the following where the loop is abstracted out more readable, the generated core is for all intents and purposes identical (modulo a switch of argument order), and the performance of course the same:
module Main (main) where
a :: Int
a = 100
b :: Int
b = 9999
ispali :: Int -> Bool
ispali n = go n 0
where
go 0 acc = acc == n
go m acc = go (m `quot` 10) (acc * 10 + (m `rem` 10))
downto :: Int -> Int -> a -> (a -> Int -> a) -> a
downto high low acc fun = go high acc
where
go i acc
| i < low = acc
| otherwise = go (i-1) (fun acc i)
maxpal :: Int
maxpal = downto b a 0 $ \m i ->
downto b a m $ \mx j ->
let p = i*j
in if mx < p && ispali p then p else mx
main :: IO ()
main = print maxpal
#axblount is at least partly right; the following modification makes the program run almost three times as fast as the original:
maxPalindrome = foldl f 0
where f a x | x > a && pali x = x
| otherwise = a
main :: IO ()
main = print . maxPalindrome $ [x * y | x <- nums, y <- nums]
where nums = [9999,9998..100]
That still leaves a factor 60 slowdown, though.
This is more true to what the C code is doing:
maxpali :: [Int] -> Int
maxpali xs = go xs 0
where
go [] m = m
go (x:xs) m = if x > m && pali(x) then go xs x else go xs m
main :: IO()
main = print . maxpali $ [ x*y | x <- nums, y <- nums ]
where nums = [9999,9998..100]
On my box this takes 2 seconds vs .5 for the C version.
Haskell may be storing that entire list [ x*y | x <- nums, y <- nums, pali (x*y)] where as the C solution calculates the maximum on the fly. I'm not sure about this.
Also the C solution will only calculate ispali if the product beats the previous maximum. I would bet Haskell calculates are palindrome products regardless of whether x*y is a possible max.
It seems to me that you are having a branch prediction problem. In the C code, you have two nested loops and as soon as a palindrome is seen in the inner loop, the rest of the inner loop will be skipped very fast.
The way you feed this list of products instead of the nested loops I am not sure that ghc is doing any of this prediction.
Another way to write this is to use two folds, instead of one fold over the flattened list:
-- foldl g0 0 [x*y | x<-[b-1,b-2..a], y<-[b-1,b-2..a], pali(x*y)] (A)
-- foldl g1 0 [x*y | x<-[b-1,b-2..a], y<-[b-1,b-2..a]] (B)
-- foldl g2 0 [ [x*y | y<-[b-1,b-2..a]] | x<-[b-1,b-2..a]] (C)
maxpal b a = foldl f1 0 [b-1,b-2..a] -- (D)
where
f1 m x = foldl f2 m [b-1,b-2..a]
where
f2 m y | p>m && pali p = p
| otherwise = m
where p = x*y
main = print $ maxpal 10000 100
Seems to run much faster than (B) (as in larsmans's answer), too (only 3x - 4x slower then the following loops-based code). Fusing foldl and enumFromThenTo definitions gets us the "functional loops" code (as in DanielFischer's answer),
maxpal_loops b a = f (b-1) 0 -- (E)
where
f x m | x < a = m
| otherwise = g (b-1) m
where
g y m | y < a = f (x-1) m
| p>m && pali p = g (y-1) p
| otherwise = g (y-1) m
where p = x*y
The (C) variant is very suggestive of further algorithmic improvements (that's outside the scope of the original Q of course) that exploit the hidden order in the lists, destroyed by the flattening:
{- foldl g2 0 [ [x*y | y<-[b-1,b-2..a]] | x<-[b-1,b-2..a]] (C)
foldl g2 0 [ [x*y | y<-[x, x-1..a]] | x<-[b-1,b-2..a]] (C1)
foldl g0 0 [ safehead 0 . filter pali $
[x*y | y<-[x, x-1..a]] | x<-[b-1,b-2..a]] (C2)
fst $ until ... (\(m,s)-> (max m .
safehead 0 . filter pali . takeWhile (> m) $
head s, tail s))
(0,[ [x*y | y<-[x, x-1..a]] | x<-[b-1,b-2..a]]) (C3)
safehead 0 $ filter pali $ mergeAllDescending
[ [x*y | y<-[x, x-1..a]] | x<-[b-1,b-2..a]] (C4)
-}
(C3) can stop as soon as the head x*y in a sub-list is smaller than the currently found maximum. It is what short-cutting functional loops code could achieve, but not (C4), which is guaranteed to find the maximal palindromic number first. Plus, for list-based code its algorithmic nature is more visually apparent, IMO.
I'm working through Project Euler, and a lot of problems involve similar functions, for example calculating lists of primes. I know calculations with Integer are slower than Int so I'd like to write the functions to work with both, depending on the size of the numbers I'm working with.
module Primes
(
isPrime
,prime
,allPrimes
)
where
import Data.List
isPrime :: Int -> Bool
isPrime n
| n == 0 = False
| n == 1 = False
| n < 0 = isPrime (-n)
| n < 4 = True
| n `mod` 2 == 0 = False
| n `mod` 3 == 0 = False
| any ( (==0) . mod n ) [5..h] = False
| otherwise = True
where
h = ( ceiling . sqrt . fromIntegral ) n
allPrimes :: [Int]
allPrimes = [ x | x<- [2..], isPrime x ]
prime :: Int -> Int
prime n = allPrimes !! (n-1)
I know this code isn't generally as optimal as it could be. I'm just interested in how to make the integer types more generic.
Try Integral it should allow support for both Int and Integer
A more general solution to this kind of problem, you could try getting your code to compile without the explicit type declarations. Haskell will assume the most general type possible and you can find out what it was by, for example, loading your file on GHCi and doing a :t myFunctionName