How to use list comprehension in Haskell? - 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]

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.

Haskell List comprehensions infinite list problem

I'm trying to learn Haskell and comprehension lists but cannot find solution on this:
mylist = [x*y | x <- [1..], y <- [1..]]
After my trials the result is something like this
mylist = [1,2,3,4,5,...]
because in list comprehensions, x takes the value 1,and then y changes value repeatedly.
But my goal is to achieve a different assignment so as to have the following result:
mylist = [1,2,2,4,3,3,6.....]
I mean i want the combinations being mixed and not each one apart,because I have a serious problem to have the suitable result.
I will give a more specific example.
I want a list that will have all numbers of this form:
num = 2^x * 3^y
x and y must take all values >= 0.
My approach is the following:
powers = [2^x * 3^y | x <- [0..], y <- [0..]]
But in this way I only take powers of 3, because x is constantly 0.
I tried this one
multiples = nub (merge (<=) powers2 powers3)
powers3 = [2^x * 3^y | x <- [0..], y <- [0..]]
powers2 = [2^x * 3^y | y <- [0..], x <- [0..]]
so as to merge the different ones but again,the values 6,12,etc. are missing - the result is this:
mylist = [1,2,3,4,8,9,16,27,32,64,81...]
The code that you show,
multiples = nub (merge (<=) powers2 powers3)
powers3 = [2^x * 3^y | x <- [0..], y <- [0..]]
powers2 = [2^x * 3^y | y <- [0..], x <- [0..]]
is equivalent to
powers3 = [2^x * 3^y | x <- [0], y <- [0..]]
= [2^0 * 3^y | y <- [0..]]
= [3^y | y <- [0..]]
powers2 = [2^x * 3^y | y <- [0], x <- [0..]]
= [2^x * 3^0 | x <- [0..]]
= [2^x | x <- [0..]]
so you only produce the powers of 2 and 3, without any mixed multiples. As such, there are guaranteed to be no duplicates in the stream, and the nub was not necessary. And of course it's incomplete.
But let's look at it at another angle. It was proposed in the comments to create a 2D grid out of these numbers:
mults23_2D = [[2^x * 3^y | y <- [0..]] | x <- [0..]]
{-
1 3 9 27 81 ...
2 6 18 54 ...
4 12 36 108 ...
8 24 72 ...
16 ...
.......
-}
Now we're getting somewhere. At least now none are skipped. We just need to understand how to join them into one sorted, increasing stream of numbers. Simple concat of course won't do. We need to merge them in order. A well-known function merge does that, provided the arguments are already ordered, increasing lists.
Each row produced is already in increasing order, but there are infinitely many of them. Never fear, foldr can do it. We define
mults23 = foldr g [] [[2^x * 3^y | y <- [0..]] | x <- [0..]]
-- foldr g [] [a,b,c,...] == a `g` (b `g` (c `g` (....)))
where
g (x:xs) ys =
Here it is a little bit tricky. If we define g = merge, we'll have a run-away recursion, because each merge will want to know the head element of its "right" (second) argument stream.
To prevent that, we produce the leftmost element right away.
x : merge xs ys
And that's that.
Tool use
I needed an infinite Cartesian product function. An infinite function must take the diagonals of a table.
The pair pattern of a diagonal traversal is
0 0 – 0 1, 1 0 – 0 2, 1 1, 2 0 – 0 3, 1 2, 2 1, 3 0
I love the symmetries but the pattern is counting forward with first digit and backward with second which when expressed in an infinite function is
diag2 xs ys = [ (m,n) | i<- [1..], (m,n) <- zip (take i xs) (reverse.take i $ ys) ]
The infinite generation is just to take any amount however large to work with.
What may be important, also is taking a diagonal or triangular number for a complete set.
revt n makes a triangular number from you input. If you want 25 elements revt 25 will return 7. tri 7 will return 28 the parameter for take. revt and tri are
tri n = foldl (+) 1 [2..n]
revt n = floor (sqrt (n*2))
Making and using taket is good until you learn the first 10 or so triangular numbers.
taket n xs = take (tri $ revt n) xs
Now, with some tools in place we apply them (mostly 1) to a problem.
[ 2^a * 3^b | (a,b) <- sort.taket 25 $ diag2 [0..] [0..]]
[1,3,9,27,81,243,729, 2,6,18,54,162,486, 4,12,36,108,324, 8,24,72,216, 16,48,144, 32,96, 64]
And it’s a diagonal. The first group is 7 long, the second is 6 long, the second-to-the-last is 2 long and the last is 1 long. revt 25 is 7. tri 7 is 28 the length of the output list.

How do you find the list of all numbers that are multiples of only powers of 2, 3, and 5? [duplicate]

This question already has answers here:
Generating integers in ascending order using a set of prime numbers
(4 answers)
Closed 4 years ago.
I am trying to generate a list of all multiples which can be represented by the form , where a, b, and c are whole numbers. I tried the following,
[ a * b * c | a <- map (2^) [0..], b <- map (3^) [0..], c <- map (5^) [0..] ]
but it only lists powers of 5 and never goes on to 2 or 3.
Edit: My apologies, it seems that I did not clarify the question enough. What I want is an ordered infinite list, and while I could sort a finite list, I feel as if there may be a solution that is more efficient.
The reason why there are only powers of 5 is that Haskell tries to evaluate every possible c for a = 2^0 and b = 3^0 and only when it is finished it goes for a = 2^0 and b = 3^1.
So this way you can only construct a finite list like this:
[ a * b * c | a <- map (2^) [0..n], b <- map (3^) [0..n], c <- map (5^) [0..n] ]
for a given n.
My first idea was starting from lists of powers of 2, 3 and 5, respectively:
p2 = iterate (2 *) 1
p3 = iterate (3 *) 1
p5 = iterate (5 *) 1
It's also easy to merge two sorted streams:
fuse [] ys = ys
fuse xs [] = xs
fuse xs#(x : xs') ys#(y : ys')
| x <= y = x : fuse xs' ys
| otherwise = y : fuse xs ys'
But then I got stuck because fuse p2 (fuse p3 p5) doesn't do anything useful. It only produces multiples of 2, or 3, or 5, never mixing factors.
I couldn't figure out a purely generative solution, so I added a bit of filtering in the form of a set accumulator. The algorithm (which is quite imperative) is:
Initialize the accumulator to {1}.
Find and remove the smallest element from the accumulator; call it n.
Emit n.
Add {2n, 3n, 5n} to the accumulator.
Go to #2 if you need more elements.
The accumulator is a set because this easily lets me find and extract the smallest element (I'm using it as a priority queue, basically). It also handles duplicates that arise from e.g. computing both 2 * 3 and 3 * 2.
Haskell implementation:
import qualified Data.Set as S
numbers :: [Integer]
numbers = go (S.singleton 1)
where
go acc = case S.deleteFindMin acc of
(n, ns) -> n : go (ns `S.union` S.fromDistinctAscList (map (n *) [2, 3, 5]))
This works, but there are things I don't like about it:
For every element we emit (n : ...), we add up to three new elements to the accumulator (ns `S.union` ... [2, 3, 5]). ("Up to three" because some of them may be duplicates that will be filtered out.)
That means numbers carries around a steadily growing data structure; the more elements we consume from numbers, the bigger the accumulator grows.
In that sense it's not a pure "streaming" algorithm. Even if we ignore the steadily growing numbers themselves, we need more memory and perform more computation the deeper we get into the sequence.
From your code:
[ a * b * c | a <- map (2^) [0..], b <- map (3^) [0..], c <- map (5^) [0..] ]
Since map (5^) [0..] is an infinite list, upon first iterations of a and b, it iterates over the said infinite list, which won't halt. That's why it is stuck at powers of 5.
Here is a solution apart from arithmetics. Note that map (2^) [0..], map (3^) [0..], and map (5^) [0..] are all lists sorted in ascending order. That means the usual merge operation is applicable:
merge [] ys = ys
merge xs [] = xs
merge (x:xs) (y:ys) = if x <= y then x : merge xs (y:ys) else y : merge (x:xs) ys
For convenience, let xs = map (2^) [0..]; let ys = map (3^) [0..]; let zs = map (5^) [0..].
To get multiples of 2 and 3, consider the following organization of said numbers:
1, 2, 4, 8, 16, ...
3, 6, 12, 24, 48, ...
9, 18, 36, 72, 144, ...
...
Judging by this, you might hope the following works:
let xys = foldr (merge . flip fmap xs . (*)) [] ys
But this doesn't work, because from the organization above, merge doesn't know which row contains the resulting head element, infinitely leaving it unevaluated. We know that the upper row contains said head element, so with following little tweak, it finally works:
let xys = foldr ((\(m:ms) ns -> m : merge ms ns) . flip fmap xs . (*)) [] ys
Do the same against zs, and here comes the desired list:
let xyzs = foldr ((\(m:ms) ns -> m : merge ms ns) . flip fmap xys . (*)) [] zs
Full code in summary:
merge [] ys = ys
merge xs [] = xs
merge (x:xs) (y:ys) = if x <= y then x : merge xs (y:ys) else y : merge (x:xs) ys
xyzs = let
xs = map (2^) [0..]
ys = map (3^) [0..]
zs = map (5^) [0..]
xys = foldr ((\(m:ms) ns -> m : merge ms ns) . flip fmap xs . (*)) [] ys
in foldr ((\(m:ms) ns -> m : merge ms ns) . flip fmap xys . (*)) [] zs
but it only lists powers of 5 and never goes on to 2 or 3.
Addressing only this bit.
To calculate numbers 2^a*3^0b*5^c you tried generating the triples (a,b,c), but got stuck producing those of the form (0,0,c). Which is why your numbers are all of the form 2^0*3^0*5^c, i.e. only powers of 5.
It's easier if you start with pairs. To produce all pairs (a,b) you can work along the diagonals of the form,
a+b = k
for each positivek. Each diagonal is easy to define,
diagonal k = [(k-x,x) | x <- [0..k]]
So to produce all pairs you'd just generate all diagonals for k<-[1..]. You want triples (a,b,c) though, but it's similar, just work along the planes,
a+b+c = k
To generate such planes just work along their diagonals,
triagonal k = [(k-x,b,c) | x <- [0..k], (b,c) <- diagonal x]
And there you go. Now just generate all 'triagonals' to get all possible triples,
triples = [triagonal k | k <- [0..]]
The other way to look at it is you wanted the numbers which are only divisible by 2,3 or 5. So check if each number starting from 1 satisfies this condition. If yes it is part of the list.
someList = [x| x<- [1..], isIncluded x]
where isIncluded is the function which decides whether x satisfies the above condition. To do this isIncluded divides the number first by 2 till it can not be divided any further by 2. Then same it does with new divided number for 3 and 5. It at ends there is 1 then we know this number is only divisible by 2,3 or 5 and nothing else.
This may not be the fastest way but still the simplest way.
isIncluded :: Int -> Bool
isIncluded n = if (powRemainder n 2 == 1) then True
else let q = powRemainder n 2
in if (powRemainder q 3 == 1) then True
else let p = powRemainder q 3
in if (powRemainder p 5 == 1) then True else False;
powRemainder is the function which takes number and base and returns the number which can not be further divided by base.
powRemainder :: Int -> Int -> Int
powRemainder 1 b = 1
powRemainder n b = if (n `mod` b) == 0 then powRemainder (n `div` b) b else n
with this when I run take 20 someList it returns [1,2,3,4,5,6,8,9,10,12,15,16,18,20,24,25,27,30,32,36].
As others already commented, your core does not work because it is analogous to the following imperative pseudocode:
for x in 0..infinity:
for y in 0..infinity:
for z in 0..infinity:
print (2^x * 3^y * 5^x)
The innermost for takes infinite time to execute, so the other two loops will never get past their first iteration. Consequently, x and y are both stuck to value 0.
This is a classic dovetailing problem: if we insist on trying all the values of z before taking the next y (or x), we get stuck on a subset of the intended outputs. We need a more "fair" way to choose the values of x,y,z so that we do not get stuck in such way: such techniques are known as "dovetailing".
Others have shown some dovetailing techniques. Here, I'll only mention the control-monad-omega package, which implements an easy to use dovetailing monad. The resulting code is very similar to the one posted in the OP.
import Control.Monad.Omega
powersOf235 :: [Integer]
powersOf235 = runOmega $ do
x <- each [0..]
y <- each [0..]
z <- each [0..]
return $ 2^x * 3^y * 5^z

Finding primes using Sieve of Eratosthenes not working - 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.

Haskell Hamming numbers, works but shows duplicates

I am trying to generate hamming numbers in haskell, the problem is I get duplicate #'s in my output list and I cannot figure out why exactly. Should I just create a remove duplicates function or am I just missing something simple?
Also in the function hamming I would like to make sure the size of the input list is exactly 3, how do I find the size of a list so I can do the comparison?
{- Merge lists x&y of possibly infinite lengths -}
merge [] [] = []
merge [] ys = ys
merge xs [] = xs
merge xs ys = min x y : if x < y then merge (tail xs) ys
else merge xs (tail ys)
where x = head xs
y = head ys
{- multiply each element in y by x -}
times x [] = []
times x y = x * (head y) : times x (tail y)
{- find the hamming numbers of the input primes list -}
ham [] = []
ham x = 1 : merge (times (head x) (ham x))
(merge (times (x !! 1) (ham x)) (times (last x) (ham x)))
{- returns x hamming #'s based on y primes of size 3 -}
hamming x [] = []
hamming x y = take x (ham y)
{- hamming x y = if "y.size = 3" then take x (ham y)
else "Must supply 3 primes in input list" -}
You get duplicates because many of the hamming numbers are multiples of several of the base numbers, and you don't remove duplicates in your merge function. For example, for the classical 2, 3, 5 Hamming numbers, you obtain 6 as 2 * 3 as well as 3 * 2.
You could of course create a duplicate removal function. Since the list you create is sorted, that wouldn't even be very inefficient. Or you could remove the duplicates in the merge function.
how do I find the size of a list so I can do the comparison?
You can obtain the length of a list using the length function that is available from the Prelude, but let me warn you right now that calling length should only be done if the length is really required, since length has to traverse the entire list to calculate its length. If the list happens to be long, that takes a lot of time, and may cause huge memory usage if the list is referenced elsewhere so that it cannot be garbage-collected. If the list is even infinite, evaluating its length will of course never terminate.
What you want to do can also be achieved by pattern-matching,
ham [a, b, c] = list
where
list = 1 : merge (map (a*) list) (merge (map (b*) list) (map (c*) list))
ham _ = []
You could also use a guard with a length check
hamming x y
| length y == 3 = take x (ham y)
| otherwise = []
to make sure that your input list has exactly three elements, but you will regret that if you call hamming 10 [1 .. ].
In the List module, Haskell has a duplicate remover called nub. Here it is on hoogle: http://www.haskell.org/hoogle/?hoogle=nub. This is O(n^2) though, so you might be better off changing merge. But it may be worthwhile to first use a slow solution already written for you, before optimizing.
I suspect that you are trying to learn Haskell with this little exercise, but here's another way to write out the hamming numbers (no duplicates, but not in order) using the List monad:
uglyNumbers = do { n <- [0..]
; k <- [0..n]
; j <- [0..n-k]
; return $ (2^(n-k-j))*(3^j)*(5^k) }
This makes a lazy, infinite list of hamming numbers. You can equivalently write this using a list comprehension:
uglyNumbers' = [(2^(n-k-j))*(3^j)*(5^k) | n <- [0..], k <- [0..n], j <- [0..n-k]]

Resources