Sieve of Euler space complexity in Haskell - haskell

I was given 2 different algorithms written in Haskell aimed to generate the first k primes. As the title suggests, they are the Sieve of Eratoshenes and Euler.
I am trying to understand why Euler implementation uses so much memory. What I thought so far is that the number of streams generated explodes quickly saturating the memory but from what I have understood they should be equal to 2k - 1 where k is the index of the prime we want.
So there should be other major problems.
I tried running the code via GHC's Debugger and it shows that much of the memory allocated is from the minus function so I think streams are definitely part of the problem.
Here minus removes from tcs every multiple of p starting from p*p which is coprime to every prime found so far (except p) and finally generates a new stream passed to the next recursive call of eulerSieve.
minus :: [Int] -> [Int] -> [Int]
minus xs#(x:txs) ys#(y:tys)
| x < y = x : minus txs ys
| otherwise = minus txs tys
eulerSieve :: [Int] -> [Int]
eulerSieve cs#(p:tcs) = p:eulerSieve (minus tcs (map (p*) cs))
Reading here I found that the space is bounded by O(k^2) but it doesn't explain why accurately.
Any suggestion would be appreciated.

Related

How to make this Haskell program run faster

So I've been trying to learn Haskell by solving some problems on Codeforce.
And I am getting a lot of TLE (Time Limit Exceed) even though I think my time complexity is optimal.
My question is: is the way I wrote this program that makes it slow?
For example, here is the problem.
Basically the answer is to find an for a given n , where
an = 2*an-1 + D(n) and D(n) = the difference of the number of divisors between n and n-1.
(update: the top limit for n is 106).
Below is my program.
import qualified Data.Map.Strict as Map
main = do t <- read <$> getLine
putStrLn . show $ solve t
solve :: Integer -> Integer
solve 0 = 1
solve 1 = 1
solve n = (2*(solve (n-1)) + (fact n) - (fact (n-1))) `mod` 998244353
where fact n = foldl (\s -> \t -> s*(snd t + 1)) 1 (Map.toList . factorization $ n)
--the number of divisors of a number
--copied from Internet,infinite prime list
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]
where (h,~(_:t)) = span (< p*p) xs
--make factorization of a number
factorization :: Integer -> Map.Map Integer Integer
factorization 1 = Map.fromList []
factorization x = Map.insertWith (+) factor 1 (factorization (x `div` factor))
where factor = head $ filter (\s -> (x `mod` s) == 0) ls
ls = primes
This program failed to solve in the time limit.
So could anyone point me out where did I do wrong and how to fix it?
Or it just impossible to solve this problem using Haskell in time limit?
There are many ways in which your time complexity is not optimal. The most obvious one is a prime finder using trial division instead of, e.g., a sieve. Maybe it's fine because you only compute the primes once, but it does not inspire confidence.
factorization also has at least one glaring problem. Consider factoring a number like 78893012641, whose prime factorization is 280879^2. You will search each prime number up to 280879: expensive, but pretty much unavoidable. However, at this point you divide by 280879 and then try to factorize 280879, starting from 2 and scanning all the small primes again even though you just found out none of them are a factor!
As Li-yao Xia says in a comment, I would also be suspicious of the multiplication of very large Integers before taking their modulus, instead of taking a modulus after each multiplication.
You haven't copied the right piece of code from the "Internet". You should've instead copied primesTMWE for the primes list, but more importantly, primeFactors for the factorization algorithm.
Your foldl based calculation of the number of divisors from a number's factorization is perfectly fine, except perhaps foldl' should be used instead.
Notice that both solve n and solve (n-1) calculate fact (n-1), so better precalculate all of them..... perhaps a better algorithm exists to find the numbers of divisors for all numbers from 1 to n than calculating it for each number separately.
I suspect even with the right algorithms (which I link above) it's going to be tough, time-wise, if you're going to factorize each number independently (O(n) numbers, O(n1/2)) time to factorize each... each prime, at least).
Perhaps the thing to try here is the smallest-factor sieve which can be built in O(n log log n) time as usual with the sieve of Eratosthenes, and once it's built it lets you find the factorization of each number in O(log log n) time (it's the average number of prime factors for a number). It will have to be built up to n though (you can special-case the evens to halve the space requirements of course; or 6-coprimes to save another 1/6th). Probably as an STUArray (that link is an example; better codes can be found here on SO).
The smallest-factor sieve is just like the sieve of Eratosthenes, except it uses the smallest factor, not just a Boolean, as a mark.
To find a number's factorization then we just repeatedly delete by a number's smallest factor, n / sf(n) =: n1, repeating for n1 / sf(n1) =: n2, then n2, etc. until we hit a prime (which is any number which has itself as the smallest factor).
Since you only use those factors to calculate the number's total number of divisors, you can fuse the two calculations together into one joined loop, for extra efficiency.

Lazy Catalan Numbers in Haskell

How might I go about efficiently generating an infinite list of Catalan numbers? What I have now works reasonably quickly, but it seems to me that there should be a better way.
c 1 = 1
c n = sum (zipWith (*) xs (reverse xs)) : xs
where xs = c (n-1)
catalan = map (head . c) [1..]
I made an attempt at using fix instead, but the lambda isn't lazy enough for the computation to terminate:
catalan = fix (\xs -> xs ++ [zipWith (*) xs (reverse xs)])
I realize (++) isn't ideal
Does such a better way exist? Can that function be made sufficiently lazy? There's an explicit formula for the nth, I know, but I'd rather avoid it.
The Catalan numbers [wiki] can be defined inductively with:
C0 = 1 and Cn+1=(4n+2)×Cn/(n+2).
So we can implement this as:
catalan :: Integral i => [i]
catalan = xs
where xs = 1 : zipWith f [0..] xs
f n cn = div ((4*n+2) * cn) (n+2)
For example:
Prelude> take 10 catalan
[1,1,2,5,14,42,132,429,1430,4862]
I'm guessing you're looking for a lazy, infinite, self-referential list of all the Catalan numbers using one of the basic recurrence relations. That's a common thing to do with the Fibonacci numbers after all. But it would help to specify the recurrence relation you mean, if you want answers to your specific question. I'm guessing this is the one you mean:
cat :: Integer -> Integer
cat 1 = 1
cat n = sum [ cat i * cat (n - i) | i <- [1 .. n - 1] ]
If so, the conversion to a self-referential form looks like this:
import Data.List (inits)
cats :: [Integer]
cats = 1 : [ sum (zipWith (*) pre (reverse pre)) | pre <- tail (inits cats) ]
This is quite a lot more complex than the fibonacci examples, because the recurrence refers to all previous entries in the list, not just a fixed small number of the most recent. Using inits from Data.List is the easiest way to get the prefix at each position. I used tail there because its first result is the empty list, and that's not helpful here. The rest is a straight-forward rewrite of the recurrence relation that I don't have much to say about. Except...
It's going to perform pretty badly. I mean, it's better than the exponential recursive calls of my cat function, but there's a lot of list manipulation going on that's allocating and then throwing away a lot of memory cells. That recurrence relation is not a very good fit for the recursive structure of the list data type. You can explore a lot of ways to make it more efficient, but they'll all be pretty bad in the end. For this particular case, going to a closed-form solution is the way to go if you want performance.
Apparently, what you wanted is
> cats = 1 : unfoldr (\ fx -> let x = sum $ zipWith (*) fx cats in Just (x, x:fx)) [1]
> take 10 cats
[1,1,2,5,14,42,132,429,1430,4862]
This avoids the repeated reversing of the prefixes (as in the linked answer), by unfolding with the state being a reversed prefix while consing onto the state as well as producing the next element.
The non-reversed prefix we don't have to maintain, as zipping the reversed prefix with the catalans list itself takes care of the catalans prefix's length.
You did say you wanted to avoid the direct formula.
The Catalan numbers are best understood by their generating function, which satisfies the relation
f(t) = 1 + t f(t)^2
This can be expressed in Haskell as
f :: [Int]
f = 1 : convolve f f
for a suitable definition of convolve. It is helpful to factor out convolve, for many other counting problems take this form. For example, a generalized Catalan number enumerates ternary trees, and its generating function satisfies the relation
g(t) = 1 + t g(t)^3
which can be expressed in Haskell as
g :: [Int]
g = 1 : convolve g (convolve g g)
convolve can be written using Haskell primitives as
convolve :: [Int] -> [Int] -> [Int]
convolve xs = map (sum . zipWith (*) xs) . tail . scanl (flip (:)) []
For these two examples and many other special cases, there are formulas that are quicker to evaluate. convolve is however more general, and cognitively more efficient. In a typical scenario, one has understood a counting problem in terms of a polynomial relation on its generating function, and now wants to compute some numbers in order to look them up in The On-Line Encyclopedia of Integer Sequences. One wants to get in and out, indifferent to complexity. What language will be least fuss?
If one has seen the iconic Haskell definition for the Fibonacci numbers
fibs :: [Int]
fibs = 0 : 1 : zipWith (+) fibs (tail fibs)
then one imagines there must be a similar idiom for products of generating functions. That search is what brought me here.

Performance of predicate on the length of a list

I have read (and also reasoned) that calculating the length of a list is not good for performance in Haskell. However, i have long lists in my program and my requirement is to find that if length is greater than or less than some number X.
Is their already something in build in Haskell for these kind of predicates ? or i have to resort to manual looping.
On vanilla lists, you can check this using drop:
cmpLen :: Int -> [a] -> Ordering
cmpLen n xs
| n < 0 = GT
| otherwise = case drop (n-1) xs of
[] -> GT
[_] -> EQ
_ -> LT
However, this still takes as long as the value (not size, as is typical of asymptotic analysis!) of n. If you intend to do this often, you can take a cue from Okasaki and build a new structure that caches the operation you want to be efficient. I have wanted this a few times before, and found the following sort of interface convenient in those cases:
type LenList a = (Sum Word, [a])
singleton x = (1, [x])
cons x = (singleton x<>)
length = getSum . fst
elems = snd
Note that, since LenList a is already a Monoid, you get some of the usual operations for free, e.g. there is an empty LenList a named mempty, and concatenation is given by (<>). Some operations (notably the ones that produce infinite lists) will not be implementable for this type. However, you pay an O(1) price on each construction operation to make asking for the length of one of these O(1), which can be a nice tradeoff in many situations.

Prime Factoring Function in Haskell

I am trying to make a function that will display a number's prime factors with a list (infinite) that I give it. Here is what I have so far:
-- Here is a much more efficient (but harder to understand) version of primes.
-- Try "take 100 primes" as an example (or even more if you like)
primes = 2 : primesFrom3 where
primesFrom3 = sieve [3,5..] 9 primesFrom3
sieve (x:xs) b ~ps#(p:q:_)
| x < b = x : sieve xs b ps
| otherwise = sieve [x | x <- xs, rem x p /= 0] (q^2) (tail ps)
-- Write a function that factors its first argument using the (infinite)
-- list of available factors given in its second argument
-- (using rem x p /= 0 to check divisibility)
primeFactsWith :: Integer -> [Integer] -> [Integer]
primeFactsWith n (p:ps) = if (rem n p /= 0) then
(primeFactsWith n ps)
else (primeFactsWith p ps)
The top half was not written by me and works just fine. I am trying to get the second half to work, but it isn't. Read the comments in the code to better understand exactly what I am trying to do. Thanks! Oh and please don't just spout the answer. Give me some hints on how to do it and maybe what is wrong.
What's wrong
The problem is that you do a recursive call in both branches, therefore the function will never stop.
Some Hints
To build a recursive list-producing function, you'll need two branches or cases:
Base case no recursive call, this stops the recursion and returns the final part of the result.
Recursive case here you modify the parameters of the function and call it again with the modified parameters, possibly also returning a part of the result.
You need two sub branches at the recursive branch. One if you've found a prime factor, and another if the current number is no prime factor.
Here is a skeleton, you need to fill in the parts in the <> brackets.
primeFactsWith :: Integer -> [Integer] -> [Integer]
primeFactsWith n (p:ps) = if <halt condition> then
<final result>
else if (rem n p /= 0) then
<not a factor - recursive call 1>
else
<found a factor - return it,
and make recursive call 2>
If you have found a prime factor, you can divide the number by it, to get a smaller number, without that factor. To perform integer division Haskell provides a function named div.
If you reach the number 1, you have generated all prime factors and you can stop. The final part of a prime factors list, that comes after all its factors, is an empty list.
You can drop any prime from your infinite list if you no longer need it, but be aware that a number could contain a prime several times in the factors list. If you want to drop p you can just use ps, from the pattern; if you want to keep p you must use (p:ps).
The cons operator (:) can be used to build a list. You can use it to return one number of the result list, and use a recursive call to find the remaining numbers, e.g.
x : foo y z
I hope that helps, if you have any questions don't hesitate to ask.
Here's a hint.
So you're recursing, which is good.
In one branch you keep looking for factors of n. In the other branch you seem to look for the factors of p, which is a bit weird, but whatevs.
Where do you return the factors of n you've found?

Solving Google Code Jam's "Minimum Scalar Product" in Haskell

In preparation for the upcoming Google Code Jam, I've started working on some problems. Here's one of the practice problems I've tried:
http://code.google.com/codejam/contest/32016/dashboard#s=p0
And here's the gist of my current Haskell solution:
{-
- Problem URL: http://code.google.com/codejam/contest/32016/dashboard#s=p0
-
- solve takes as input a list of strings for a particular case
- and returns a string representation of its solution.
-}
import Data.List
solve :: [String] -> String
solve input = show $ minimum options
where (l1:l2:l3:_) = input
n = read l1 :: Int
v1 = parseVector l2 n
v2 = parseVector l3 n
pairs = [(a,b) | a <- permutations v1, b <- permutations v2]
options = map scalar pairs
parseVector :: String -> Int -> [Int]
parseVector line n = map read $ take n $ (words line) :: [Int]
scalar :: ([Int],[Int]) -> Int
scalar (v1,v2) = sum $ zipWith (*) v1 v2
This works with the sample input provided, but dies on the small input to an out of memory error. Increasing the max heap size appears to do nothing but let it run indefinitely.
My main question is how to go about optimizing this so that it will actually return a solution, other than passing in the -O flag to ghc, which I've already done.
Improving your algorithm is the most important thing. Currently, you permute both lists, giving a total of (n!)^2 options to check. You need only permute one of the lists. That should not only reduce the time complexity but also the space usage drastically.
And make sure the minimum gets replaced by the strict minimum (as it should, with optimisations, since you're taking the minimum of a list of Ints, compile with -ddump-rule-firings and check for "minimumInt"). If it isn't, use foldl1' min instead of minimum.
I just checked:
Large dataset
T = 10
100 ≤ n ≤ 800
-100000 ≤ xi, yi ≤ 100000
For that, you need a dramatically better algorithm. 100! is about 9.3 * 10157, the universe will long have ceased to exist before you have checked a measurable portion of all the permutations of 100 elements. You must construct the solving permutations by looking at the data. To find out what the solutions would look like, investigate some small inputs and what permutations realise the minimum scalar product for those (having a look at the Cauchy-Bun'akovskiy-Schwarz inequality would also not hurt).
The solution I came up with:
{-
- Problem URL: http://code.google.com/codejam/contest/32016/dashboard#s=p0
-
- solve takes as input a list of strings for a particular case
- and returns a string representation of its solution.
-}
import Data.List
solve :: [String] -> String
solve input = show result
where (l1:l2:l3:_) = input
n = read l1 :: Int
v1 = parseVector l2 n
v2 = parseVector l3 n
result = scalar (sort v1) (reverse $ sort v2)
parseVector :: String -> Int -> [Integer]
parseVector line n = map read $ take n $ (words line) :: [Integer]
scalar :: [Integer] -> [Integer] -> Integer
scalar v1 v2 = sum $ zipWith (*) v1 v2 :: Integer
This seems to give the right answer and is orders of magnitude faster. The trick I guess is to not take the word "permutation" at face value when reading problems like this.
according to me(my solution work), you really don't need to permute,
you really need to sort both list,then you require queue and stack,
so how it work
ex:-
input
1 3 -5
-2 1 4
sort
-5 1 3
-2 1 4
then -2*3+4*-5+1*1=-6
ex2:-
so you see
-ve number multiply with most +ve or least -ve
+ve number multiply with most -ve or least +ve
My main question is how to go about optimizing this so that it will actually return a solution, other than passing in the -O flag to ghc, which I've already done.
I think you should reconsider your approach. I think this practice problem is not so much about coding skills but more about problem solving. Trying out all possible permutations is the brute force way and I think you have a good feeling now why this brute force strategy does not work in this case ;). It really can be done in 3 lines of code when you use stl algorithms (not including in- and output of course).
Actually Madan Ram already gave some kind of solution. However, in case you will ever be given such a problem in an interview, you will also have to know why it works for all cases (not just for a number of examples). So my advice is to take a pen and a piece of paper and do some examples by hand, then you will find out how to do it.
SPOILER ALERT
Its hard to give a hint without spoiling to much, but as the solution has been posted already... Try to start simple. Which element in the first vector has the biggest contribution to the scalar product? To which element from the second vector do you have to mulitply this one to get in total the smallest contribution to the scalar product?

Resources