How can I do the sum of elements in a list at the same position?
For example:
[[2,3,4],[5,6,7],[8,9,10]]=[15,18,21]
Thanks
Try:
sumIn :: Num a => [[a]] -> [a]
sumIn = foldl (zipWith (+)) (repeat 0)
Note that if the argument is an empty list, the result is an infinite list of zeros. So you may want to treat this case separately, for example
sumIn :: Num a => [[a]] -> [a]
sumIn [] = []
sumIn xs = foldl (zipWith (+)) (repeat 0) xs
Here's an example in GHCi:
λ> let xs = [[2,3,4],[5,6,7],[8,9,10]]
λ> foldr1 (zipWith (+)) xs
[15,18,21]
You could transpose the list, and sum each list in the result:
ghci> import Data.List (transpose)
ghci> map sum $ transpose [[2,3,4],[5,6,7],[8,9,10]]
[15,18,21]
Unlike the other solutions, this works for lists of non-uniform length.
Related
How can I find all the minimum elements in a list? Right now I have a list of tuples, i.e.
[(10,'a'),(5,'b'),(1,'c'),(8,'d'),(1,'e')]
So I want the output which is all the minimum elements of the list, in a new list. For example
[(1,'c'),(1,'e')]
I tried
minimumBy (comparing fst) xs
but that only returns the first minimum element.
After you obtain the minimum of the first value, we can filter the list on these items. Because you here want to retrieve a list of minimum items, we can cover the empty list as well by returning an empty list:
minimumsFst :: Ord a => [(a, b)] -> [(a, b)]
minimumsFst [] = []
minimumsFst xs = filter ((==) minfst . fst) xs
where minfst = minimum (map fst xs)
For example:
Prelude> minimumsFst [(10,'a'),(5,'b'),(1,'c'),(8,'d'),(1,'e')]
[(1,'c'),(1,'e')]
Oneliner. The key is sorting.
Prelude Data.List> let a = [(1,'c'),(2,'b'),(1,'w')]
Prelude Data.List> (\xs#((m,_):_) -> takeWhile ((== m) . fst ) xs) . sortOn fst $ a
[(1,'c'),(1,'w')]
Here's a solution that works in one pass (most other answers here do two passes: one to find the minimum value and one to filter on it), and doesn't rely on how the sorting functions are implemented to be efficient.
{-# LANGUAGE ScopedTypeVariables #-}
import Data.Foldable (foldl')
minimumsBy :: forall a. (a -> a -> Ordering) -> [a] -> [a]
minimumsBy _ [] = []
minimumsBy f (x:xs) = postprocess $ foldl' go (x, id) xs
where
go :: (a, [a] -> [a]) -> a -> (a, [a] -> [a])
go acc#(x, xs) y = case f x y of
LT -> acc
EQ -> (x, xs . (y:))
GT -> (y, id)
postprocess :: (a, [a] -> [a]) -> [a]
postprocess (x, xs) = x:xs []
Note that the [a] -> [a] type I'm using here is called a difference list, aka a Hughes list.
You tried
minimumBy (comparing fst) xs
which can also be written as
= head . sortBy (comparing fst) $ xs
= head . sortOn fst $ xs
= head . head . group . sortOn fst $ xs
= head . head . groupBy ((==) `on` fst) . sortOn fst $ xs
This returns just the first element instead of the list of them, so just drop that extra head to get what you want:
= head . groupBy ((==) `on` fst) . sortOn fst $ xs
Of course having head is no good since it'll error out on the [] input. Instead, we can use the safe option,
= concat . take 1 . groupBy ((==) `on` fst) . sortOn fst $ xs
By the way any solution that calls minimum is also unsafe for the empty input list:
> head []
*** Exception: Prelude.head: empty list
> minimum []
*** Exception: Prelude.minimum: empty list
but takeWhile is safe:
> takeWhile undefined []
[]
edit: thanks to laziness, the overall time complexity of the final version should still be O(n) even in the worst case.
You can do it easily too with foldr:
minimumsFst :: Ord a => [(a, b)] -> [(a, b)]
minimumsFst xs = go (minfst xs) xs
where
go mn ls = foldr (\(x, y) rs -> if (x == mn) then (x,y) : rs else rs) [] xs
minfst ls = minimum (map fst ls)
with your example:
minimumsFst [(10,'a'),(5,'b'),(1,'c'),(8,'d'),(1,'e')]
=> [(1,'c'),(1,'e')]
I need a function that returns a list of all possible sublists, without skipping elements, e.g. sublists [1,2,3,4] should return [[1,2,3,4],[1,2,3] etc.] but the list should NOT contain [1,2,4].
My current "solution" is
>sublists :: [Integer] -> [[Integer]]
>sublists [] = [[]]
>sublists (x:xs) = [x:ys | ys <- sublists xs] ++ sublists xs
which does include [1,2,4]
Thanks in advance
EDIT: Found a solution (with a little help of my friend)
Looks a bit clumsy but it works
>sublists :: [Integer] -> [[Integer]]
>sublists [] = [[]]
>sublists (x:xs) = subs [] (x:xs) ++ sublists xs
> where
> subs :: [Integer] -> [Integer] -> [[Integer]]
> subs xs [] = [xs]
> subs xs (a:as) = (xs ++ [a]) : (subs (xs ++ [a]) as)
Data.List contains both inits and tails. What you want is the inits of each member of the tails list (or possibly vice-versa, but see later for the reason why this way round is better)
sublists = concatMap inits . tails
> sublists [1,2,3,4]
[[],[1],[1,2],[1,2,3],[1,2,3,4],[],[2],[2,3],[2,3,4],[],[3],[3,4],[],[4],[]]
If you prefer, you might want to get rid of all the null lists:
sublists = filter (not . null) . concatMap inits . tails
Or if you prefer to avoid generating the null lists in the first place:
sublists = concatMap (tail . inits) . tails
The result of inits always starts with the empty list, while the result of tails always ends with the empty list. So tail . inits is safe because tail will never be applied to an empty list; it just returns the result without the leading empty list. inits [] just returns [[]], so the last empty list from tails gets dropped.
merge :: [a] -> [a] -> [a]
merge xs [] = xs
merge [] ys = ys
merge (x:xs) (y:ys) = x : y : merge xs ys
maxOfTwoLists [x] [y] = maximum (merge [x] [y])
I am trying to combine the two lists then find the max value in the single list. It compiles but when i call maxOfTwoLists it gives me a non-exhaustive patterns error. My merge returns a single list just fine, and maximum takes a single list. So it feels like it should be working.
If you're looking to merge two lists, the builtin concat would help. It flattens a list, so we could do the following:
maxOfTwoLists :: (Ord a) => [a] -> [a] -> a
maxOfTwoLists xs ys = maximum $ concat [xs,ys]
In which, $ means to evaluate the result of the right side function before applying it to the left side function.
As #badcook notes the pattern match isn't quite right.
merge :: [a] -> [a] -> [a]
merge xs [] = xs
merge [] ys = ys
merge (x:xs) (y:ys) = x : y : merge xs ys
maxOfTwoLists :: (Ord a) => [a] -> [a] -> a
maxOfTwoLists [] ys = maximum ys
maxOfTwoLists xs [] = maximum xs
maxOfTwoLists xs ys = maximum (merge xs ys)
I'll guess you wrote the merge function as an exercise but you can also use ++ from Prelude to append one list to another.
maxOfTwoLists :: (Ord a) => [a] -> [a] -> a
maxOfTwoLists xs ys = maximum (xs ++ ys)
Output:
λ> maxOfTwoLists [1,2,3] [4,5,6]
6
λ> maxOfTwoLists [1,2,3] []
3
λ> maxOfTwoLists [] [1,2,3]
3
λ>
What is the best way to find out if a number in a list is within the range of a second list, using a Maybe data type?
What I have so far:
getElems :: [Int] -> [a] -> [Maybe a]
getElems [xs] ys
| head(tail[(xs)]) > head(tail[(ys)]) = [Nothing]
| otherwise = [Just xs]
It needs to return those elements that correspond to the positions specified. Depending on if a position is greater than the list size it returns Nothing, else Just value.
For example:
getElems [2,4] [1..10] ) [Just 3,Just 5]
getElems [2,4] [1..4] ) [Just 3,Nothing]
You can write an getElementByIndex which does that for a single list:
getElementByIndex :: Int -> [a] -> Maybe a
getElementByIndex n [] = Nothing
getElementByIndex n (x:xs) = if (n == 0)
then Just x
else getElementByIndex (n - 1) xs
And then just map it to get an answer:
getElems :: [Int] -> [a] -> [Maybe a]
getElems xs ys = map (\x -> getElementByIndex x ys) xs
Demo in ghci:
λ> getElems [2,4] [1..10]
[Just 3,Just 5]
λ> getElems [2,4] [1..4]
[Just 3,Nothing]
count :: Eq a => a -> [a] -> Int
count n [] = 0
count n (x:xs) | n == x = 1 + count n xs
| otherwise = count n xs
rmdups :: Eq a => [a] -> [a]
rmdups [ ] = [ ]
rmdups (x:xs) = x : rmdups (filter(/= x) xs)
using the 2 functions, a third needs to be created, called frequency:
it should count how many times each distinct value in a list occurs in that list. for example : frequency "ababc", should return [(3,'a'),(2,'b'),(1,'c')].
the layout for frequency is :
frequency :: Eq a => [a] -> [(Int, a)]
P.s rmdups, removes duplicates from list, so rmdups "aaabc" = abc
and count 2 [1,2,2,2,3] = 3.
so far i have:
frequency :: Eq a => [a] -> [(Int, a)]
frequency [] = []
frequency (x:xs) = (count x:xs, x) : frequency (rmdups xs)
but this is partly there, (wrong). thanks
frequency xs = map (\c -> (count c xs,c)) (rmdups xs)
or, with a list comprehension,
frequency xs = [(count c xs, c) | c <- rmdups xs]
is the shortest way to define it using your count and rmdups. If you need it sorted according to frequency (descending) as in your example,
frequency xs = sortBy (flip $ comparing fst) $ map (\c -> (count c xs,c)) (rmdups xs)
using sortBy from Data.List and comparing from Data.Ord.
If all you have is an Eq constraint, you cannot gain much efficiency, but if you only need it for types in Ord, you can get a much more efficient implementation using e.g. Data.Set or Data.Map.
Here is my own 'lazy' answer, which does not call rmdups:
frequency [] = []
frequency (y:ys) = [(count y (y:ys), y)] ++ frequency (filter (/= y) ys)
import qualified Data.Set as Set
frequency xs = map (\x -> (length $ filter (== x) xs, x)) (Set.toList $ Set.fromList xs)