Related
I am trying to count the number of non-empty lists in a list of lists with recursive code.
My goal is to write something simple like:
prod :: Num a => [a] -> a
prod [] = 1
prod (x:xs) = x * prod xs
I already have the deifniton and an idea for the edge condition:
nonEmptyCount :: [[a]] -> Int
nonEmptyCount [[]] = 0
I have no idea how to continue, any tips?
I think your base case, can be simplified. As a base-case, we can take the empty list [], not a singleton list with an empty list. For the recursive case, we can consider (x:xs). Here we will need to make a distinction between x being an empty list, and x being a non-empty list. We can do that with pattern matching, or with guards:
nonEmptyCount :: [[a]] -> Int
nonEmptyCount [] = 0
nonEmptyCount (x:xs) = -- …
That being said, you do not need recursion at all. You can first filter your list, to omit empty lists, and then call length on that list:
nonEmptyCount :: [[a]] -> Int
nonEmptyCount = length . filter (…)
here you still need to fill in ….
Old fashion pattern matching should be:
import Data.List
nonEmptyCount :: [[a]] -> Int
nonEmptyCount [] = 0
nonEmptyCount (x:xs) = if null x then 1 + (nonEmptyCount xs) else nonEmptyCount xs
The following was posted in a comment, now deleted:
countNE = sum<$>(1<$)<<<(>>=(1`take`))
This most certainly will look intimidating to the non-initiated, but actually, it is equivalent to
= sum <$> (1 <$) <<< (>>= (1 `take`))
= sum <$> (1 <$) . (take 1 =<<)
= sum . fmap (const 1) . concatMap (take 1)
= sum . map (const 1) . concat . map (take 1)
which is further equivalent to
countNE xs = sum . map (const 1) . concat $ map (take 1) xs
= sum . map (const 1) $ concat [take 1 x | x <- xs]
= sum . map (const 1) $ [ r | x <- xs, r <- take 1 x]
= sum $ [const 1 r | (y:t) <- xs, r <- take 1 (y:t)] -- sneakiness!
= sum [const 1 r | (y:_) <- xs, r <- [y]]
= sum [const 1 y | (y:_) <- xs]
= sum [ 1 | (_:_) <- xs] -- replace each
-- non-empty list
-- in
-- xs
-- with 1, and
-- sum all the 1s up!
= (length . (take 1 =<<)) xs
= (length . filter (not . null)) xs
which should be much clearer, even if in a bit sneaky way. It isn't recursive in itself, yes, but both sum and the list-comprehension would be implemented recursively by a given Haskell implementation.
This reimplements length as sum . (1 <$), and filter p xs as [x | x <- xs, p x], and uses the equivalence not (null xs) === (length xs) >= 1.
See? Haskell is fun. Even if it doesn't yet feel like it, but it will be. :)
I'm struggling with the syntax of Haskell and am getting receiving "error: parse error on input ‘if’" when I try to compile my script with GHCI. The aim of my code is to return the minimum and maximum of an unordered list. It does this recursively by splitting the list in half and finding the minimum and maximum of each half. If the list has only one element it simply returns that that element is both the maximum and the minimum, if the list has two elements it does a simple comparison to find the minimum and maximum. Here is my code, the "splitlist" function was taken from an online resource:
splitlist :: [a] -> ([a], [a])
splitlist xs = splitAt ((length xs + 1) `div` 2) xs
minMax :: [Int] -> [Int]
minMax x
if length x == 1 then
[x, x]
else if length x == 2 then
if (head x > tail x) then
[tail x, head x]
else
[head x, tail x]
else
listOfLists = splitlist x
list1 = listOfLists!!0
list2 = listOfLists!!1
minMax1 = minMax list1
minMax2 = minMax list2
if (minMax1!!0 < minMax2!!0) then
min = minMax1!!0
else
min = minMax2!!0
if (minMax!!1 > minMax2!!1) then
max = minMax1!!1
else
max = minMax2!!1
[min, max]
I am also suspicious that I am not attempting to do this in a way that Haskell was meant for, I'm a beginner and still accidentally treat it like python quite a lot. Ideally if someone could tell me what I'm doing wrong with my method and then show me a method more in line with Haskell's design principles I would be very appreciative.
There are several things in your function that isn't valid Haskell syntax. You are missing a =, and you are trying to declare variables in a way Haskell doesn't allow.
I tried to rearrange your code to be correct and here is what I got:
splitlist :: [a] -> ([a], [a])
splitlist xs = splitAt ((length xs + 1) `div` 2) xs
minMax :: [Int] -> [Int]
minMax x = if length x == 1 then
[head x, head x]
else if length x == 2 then
if (head x > (head $ tail x)) then
[(head $ tail x), head x]
else
[head x, (head $ tail x)]
else [if (minMax1!!0 < minMax2!!0) then minMax1!!0 else minMax2!!0,
if (minMax1!!1 > minMax2!!1) then minMax1!!1 else minMax2!!1]
where
listOfLists = splitlist x
list1 = fst listOfLists
list2 = snd listOfLists
minMax1 = minMax list1
minMax2 = minMax list2
It looks like your algorithm works as expected! It was a little tricky because this isn't usually the way most people tend to write Haskell methods.
Here is a different implementation that might be useful for comparison:
minMax :: [Int] -> [Int]
minMax [] = []
minMax (x:xs) = minMax' x x xs
where
minMax' a b [] = [a, b]
minMax' a b (x:xs) = minMax' (min a x) (max b x) xs
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.
I'm writing a small program that takes coefficients of two polynomials and FOILs them together, however I can only seem to multiply elements at the same indices.
fun polyMult([],[]) = []
| polyMult(M, []) = []
| polyMult([], N) = []
| polyMult(M as x::xs, N as y::ys) =
(x * y) :: polyMult(M, ys);
I can successfully multiply the first element of M by every element of N, but then afterwards I want to be able to advance one element in M and then take that and multiply it by every element in N.
Is there any way I can advance the index in M and repeat the multiplication process? I.E
polyMult(tl(M) as x::xs, N as y::ys) =
(x * y) :: polyMult(M, ys);
Something along these lines
fun foldL F y nil = y
| foldL F y (x::xr) = foldL F (F(x,y)) xr;
fun polymult(M, nil) = nil
| polymult(nil, N) = nil
| polymult(m::mr, N) = foldL(fn(x,a) => x * a) m N::polymult(mr,N);
But you will need to figure out how to make it only accept real numbers and not integers as it does now ;)
Hi
Im new to Haskell and wish to write a simple code.
I want to write a function which creates a list of numbers.
Where it starts of with 1 and increase with 2n+1 and 3n+1
so for example output should be like
take 6 myList = [1,3,4,7,9,10]
I think i need to use recursion but not sure how to do
it in list format.
Any help will be appreciated. Thanks
Actually, I am not sure if I get your idea.
But Is this what you want?
generator list = list ++ generator next
where
next = (map (\n -> 2 * n + 1) list) ++ (map (\n -> 3 * n + 1) list)
Oh, you can use generator [1] to fire up. like this:
take 100 $ generator [1]
merge xs [] = xs
merge [] ys = ys
merge (x:xs) (y:ys) | x == y = x : merge xs ys
| x < y = x : merge xs (y:ys)
| otherwise = y : merge (x:xs) ys
print $ take 10 $ merge [1,3..] [1,4..]
--[1,3,4,5,7,9,10,11,13,15]
As luqui said, we could use info such as do duplicates matter and does order matter. If the answers are no and no then a simple concatMap works fine:
myList = 1 : concatMap (\n -> 2*n+1 : 3*n+1 : []) myList
Results in:
> take 20 myList
[1,3,4,7,10,9,13,15,22,21,31,19,28,27,40,31,46,45,67,43]
If the answers are yes and yes then I imagine it could be cleaner, but this is sufficient:
myList = abs
where
abs = merge as bs
as = 1 : map (\n -> 2*n+1) abs
bs = 1 : map (\n -> 3*n+1) abs
merge (x:xs) (y:ys)
| x == y = x : merge xs ys
| x < y = x : merge xs (y:ys)
| otherwise = y : merge (x:xs) ys
Results in:
> take 20 myList
[1,3,4,7,9,10,13,15,19,21,22,27,28,31,39,40,43,45,46,55]