Related
I'm having trouble with an assignment from my Haskell class. I have already solved a partial problem of this task: I have to write a function that takes an Int and creates an infinite list with the multiples of that Int.
function :: Int -> [Int]
function d = [d*x | x <- [1..]]
Console:
ghci> take 10 (function 3)
gives
[3,6,9,12,15,18,21,24,27,30]
In the second task I have to extend the function so that it accepts a list of numbers and uses each value of that list as a factor (d previously). For example:
ghci> take 10 (function [3, 5])
should give
[3,5,6,9,10,12,15,18,20,21]
Already tried a list comprehension like
function d = [y*x | y <- [1..], x <- d]
but the function returns the list in an unsorted form:
[3,5,6,10,9,15,12,20,15,25]
We got the tip that we should use the modulo function of Haskell, but I have no real idea how to proceed exactly. Do you have a good tip for me?
If you think of d being a factor not as
y = x * d
but instead
y `mod` d == 0,
then you can source the list comprehension from the list [1..] and add a predicate function, for example:
function ds
| null ds = [1..]
| otherwise = [ x | x <- [1..], qualifies x ]
where
qualifies x = any (==0) $ (flip mod) <$> ds <*> [x]
A more expressive version which is perhaps easier to grasp in the beginning:
function' ds
| null ds = [1..]
| otherwise = [ x | x <- [1..], divByAnyIn ds x ]
where
divByAnyIn ds x =
case ds of
(d:ds') -> if x `mod` d == 0 then True
else divByAnyIn ds' x
_ -> False
I have a one liner.
import Data.List (nub)
f xs = nub [x|x<-[1..], d<-xs, x `mod` d == 0]
take 10 $ f [3,5] -- [3,5,6,9,10,12,15,18,20,21]
runtime should be O(n² + n*d) from the resulting list. The nub runs in O(n²). Would be nice to get rid of it.
g xs = [x |x<-[1..], let ys = map (mod x) xs in 0 `elem` ys]
This performs pretty ok. It should run in O (n*d). I also have this version which I thought performs at least as well as g, but apparently it performs better than f and worse than g.
h xs = [x |x<-[1..], or [x `mod` d == 0 |d<-xs] ]
I am not sure why that is, or is lazy as far as I can tell and I don`t see any reason why it should run slower. It especially does not scale as well when you increase the length of the input list.
i xs = foldr1 combine [[x, x+x ..] |x<- sort xs]
where
combine l [] = l
combine [] r = r
combine l#(x:xs) r#(y:ys)
| x < y = (x: combine xs r)
| x > y = (y: combine l ys)
| otherwise = (x: combine xs ys)
Not a one liner anymore, but the fastest I could come up with. I am not a hundred percent sure why it makes such a big difference on runtime if you right or left fold and if you sort the input list in advance. But it should not make a difference on the result since:
commutative a b = combine [a] [b] == combine [b] [a]
I find it completely insane to think about this Problem in terms of folding a recursive function over a list of endless lists of multiples of input coefficients.
On my System it is still about a factor of 10 slower than another solution presented here using Data.List.Ordered.
The answer here just shows the idea, it is not a optimized solution, there may exists many way to implement it.
Firstly, calculate all the value of each factors from the inputted list:
map (\d->[d*x|x<-[1..]]) xs
For example: xs = [3, 5] gives
[[3, 6, 9, ...], [5, 10, 15, ...]]
then, find the minimum value of 1st element of each list as:
findMinValueIndex::[(Int, [Int])]->Int
findMinValueIndex xss = minimum $
map fst $
filter (\p-> (head $ snd p) == minValue) xss
where minValue = minimum $ map (head . snd) xss
Once we found the list hold the minimum value, return it and remove the minimum value from list as:
sortMulti xss =
let idx = findMinValueIndex $ zip [0..] xss
in head (xss!!idx):sortMulti (updateList idx (tail $ xss!!idx) xss
So, for example, after find the first value (i.e. 3) of the result, the lists for find next value is:
[[6, 9, ...], [5, 10, 15, ...]]
repeat above steps we can construct the desired list. Finally, remove the duplicated values. Here is the completed coding:
import Data.Sequence (update, fromList)
import Data.Foldable (toList)
function :: [Int] -> [Int]
function xs = removeDup $ sortMulti $ map (\d->[d*x|x<-[1..]]) xs
where sortMulti xss =
let idx = findMinValueIndex $ zip [0..] xss
in head (xss!!idx):sortMulti (updateList idx (tail $ xss!!idx) xss)
removeDup::[Int]->[Int]
removeDup [] = []
removeDup [a] = [a]
removeDup (x:xs) | x == head xs = removeDup xs
| otherwise = x:removeDup xs
findMinValueIndex::[(Int, [Int])]->Int
findMinValueIndex xss = minimum $
map fst $
filter (\p-> (head $ snd p) == minValue) xss
where minValue = minimum $ map (head . snd) xss
updateList::Int->[Int]->[[Int]]->[[Int]]
updateList n xs xss = toList $ update n xs $ fromList xss
There is a pretty nice recursive solution
function' :: Int -> [Int]
function' d = [d * x | x <- [1..]]
braid :: [Int] -> [Int] -> [Int]
braid [] bs = bs
braid as [] = as
braid aa#(a:as) bb#(b:bs)
| a < b = a:braid as bb
| a == b = a:braid as bs # avoid duplicates
| otherwise = b:braid aa bs
function :: [Int] -> [Int]
function ds = foldr braid [] (map function' ds)
braid function builds the desired list "on the fly" using only input's head and laziness
If you want to do it with the modulo function, you can define a simple one-liner
foo ds = filter (\x -> any (== 0) [mod x d | d <- ds]) [1..]
or, in the more readable form,
foo ds = filter p [1..]
where
p x = any id [ mod x d == 0 | d <- ds]
= any (== 0) [ mod x d | d <- ds]
= not $ null [ () | d <- ds, mod x d == 0]
= null [ () | d <- ds, mod x d /= 0]
= null [ () | d <- ds, rem x d > 0]
With this, we get
> take 20 $ foo [3,5]
[3,5,6,9,10,12,15,18,20,21,24,25,27,30,33,35,36,39,40,42]
But, it is inefficient: last $ take 20 $ foo [300,500] == 4200, so to produce those 20 numbers this code tests 4200. And it gets worse the bigger the numbers are.
We should produce n numbers in time roughly proportional to n, instead.
For this, first write each number's multiples in their own list:
[ [d*x | x <- [1..]] | d <- ds ] ==
[ [d, d+d ..] | d <- ds ]
Then, merge these ordered increasing lists of numbers in an ordered fashion to produce one ordered non-decreasing list of numbers. The package data-ordlist has many functions to deal with this kind of lists:
import qualified Data.List.Ordered as O
import Data.List (sort)
bar :: (Ord a, Num a, Enum a) => [a] -> [a]
bar ds = foldr O.merge [] [ [d, d+d ..] | d <- ds ]
= O.foldt' O.merge [] [ [d, d+d ..] | d <- ds ] -- more efficient,
= O.mergeAll [ [d, d+d ..] | d <- sort ds ] -- tree-shaped folding
If we want the produced list to not contain any duplicates, i.e. create an increasing list, we can change it to
baz ds = O.nub $ foldr O.merge [] [ [d, d+d ..] | d <- ds ]
= foldr O.union [] [ [d, d+d ..] | d <- ds ]
= O.foldt' O.union [] [ [d, d+d ..] | d <- ds ]
= O.unionAll [ [d, d+d ..] | d <- sort ds ]
= (O.unionAll . map (iterate =<< (+)) . sort) ds
Oh, and, unlike the quadratic Data.List.nub, Data.List.Ordered.nub is linear, spends O(1) time on each element of the input list.
So suppose we want to produce the list [0, 1, -1, 2, -2, ...in Haskell.
What is the most elegant way of accomplishing this?
I came up with this solution:
solution = [0] ++ foldr (\(a,b) c->a:b:c) [] zip [1..] $ map negate [1..]
But I am sure there must be a better way.
This seems like the kind of thing that comprehensions are made for:
solution = 0 : [y | x <- [1..], y <- [x, -x]]
With iterate
Perhaps a more elegant way to do this, is by using iterate :: (a -> a) -> a -> [a] with a function that generates each time the next item. For instance:
solution = iterate nxt 0
where nxt i | i > 0 = -i
| otherwise = 1-i
Or we can inline this with an if-then-else:
solution = iterate (\i -> if i > 0 then -i else 1-i) 0
Or we can convert the boolean to an integer, like #melpomene says, with fromEnum, and then use this to add 1 or 0 to the answer, so:
solution = iterate (\i -> fromEnum (i < 1)-i) 0
Which is more pointfree:
import Control.Monad(ap)
solution = iterate (ap subtract (fromEnum . (< 1))) 0
With (<**>)
We can also use the <**> operator from applicate to produce each time the positive and negative variant of a number, like:
import Control.Applicative((<**>))
solution = 0 : ([1..] <**> [id, negate])
How about
concat (zipWith (\x y -> [x, y]) [0, -1 ..] [1 ..])
or
concat (transpose [[0, -1 ..], [1 ..]])
?
How about:
tail $ [0..] >>= \x -> [x, -x]
On a moment's reflection, using nub instead of tail would be more elegant in my opinion.
another primitive solution
alt = 0 : go 1
where go n = n : -n : go (n+1)
You could also use concatMap instead of foldr here, and replace map negate [1..] with [0, -1..]:
solution = concatMap (\(a, b) -> [a, b]) $ zip [0, -1..] [1..]
If you want to use negate instead, then this is another option:
solution = concatMap (\(a, b) -> [a, b]) $ (zip . map negate) [0, 1..] [1..]
Just because no one said it:
0 : concatMap (\x -> [x,-x]) [1..]
Late to the party but this will do it as well
solution = [ (1 - 2 * (n `mod` 2)) * (n `div` 2) | n <- [1 .. ] ]
I want to write a function that uses list comprehensions to generate a list of lists that works like this:
makeList 3 == [[1],[1,2],[1,2,3]]
makeList 5 == [[1],[1,2],[1,2,3],[1,2,3,4],[1,2,3,4,5]]
makeList (-2) == []
I end up with this solution, but It not gives me what it needs from the question obviously:
let makelist x = [x | x <- x, y <- [1..x]]
So if I enter this
Prelude> makelist [3]
the output will shows like this:
[3,3,3]
I wanted to be a list in list first then I want it to be increased. Thank you for help!
Let's try generating an inner list first, for some limit m:
> let inner m = [1..m]
> inner 5
[1,2,3,4,5]
Now, observe that your outer list, for some limit n, is [inner 1, inner 2, inner 3, ..., inner n], or, in list comprehension form:
> let outer n = [inner m | m <- [1..n]]
> outer 3
[[1], [1,2], [1,2,3]]
so we can combine the two into the single list comprehension expression:
> let makeList n = [[1..m] | m <- [1..n]]
> makeList 4
[[1],[1,2],[1,2,3],[1,2,3,4]]
I propose you this:
make_list n = [ [1..m] | m <- [1..n] ]
However there's something strange in your first attempt:
make_list x = [x | x <- x, y <- [1..x]]
there you put x for every purpose. It just feels wrong.
A recursive version based in list generation as well,
makeList' :: Int -> [[Int]]
makeList' n
| n < 1 = []
| otherwise = [1..n] : makeList' (n-1)
makeList :: Int -> [[Int]]
makeList n = reverse $ makeList' n
makeList' returns the desired outcome in reverse order.
I just started learning Haskell about filtering lists.
Suppose I have the following list : [2, 3, 4, 5, 8, 10, 11]
I would like to keep only those numbers in the list, which are not divisible by the other members.
The result of our example would be : [2, 3, 5, 11]
[x | x <- src, all (\y -> x `rem` y /= 0) (filter (<x) src)]
where src = [2,3,4,5,8,10,11]
It should be noted that you actually also mean dividable by other numbers that are below it, and not just any number in that list, which is why there's a filter in the 2nd argument for all.
The result, of course, is the one you expect in your question: [2,3,5,11].
Here's how it works (and if I'm missing anything, let me know and I'll update).
I'll explain the code side-by-side with normal English. I suggest you just read just the English first, and afterwards see how each statement is expressed in code - I think it should be the most friendly for a newcomer.
Also note that I flipped the arguments for filter and all below (it is invalid!) to make the explanation fluid.
[x|: Construct a list made out of x
x <- src: Where x is an element from src
,: But only the elements that satisfy the following predicate/rule:
all of the numbers from
(filter src (<x)): src that are lesser-than the current x
(\y -> x 'rem' y /= 0): must not yield a remainder equal to 0.
]
For the code part to make sense, make sure you've familiarized yourself with all, filter, rem, and the syntax for: list comprehensions, lambda expressions, sections, and backticks.
On GHC,
Prelude> :m + Data.List
Prelude Data.List> nubBy (\a b -> rem a b == 0) [2,3,4,5,8,10,11]
[2,3,5,11]
does the trick. On Haskell98-compatible systems (e.g. Hugs), use nubBy (\b a -> rem a b == 0).
This answer was posted as a comment by Will Ness.
Using filter
filter :: (a -> Bool) -> [a] -> [a]
and from Data.Numbers.Primes the function
isPrime :: Integral int => int -> Bool
may be
filter isPrime [2, 3, 4, 5, 8, 10, 11]
or using list comprehension
[ x | x <- [2, 3, 4, 5, 8, 10, 11], isPrime x]
change filter predicate as you wish, e.g.
-- None `xs` element (different than `x`) divide `x`
noneDiv xs x = and [x `mod` y /= 0 | y <- xs, x /= y]
now
myFilter xs = filter (noneDiv xs) xs
or
myFilter xs = [x | x <- xs, noneDiv xs x]
I have a series of numbers: 0, 1, 3, 6, 10, 15,...
Basically, you add 1, then you add 2, then add 3, etc.
I have to make a function where I return this series of numbers in a list up to a given number, n. I want to use foldl.
so, series 5 should return [0, 1, 3, 6, 10, 15]
Here is what I have so far:
eachElem n = foldl (+) 0 [0..n]
series n = [x | x <- [(eachElem 0), (eachElem 1)..(eachElem n)]]
Basically, I figured that each element in the list was a foldl operation, and so I made a separate helper function (eachElem) to accomplish this.
However, it is returning a list much larger than what I want.
Eg. series 3 => [0,1,2,3,4,5,6] when it should really return [0,1,3,6]
Any ideas why this is?
scanl is better suited to what you're doing.
Its type is scanl :: (a -> b -> a) -> a -> [b] -> [a] -- its type signature is the same as foldl's, but it returns a list of incremental values, instead of just the final result.
I'll leave the rest as an exercise for you, since this seems like homework. Good luck!
If you are so adamant of using foldl you can do something like
series n = reverse $ foldl f [0] [1..n]
where f xs#(x:_) y = x+y:xs
In ghci
> series 5
[0,1,3,6,10,15]
But problem with foldl is you can not create infinite series.
You can have infinite series like
series = 0:zipWith (+) series [1..]
Then you can do something like
> take (5+1) series
[0,1,3,6,10,15]
I have not tried but you might also use unfoldr or similar concept to build your list.
scanl is the best here, but if you have to use fold try this
testso :: Integral a => a -> [a]
testso n = reverse $ foldl (\acc x -> head acc + x:acc ) [0] [1,2..n]
gives output as testso 10 [0,1,3,6,10,15,21,28,36,45,55].
Your definition of series is wrong.
[(eachElem 0), (eachElem 1)..(eachElem n)] becomes [0, 1, eachElem n] which is actually every number up to eachElem n.
You actually want to do this:
series n = [eachElem x | x <- [0..n]]
the definition
series n = [ x | x <- [(eachElem 0)..(eachElem n)]]
is wrong!
For instance:
because of
eachElem 0 -> 0
eachElem 3 -> 6
series 3 evaluates to
series 3 -> [(eachElem 0)..(eachElem 3)] -> [0..6] -> [0,1,2,3,4,5,6]
You need something like that
series' n = [ eachElem x | x <- [0..n]]
tests:
> let series' n = [ eachElem x | x <- [0..n]]
> let series n = [ x | x <- [(eachElem 0)..(eachElem n)]]
> series' 3
> [0,1,3,6]
> series 3
> [0,1,2,3,4,5,6]
> eachElem 0
> 0
> eachElem 3
> 6
When you write [a,b..c], a is the first element, c is the last element and b is the step, it's the interval between every element in the list and if you omit it, it will be defaulted to 1.
So let's have a look at your code, you do:
[x | x <- [(eachElem 0), (eachElem 1)..(eachElem n)]]
In your list comprehension, x will first take the value (eachElem 0) = 0
Then the next element will be (eachElem 0) + (eachElem 1) = 1
Then the ith elent will be (eachElem 0) + i*(eachElem 1 - eachElem 0) as long as the value is <= (eachElem n)
Hence your result: [0,1..(eachElem n)] which produces [0,1,2,3... and clearly isn't what you expected.
As suggested by amindfv, you should have a look at scanl.
You can cheat :-)
series x = foldl (\xs n -> (n*(n+1) `div` 2):xs) [] [x,(x-1)..0]