I am trying to write a function in Haskell that allows me to calculate the next 3 prime numbers, given a Intenger N and store the three prime numbers in a sorted list.
The challenge is to do it without import any external module.
Behavior of the function:
*nextPrimes 75 = [79,83,89]
*nextPrimes 64 = [67,71,73]
it should calculate the next 3 prime numbers of an N with 10-digit numbers in less than 2 minutes.
nextPrimes :: Int -> [Int]
nextPrimes n
sorry... but I could not resist...
nextPrimes :: Int -> [Int]
nextPrimes n = let sq = fromIntegral . ceiling . sqrt $ fromIntegral n
pri k = (k,and [ k`mod`x/=0 | x <- [2..sq]])
in take 3 . map fst . filter snd $ map pri [n..]
This works almost instantly, even when we have to count up all the way until sqrt n:
λ> nextPrimes 295084709089
[295084709159,295084709209,295084709273]
Related
I recently started learning Haskell. To train a bit I wanted to try generating the list of prime numbers via self reference using the following code:
main = do
print (smaller_than_sqrt 4 2)
print (smaller_than_sqrt_list 5 [2..])
print ("5")
print (is_prime 5 [2..])
print ("7")
print (is_prime 7 [2..])
print ("9")
print (is_prime 9 [2..])
print ("test")
print (take 5 primes) -- Hangs
-- Integer square root
isqrt :: Int -> Int
isqrt = ceiling . sqrt . fromIntegral
-- Checks if x is smaller than sqrt(p)
smaller_than_sqrt :: Int -> Int -> Bool
smaller_than_sqrt p x = x <= isqrt p
-- Checks if x doesn't divide p
not_divides :: Int -> Int -> Bool
not_divides p x = p `mod` x /= 0
-- Takes in a number and an ordered list of numbers and only keeps the one smaller than sqrt(p)
smaller_than_sqrt_list :: Int -> [Int] -> [Int]
smaller_than_sqrt_list p xs = takeWhile (smaller_than_sqrt p) xs
-- Checks if p is prime by looking at the provided list of numbers and checking that none divides p
is_prime :: Int -> [Int] -> Bool
is_prime p xs = all (not_divides p) (smaller_than_sqrt_list p xs)
-- Works fine: primes = 2 : [ p | p <- [3..], is_prime p [2..]]
-- Doesn't work:
primes = 2 : 3 : [ p | p <- [5..], is_prime p primes]
But for some reason referencing primes inside of primes hangs when running runhaskell and is detected as a loop error when running the compiled binary with ghc.
However I don't really understand why.
Clearly, the first two elements of primes are 2 and 3. What comes after that? The next element of primes is the first element of
[p | p <- [5..], is_prime p primes]
What's that? It could be 5, if is_prime 5 primes, or it could be some larger number. To find out which, we need to evaluate
smaller_than_sqrt_list 5 primes
Which requires
takeWhile (<= isqrt 5) primes
Which requires
takeWhile (<= 3) primes
Well, that's easy enough, it starts with 2:3:..., right? Okay, but what's the next element? We need to look at the third element of primes and see whether it's less or equal to 3. But the third element of primes is what we were trying to calculate to begin with!
The problem is that smaller_than_sqrt 5 3 is still True. To compute whether 5 is a prime, the is_prime 5 primes expands to all (not_divides 5) (takeWhile (smaller_than_sqrt 5) primes), and takeWhile will attempt to iterate primes until the predicate no longer holds. It does hold for the first element (2), it still does hold for the second element (3), will it hold for the next element - wait what's the next element? We're still computing which one that is!
It should be sufficient to use floor instead of ceiling in isqrt, or simpler just
smaller_than_sqrt p x = x * x <= p
I'm looking for a non-recursive implementation of sum of digits (a "cross sum") of a non-negative number like this:
cs :: Int -> Int
cs n = sum digits_of_n where digits_of_n = [ . | ... ]
Basically: How does one get a list of digits from a non-negative whole number using list comprehension only?
A cross sum example: The crossum of 157 is 1 + 5 + 7 = 13
The "usual way" would be extracting the digits from a number recursively using modulo and division, and then summing them up like this:
cs :: Int -> Int
cs n = if n == 0 then 0 else n `mod` 10 + cs (n `div` 10)
I have however difficulty expressing this without recursion and with list comprehension, does anyone have ideas regarding this?
sume n = foldr (+) 0 [ digitToInt c | c <- show n, isDigit c ]
My factorial function seems to work for numbers between 1 and 6, but not for numbers much bigger than 6, for example starting with 21! the results are negative.
I cannot figure out why. Here's my function:
factorial :: Int -> Int
factorial 0 = 1
factorial 1 = 1
factorial num = num * factorial( num - 1)
And here's my binomial coefficient function that calls my factorial function (maybe the problem comes from this one ?):
binomialCoef :: Int -> Int -> Int
binomialCoef n 1 = n
binomialCoef n k = factorial n `div`
((factorial k) * factorial (n - k))
(…) realized my factorial function returns negative numbers starting at 21!, and I can't figure out why.
Because an Int has a fixed number of bits. An Int should at least represent all numbers between -2-29 and 229-1, and on a 64-bit system, typically it will represent numbers between -2-63 and 263-1, but regardless what bounds it represents, it will eventually run out of bits to represent such number.
You can work with Integer to represent arbitrary large numbers:
factorial :: Integer -> Integer
factorial 0 = 1
factorial 1 = 1
factorial num = num * factorial (num-1)
For example:
Prelude> factorial 21
51090942171709440000
Prelude> factorial 22
1124000727777607680000
The binomial coefficient is where ln(gamma) really shines:
Bi(n, k) = n!/(k!*(n-k)!)
Taking the natural log of both sides:
ln(Bi(n, k)) = ln(n!) - ln(k!) - ln((n-k)!)
But
gamma(n) = (n-1)!
Or
gamma(n+1) = n!
Substituting
ln(Bi(n, k)) = lngamma(n+1) - lngamma(k+1) -lngamma(n-k+1)
Taking the exponential of both sides gives the final result:
Bi(n, k) = exp(lngamma(n+1) - lngamma(k+1) - lngamma(n-k+1))
There's a Haskell implementation. I haven't looked at it, but it should return a Double instead of an Integer. You won't have overflow problems because of that fact. It'll also be better behaved because you will be subtracting logarithms instead of dividing a large numerator by a large product in the denominator.
Of course best way to avoid integer overflow and wrap-around while calculating a big factorial is not to calculate the factorial in the first place. Instead, since
factorial n = product [1..n]
keeping [1..n] as the representation of the factorial of n is as good -- or even much better -- as calculating the actual number. Postponing an action until absolutely unavoidable we get to pre-optimize it before post-calculating:
bincoef :: Int -> Int -> Int
bincoef n k = factorial n `div`
((factorial k) * factorial (n - k))
= product [1 .. n] `div`
(product [1 .. k] * product [1 .. n-k])
= product [n-k+1 .. n] `div`
product [1 .. k]
= foldl' g 1 $ zip [n, n-1 .. n-k+1] [1 .. k]
where g !acc (a,b) = (acc * a) `div` b
So now,
> mapM_ (\n -> print $ map (bincoef n) [5,10..n]) [20,30..60]
[15504,184756,15504,1]
[142506,30045015,155117520,30045015,142506,1]
[658008,847660528,40225345056,137846528820,40225345056,847660528,658008,1]
[2118760,10272278170,2250829575120,47129212243960,126410606437752,47129212243960,
2250829575120,10272278170,2118760,1]
[5461512,75394027566,53194089192720,4191844505805495,51915437974328292,1182645815
64861424,51915437974328292,4191844505805495,53194089192720,75394027566,5461512,1]
> head . filter (not . snd) $ map (\n -> (n, all (> 0) $ map (bincoef n) [1..n])) [1..]
(62,False)
the Int wrap-around error makes its first appearance at n=62. But it's still working at n=60, and we can see there are more than 16 digits in those numbers, so no Double-based calculation has a hope of working correctly, there.
To get into yet higher ranges still with the Int-based operations only, the next logical step is keeping the lists of integers as originally proposed, or better yet as their prime factorizations which are easy to multiply and divide; but at that point we'd be getting pretty close to re-implementing the bignum arithmetic ourselves, so might as well just use the simple Integer-based code,
bc :: Integer -> Integer -> Integer
bc n k = product [n-k+1 .. n] `div` product [1 .. k]
which "just works".
> bc 600 199
124988418115780688528958442419612410733294315465732363826979722360319899409241320138
666379143574138790334901309769571503484430553926248548697640619977793300443439200
Given an arbitrary number, how can I process each digit of the number individually?
Edit
I've added a basic example of the kind of thing Foo might do.
For example, in C# I might do something like this:
static void Main(string[] args)
{
int number = 1234567890;
string numberAsString = number.ToString();
foreach(char x in numberAsString)
{
string y = x.ToString();
int z = int.Parse(y);
Foo(z);
}
}
void Foo(int n)
{
Console.WriteLine(n*n);
}
Have you heard of div and mod?
You'll probably want to reverse the list of numbers if you want to treat the most significant digit first. Converting the number into a string is an impaired way of doing things.
135 `div` 10 = 13
135 `mod` 10 = 5
Generalize into a function:
digs :: Integral x => x -> [x]
digs 0 = []
digs x = digs (x `div` 10) ++ [x `mod` 10]
Or in reverse:
digs :: Integral x => x -> [x]
digs 0 = []
digs x = x `mod` 10 : digs (x `div` 10)
This treats 0 as having no digits. A simple wrapper function can deal with that special case if you want to.
Note that this solution does not work for negative numbers (the input x must be integral, i.e. a whole number).
digits :: Integer -> [Int]
digits = map (read . (:[])) . show
or you can return it into []:
digits :: Integer -> [Int]
digits = map (read . return) . show
or, with Data.Char.digitToInt:
digits :: Integer -> [Int]
digits = map digitToInt . show
the same as Daniel's really, but point free and uses Int, because a digit shouldn't really exceed maxBound :: Int.
Using the same technique used in your post, you can do:
digits :: Integer -> [Int]
digits n = map (\x -> read [x] :: Int) (show n)
See it in action:
Prelude> digits 123
[1,2,3]
Does that help?
You could also just reuse digits from Hackage.
Textbook unfold
import qualified Data.List as L
digits = reverse . L.unfoldr (\x -> if x == 0 then Nothing else Just (mod x 10, div x 10))
You can use
digits = map (`mod` 10) . reverse . takeWhile (> 0) . iterate (`div` 10)
or for reverse order
rev_digits = map (`mod` 10) . takeWhile (> 0) . iterate (`div` 10)
The iterate part generates an infinite list dividing the argument in every step by 10, so 12345 becomes [12345,1234,123,12,1,0,0..]. The takeWhile part takes only the interesting non-null part of the list. Then we reverse (if we want to) and take the last digit of each number of the list.
I used point-free style here, so you can imagine an invisible argument n on both sides of the "equation". However, if you want to write it that way, you have to substitute the top level . by $:
digits n = map(`mod` 10) $ reverse $ takeWhile (> 0) $ iterate (`div`10) n
Via list comprehension:
import Data.Char
digits :: Integer -> [Integer]
digits n = [toInteger (digitToInt x) | x <- show n]
output:
> digits 1234567890
[1,2,3,4,5,6,7,8,9,0]
I was lazy to write my custom function so I googled it and tbh I was surprised that none of the answers on this website provided a really good solution – high performance and type safe. So here it is, maybe somebody would like to use it. Basically:
It is type safe - it returns a type checked non-empty list of Word8 digits (all the above solutions return a list of numbers, but it cannot happen that we get [] right?)
This one is performance optimized with tail call optimization, fast concatenation and no need to do any reversing of the final values.
It uses special assignment syntax which in connection to -XStrict allows Haskell to fully do strictness analysis and optimize the inner loop.
Enjoy:
{-# LANGUAGE Strict #-}
digits :: Integral a => a -> NonEmpty Word8
digits = go [] where
go s x = loop (head :| s) tail where
head = fromIntegral (x `mod` 10)
tail = x `div` 10
loop s#(r :| rs) = \case
0 -> s
x -> go (r : rs) x
Here's an improvement on an answer above. This avoids the extra 0 at the beginning ( Examples: [0,1,0] for 10, [0,1] for 1 ). Use pattern matching to handle cases where x < 10 differently:
toDigits :: Integer -> [Integer] -- 12 -> [1,2], 0 -> [0], 10 -> [1,0]
toDigits x
| x < 10 = [x]
| otherwise = toDigits (div x 10) ++ [mod x 10]
I would have put this in a reply to that answer, but I don't have the needed reputation points :(
Applicative. Pointfree. Origami. Neat.
Enjoy:
import Data.List
import Data.Tuple
import Data.Bool
import Control.Applicative
digits = unfoldr $ liftA2 (bool Nothing) (Just . swap . (`divMod` 10)) (> 0)
I've been following next steps(based on this comment):
Convert the integer to a string.
Iterate over the string
character-by-character.
Convert each character back to an integer,
while appending it to the end of a list.
toDigits :: Integer -> [Integer]
toDigits a = [(read([m])::Integer) | m<-show(a)]
main = print(toDigits(1234))
For returning a list of [Integer]
import Data.Char
toDigits :: Integer -> [Integer]
toDigits n = map (\x -> toInteger (digitToInt x)) (show n)
The accepted answer is great but fails in cases of negative numbers since mod (-1) 10 evaluates to 9. If you would like this to handle negative numbers properly... which may not be the case the following code will allow for it.
digs :: Int -> [Int]
digs 0 = []
digs x
| x < 0 = digs ((-1) * x)
| x > 0 = digs (div x 10) ++ [mod x 10]
The accepted answer is correct except that it will output an empty list when input is 0, however I believe the output should be [0] when input is zero.
And I don't think it deal with the case when the input is negative. Below is my implementation, which solves the above two problems.
toDigits :: Integer -> [Integer]
toDigits n
| n >=0 && n < 10 = [n]
| n >= 10 = toDigits (n`div`10) ++ [n`mod`10]
| otherwise = error "make sure your input is greater than 0"
I would like to improve upon the answer of Dave Clarke in this page. It boils down to using div and mod on a number and adding their results to a list, only this time it won't appear reversed, nor resort to ++ (which is slower concatenation).
toDigits :: Integer -> [Integer]
toDigits n
| n <= 0 = []
| otherwise = numToDigits (n `mod` 10) (n `div` 10) []
where
numToDigits a 0 l = (a:l)
numToDigits a b l = numToDigits (b `mod` 10) (b `div` 10) (a:l)
This program was a solution to a problem in the CIS 194 course at UPenn that is available right here. You divide the number to find its result as an integer and the remainder as another. You pass them to a function whose third argument is an empty list. The remainder will be added to the list in case the result of division is 0. The function will be called again in case it's another number. The remainders will add in order until the end.
Note: this is for numbers, which means that zeros to the left won't count, and it will allow you to have their digits for further manipulation.
digits = reverse . unfoldr go
where go = uncurry (*>) . (&&&) (guard . (>0)) (Just . swap . (`quotRem` 10))
I tried to keep using tail recursion
toDigits :: Integer -> [Integer]
toDigits x = reverse $ toDigitsRev x
toDigitsRev :: Integer -> [Integer]
toDigitsRev x
| x <= 0 = []
| otherwise = x `rem` 10 : toDigitsRev (x `quot` 10)
So I'm trying to do something and it's almost there I think but I can't solve the last part of it. I have to make a code where someone gives a number (let's make it 22) an I need to find all the palindromic numbers there is when I multiply two numbers smaller than 22:
Find all the palindromic numbers of a*b but a < n && b < n. but they can't repeat themselves.
I got this
calc :: Int -> [Int]
calc n = [a*b|a<-[1..n-1], b<-[a..n-1], a*b>10, reverse(show(a*b))==show(a*b)]
If we do calc 22 the result should be
[11,22,33,44,55,66,77,88,99,171,121,252,272,323]
but I'm getting
[11,22,33,44,55,66,77,88,99,171,121,252,252,272,323]
because 14x18 = 12x21 = 252.
Where did I go wrong?
Well, you have to make sure that every number is unique. There exist multiple representations for all numbers with at least three prime factors (x * y * z = (x * y) * z = x * (y * z)). So one way we could tacke this would be prime factor analysis and reasoning about them. But that's probably an overkill.
Instead, we can use a function that makes sure that every number in our sorted list is unique:
unique :: Eq a => [a] -> [a]
unique (x:y:xs) = if x == y then unique (y:xs) else x : unique (y:xs)
unique xs = xs
(Alternatively, use unique = map head . group)
Now you can use sort from Data.List and you end up with your actual calUniuqe:
calcUnique :: Int -> [Int]
calcUnique = unique . sort . calc
However, we can make calc a lot easier to read if we move the palindrome check into its own function:
isPalindrome :: Int -> Bool
isPalindrome n = n > 10 && reverse n' == n'
where n' = show n
calc :: Int -> [Int]
calc n = [a * b | a <- [1..n-1], b <- [a..n-1], isPalindrome (a * b)]