Finding the Highest number of two lists-haskell - list

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
λ>

Related

Haskell: Merging a list where even indices are from list 1 and odd are from list 2. Fill with 0's if not the same size

i've tried to create a Haskell function that is merging 2 lists into a single list, where even indices in the new list are from list 1 and the odd are from list 2. Fill with 0's if not the same size.
For example:
[1] [10,15,20] => [1,10,0,15,0,20]
[2,3] [4,5] => [2,4,3,5]
I've tried to create a couple of versions but with no luck.
How can I create such a thing?
There is a interleave function, that does something similar, however, not exactly that. It 'merges' lists until one of them ends.
So you can write that function by yourself:
merge :: [Int] -> [Int] -> [Int]
merge (x:xs) (y:ys) = x : y : merge xs ys
merge (x:xs) [] = x : 0 : merge xs []
merge [] (y:ys) = 0 : y : merge [] ys
merge _ _ = []
When we have some elements on both sides, we take both of them. When one of elements is absent, we take 0 instead of it. In all other cases (it is the merge [] [] case) we end up with our recursion and return an empty list.
We can also slightly generalize our function to support any number-like type:
merge :: Num a => [a] -> [a] -> [a]
merge (x:xs) (y:ys) = x : y : merge xs ys
merge (x:xs) [] = x : 0 : merge xs []
merge [] (y:ys) = 0 : y : merge [] ys
merge _ _ = []
Also, we can go further and use def from Data.Default package to get the default value for our type, so we can use this function with not only lists of numbers:
import Data.Default
merge :: Default a => [a] -> [a] -> [a]
merge (x:xs) (y:ys) = x : y : merge xs ys
merge (x:xs) [] = x : def : merge xs []
merge [] (y:ys) = def : y : merge [] ys
merge _ _ = []
Using the idea from this answer of mine, using the transpose :: [[a]] -> [[a]] function,
interweaveWith :: a -> [a] -> [a] -> [a]
interweaveWith def xs ys =
-- 0 [1] [10,15,20] => [1,10,0,15,0,20]
concat $
zipWith const
(transpose [ xs ++ repeat def, -- no limit, padded with def
ys ++ repeat def ])
(transpose [xs, ys]) -- as long as the longest

How to combine list of lists with list of lists

I have lists of lists and need to combine it with another list of lists.
Example inputs:
A: [[1,2],[3,4],[5,6],[7,8]]
B: [[1,2],[3,4],[5,6],[7,8]]
Example output:
[[1,2,1,2],[1,2,3,4],..,[7,8,5,6],[7,8,7,8]]
2 lists of lists with 4 lists inside both would return us a list of lists size 4*4 = 16
I've tried just recursively combine the lists, but i know it wouldn't work even if would go through.
mergeAll [[]] [[]] = [[]]
mergeAll [[]] b = b
mergeAll a [[]] = a
mergeAll xs ys = mergeAll (merge xs ys) (drop 1 ys)
merge :: [[a]] -> [[a]] -> [[a]]
merge [[]] [[]] = [[]]
merge xs [[]] = xs
merge [[]] ys = ys
merge (x:xs) (y:ys) = ((x++y):xs)
You can use a list comprehension:
[ xs ++ ys | xs <- listOfLists1, ys <- listOfLists2 ]
You may do like
Prelude> let doit = \as bs -> as >>= \a -> bs >>= \b -> pure (a ++ b)
Prelude> doit [[1,2],[3,4],[5,6],[7,8]] [[1,2],[3,4],[5,6],[7,8]]
[[1,2,1,2],[1,2,3,4],[1,2,5,6],[1,2,7,8],[3,4,1,2],[3,4,3,4],[3,4,5,6],[3,4,7,8],[5,6,1,2],[5,6,3,4],[5,6,5,6],[5,6,7,8],[7,8,1,2],[7,8,3,4],[7,8,5,6],[7,8,7,8]]
As Robin says in a comment, you can also do it like:
liftA2 (++)
I ask my self a question trying to understand why that is equivalent to:
[xs ++ ys | xs <- xss, ys <- yss]

own nub function - how to use foldl/foldr?

Here is my own implementation of nub (remove duplicates):
nub :: (Eq a) => [a] -> [a]
nub lista = nub_rec lista []
where
nub_rec :: (Eq a) => [a] -> [a] -> [a]
nub_rec [] acc = acc
nub_rec (x:xs) acc = nub_rec (filter (\y -> if y == x then False else True) xs) (x:acc)
I consider how to use foldr/foldl to implement nub, could you help me ? I can't see a way.
First, your implementation of nub is bit more complex than it needs to be (and it reverses the order of elements in the list). Here's a simpler one:
myNub :: Eq a => [a] -> [a]
myNub (x:xs) = x : filter (/= x) (myNub xs)
myNub [] = []
Now, if we want to use foldr to write a function that will output, not just an "aggregate" but a full list, it's useful to first have a look at the simplest foldr-based function that takes in a list and spits out a list:
myNoop :: [a] -> [a]
myNoop l = foldr (\ x xs -> x : xs) [] l
Given that, the filter must be inserted somewhere. Since I assume this is a homework, I'll leave that to the OP as an exercise :)
Solution only with filter and foldr without direct (or self) recursion:
removeDuplicates :: Eq a => [a] -> [a]
removeDuplicates = foldr (\z ys -> z : filter (/= z) ys) []

How to insert a list in a list in all possible ways?

I am trying to enumerate all the possible merges of two lists.
In example inserting "bb" into "aaa" would look like
["bbaaa", "babaa", "baaba", "baaab", "abbaa", "ababa", "abaab", "aabba", "aabab", "aaabb"]
What I currently did is this
import Data.List
insert'' :: Char -> String -> [(String, String)] -> String
insert'' _ _ ([]) = []
insert'' h b ((x, y):xs) =
(x ++ [h] ++ (insert' (b, y))) ++ (insert'' h b xs)
insert' :: (String, String) -> String
insert' ([], ys) = ys
insert' (xs, ys) =
insert'' h b lists
where
h = head xs
b = tail xs
lists = zip (tails ys) (inits ys)
This returns for ("aaa", "bb")
"bbaaababaaabaababbaababaababbabababb"
a concatenated string, I tried making it a list of strings, but I just cannot wrap my head around this function. I always seems to get infinite type construction.
How could I rewrite the function, so it would return a list of strings?
An other implementation idea as in Daniel Wagners first post is to choose in each step a element from one of the lists and prepending it to the results generated by the function called with only the remaining parts of the list:
interleave :: [a] -> [a] -> [[a]]
interleave xs [] = [xs]
interleave [] ys = [ys]
interleave xs#(x : xs') ys#(y : ys') =
map (x :) (interleave xs' ys) ++ map (y :) (interleave xs ys')
For your intial example this produces:
ghci> interleave "bb" "aaa"
["bbaaa","babaa","baaba","baaab","abbaa","ababa","abaab","aabba","aabab","aaabb"]
Here is one implementation idea: for each element in the first list, we will choose (nondeterministically) a position in the second list to insert it, then recurse. For this to work, we first need a way to nondeterministically choose a position; thus:
choose :: [a] -> [([a], [a])]
choose = go [] where
go before xs = (before, xs) : case xs of
[] -> []
x:xs -> go (x:before) xs
For example:
> choose "abcd"
[("","abcd"),("a","bcd"),("ba","cd"),("cba","d"),("dcba","")]
Now we can use this tool to do the insertion:
insert :: [a] -> [a] -> [[a]]
insert [] ys = [ys]
insert (x:xs) ys = do
(before, after) <- choose ys
rest <- insert xs (reverse after)
return (before ++ [x] ++ rest)
In ghci:
> insert "ab" "cde"
["abcde","aebcd","adebc","acdeb","cabde","caebd","cadeb","dcabe","dcaeb","edcab"]
In this answer, I will give the minimal change needed to fix the code you already have (without completely rewriting your code). The first change needed is to update your type signatures to return lists of strings:
insert'' :: Char -> String -> [(String, String)] -> [String]
insert' :: (String, String) -> [String]
Now your compiler will complain that the first clause of insert' is returning a String instead of a [String], which is easily fixed:
insert' ([], ys) = [ys]
...and that the second clause of insert'' is trying to append a String to a [String] when running [h] ++ insert' (b, y). This one takes some thinking to figure out what you really meant; but my conclusion is that instead of x ++ [h] ++ insert' (b, y), you really want to run \t -> x ++ [h] ++ t for each element in insert' (b, y). Thus:
insert'' h b ((x, y):xs) =
(map (\t -> x ++ [h] ++ t) (insert' (b, y))) ++ (insert'' h b xs)
The complete final code is:
import Data.List
insert'' :: Char -> String -> [(String, String)] -> [String]
insert'' _ _ ([]) = []
insert'' h b ((x, y):xs) =
(map (\t -> x ++ [h] ++ t) (insert' (b, y))) ++ (insert'' h b xs)
insert' :: (String, String) -> [String]
insert' ([], ys) = [ys]
insert' (xs, ys) =
insert'' h b lists
where
h = head xs
b = tail xs
lists = zip (tails ys) (inits ys)
Now ghci will happily produce good answers:
> insert' ("aaa", "bb")
["bbaaa","babaa","baaba","baaab","abbaa","ababa","abaab","aabba","aabab","aaabb"]

Haskell own function to merge two lists

I need to write a function to merge two lists. Exactly like '++' is working.
let x = merge [1,2,3] [3,3,4] -- should output [1,2,3,3,3,4]
How should it be done?
Edit: solution is
merge :: [a] -> [a] -> [a]
merge [] ys = ys
merge (x:xs) ys = x : (merge xs ys)
Maybe something like this.
merge :: (a -> a -> Bool) -> [a] -> [a] -> [a]
merge pred xs [] = xs
merge pred [] ys = ys
merge pred (x:xs) (y:ys) =
case pred x y of
True -> x: merge pred xs (y:ys)
False -> y: merge pred (x:xs) ys
(++) xs ys = merge (\x y -> compare x y == LT) xs ys
Or, if you just need to repeat the functionality of (++), you can look up it's definition with hoogle which eventually leads you to the source code
(++) [] ys = ys
(++) (x:xs) ys = x : xs ++ ys