Matching list of lists with other list of lists - haskell

Hey guys I have a question about matching lists
Given the list of lists:
Input List 1 = [[True],[False],[True],[[False]]
Input List 2 = [[Bob],[Rick],[Lee],[Bill]]
Input List 3 = [[1],[2],[3],[4]]
Then match the Booleans of list 1 with the other lists so this happens:
Input List 1 + Input List 2 = [[Bob],[Dead],[Lee],[Dead]]
Input List 1 + Input List 2 = [[1],[0],[3],[0]]

As far as I can see, using nested lists here is unnecessary. Without them, all you need is zipWith and an appropriate combining function:
-- The first argument is the "dead" value. Note that this works with any type.
makeDead :: a -> Bool -> a -> a
makeDead dead b val
| b = val
| otherwise = dead
GHCi> :t zipWith
zipWith :: (a -> b -> c) -> [a] -> [b] -> [c]
GHCi> zipWith (makeDead "Dead") [True,False,True,False] ["Bob","Rick","Lee","Bill"]
["Bob","Dead","Lee","Dead"]
Two variations on the theme. Firstly, if whether a value should be changed depends only on what the value is, then you can simply use map/fmap:
-- Affects all names with 'i' as the second letter:
lethalLetter :: String -> String
lethalLetter name -> case name of
(_:'i':_) -> "Dead"
_ -> name
GHCi> fmap lethalLetter ["Bob", "Rick", "Lee", "Bill"]
["Bob","Dead","Lee","Dead"]
Secondly, you might prefer using Maybe to indicate deadness rather than using an arbitrary value (what if someone is actually called "Dead")?
makeDead' :: Bool -> a -> Maybe a
makeDead' b val
| b = Just val
| otherwise = Nothing
GHCi> zipWith makeDead' [True,False,True,False] ["Bob","Rick","Lee","Bill"]
[Just "Bob",Nothing,Just "Lee",Nothing]
You can then use functions like maybe, fromMaybe and catMaybes (the latter two are in Data.Maybe) to get rid of the Nothings however you feel like doing it:
GHCi> import Data.Maybe
GHCi> foo = zipWith makeDead' [True,False,True,False] ["Bob","Rick","Lee","Bill"]
GHCi> catMaybes foo
["Bob","Lee"]

Assuming you change them to lists, as recommended by duplode, how about zipping together the two lists within a list comprehension, something like this:
[if flag then val else defaultVal | (flag, val) <- zip(list1, list2)]
where defaultVal would have to be specified, but seems to be Dead and 0 for lists 2 and 3.
(I don't have access right now to Haskell, so the syntax may not be 100% there, but that's the idea.)

You can use zipWith . zipWith :: (a -> b -> c) -> [[a]] -> [[b]] -> [[c]] for matching lists of lists. For example:
import Data.Bool (bool)
kill deadVal = zipWith . zipWith $ bool (const deadVal) id
example = kill 0 [[True, False],[False,True]] [[1,2,3],[2]]
-- example = [[1,0],[0]]

Related

Haskell How to return a list of int from two int list

if list1 = [14,24,1,2,11,7,23,8,12,22,20,0,15,19,4,9,10,21,18,17,3,13,16,5,6,25],
and list2 = [14,14,24,24,1,1,2,2]
How could I return a int list which is [0,0,1,1,2,2,3,3]
I have used the function
elemIndex' :: Eq a => a -> [a] -> Int
elemIndex' x = fromMaybe (-1) . elemIndex x
and the result for this for the first one
0
to get the index from list 1 for a single digit
But what I want is
findIndex :: [Int] -> [Int] -> [Int]
That would input two int list and return the index value base on the key list
How could I recursively get the index for one list or using any import function, such as map.
You've done a very good job of breaking the problem down. You've already recognized that you're doing the same thing for each element of the second list, and you've written a function to capture that behavior.
elemIndex' :: Eq a => a -> [a] -> Int
elemIndex' x = fromMaybe (-1) . elemIndex x
Now you want to take this function and apply it to each element of another list, collecting the results into a new list. That is, you want something that looks like
mystery :: (a -> b) -> [a] -> [b]
And we can search Hoogle and find exactly that function: map
map :: (a -> b) -> [a] -> [b]
map takes a function and a list and applies it to each element. You've got a function (elemIndex', with appropriate partial application), and you've got a list (list2 in your example). So let's put it together.
findAll :: Eq a => [a] -> [a] -> [Int]
findAll haystack needles = map (\x -> elemIndex' x haystack) needles
There are lots of streaming functions in Haskell like map, and knowing / figuring out which one to use in a given situation comes with practice. If you're ever in doubt, remember that you can use Hoogle to search for a type or you can simply do whatever you're trying to do recursively (if you didn't know map existed, you could write it yourself with a bit of recursion), and you'll get the hang of it over time. Good luck in your Haskell endeavors!
As an alternative to the answer by #SilvioMayolo, you could use a Map data structure. We zip in the indexes for each value in list1 and then turn that into a map, then just do a lookup for each value in list2.
import Data.Map
import Data.List
list1 = [14,24,1,2,11,7,23,8,12,22,20,0,15,19,4,9,10,21,18,17,3,13,16,5,6,25]
list2 = [14,14,24,24,1,1,2,2]
map1 = Data.Map.fromList $ list1 `zip` [0..]
-- fromList [(0,11),(1,2),(2,3),(3,20),(4,14),(5,23),(6,24),
-- (7,5),(8,7),(9,15),(10,16),(11,4),(12,8),(13,21),
-- (14,0),(15,12),(16,22),(17,19),(18,18),(19,13),
-- (20,10),(21,17),(22,9),(23,6),(24,1),(25,25)]
list3 = Data.List.map (map1 !) list2
-- [0,0,1,1,2,2,3,3]

Removing specific elements from lists in Haskell

I'm having a hard time getting Haskell and functional programming together in my head. What I am trying to do is manipulate a string so that I am printing/returning specific characters each time based on a number given. For example:
printing "testing" 2 = "etn"
printing "testing" 3 = "sn"
I've read a lot online, and from what I understand I can achieve this with filtering and cycling, but I cannot get/understand the syntax of this language to get a working program.
I'll try to describe my thought process so you can follow. This function fits the pattern of creating an output list (here a string) from an input seed (here a string) by repeated function application (here dropping some elements). Thus I choose an implementation with Data.List.unfoldr.
unfoldr :: (b -> Maybe (a, b)) -> b -> [a]
Okay so, I need to turn the seed b into (Maybe) an output a and the rest of the string. I'll call this subfunction f and pass it into unfoldr.
printing s n = unfoldr f s
where f b = case drop n b of
[] -> Nothing
(x:xs) -> Just (x,xs)
It turns out that attempting to take the head off the front of the list and returning a Maybe is also a common pattern. It's Data.List.uncons, so
printing s n = unfoldr (uncons . drop n) s
Very smooth! So I test it out, and the output is wrong! Your specified output actually eg. for n=2 selects every 2nd character, ie. drops (n-1) characters.
printing s n = unfoldr (uncons . drop (n-1)) s
I test it again and it matches the desired output. Phew!
To demonstrate the Haskell language some alternative solutions to the accepted answer.
Using list comprehension:
printing :: Int -> String -> String
printing j ls = [s | (i, s) <- zip [1 .. ] ls, mod i j == 0]
Using recursion:
printing' :: Int -> String -> String
printing' n ls
| null ls' = []
| otherwise = x : printing' n xs
where
ls' = drop (n - 1) ls
(x : xs) = ls'
In both cases I flipped the arguments so it is easier to do partial application: printing 5 for example is a new function and will give each 5th character when applied to a string.
Note with a minor modification they will work for any list
takeEvery :: Int -> [a] -> [a]

Haskell mix two lists

Im about to write my first haskell program, so I need your help. I want to interlink two lists. For example;
a = [4,8,20]
b = [3,5,17,56,89,30]
interlink a b = [4,3,8,5,20,17,56,89,30]
The resulting list must cointain the elements of List a and b alternately. If one List is longer then the elements of the longer list should be added to the result list after the shorter list mashed up with the elements of the longer list. I think you saw that in my example above.
Now how do i do this in Haskell??
My start
mix :: [a]->[a]->[a]
mix (x:l1) (y:l2) = (x:y:[])
mix [] [] = []
Please, can you help me??
I do not have an interpreter available to use as I am on a different computer to usual, but here is some code:
mix :: [a] -> [a] -> [a]
mix (x:xs) (y:ys) = x : y : mix xs ys
mix x [] = x
mix [] y = y
Edit: I just tested this online, I believe it works.
So there are two functions transpose and concat.
-- transpose :: [[a]] -> [[a]]
-- concat :: Foldable t => t [a] -> [a]
Since List already has an instance of Foldable this ends up being one line of code like so:
concat . transpose $ a : b : []
or
concat . transpose $ [a,b]
The first step is to create a list of lists with transpose like so
λ> transpose $ [a, b]
[[4,3],[8,5],[20,17],[56],[89],[30]]
which we then collapse into one.
The secret here is to use function composition. The . is a function that takes two functions and calls one after the other creating a larger function so:
(.) :: (b -> c) -> (a -> b) -> a -> c
means: take the result of the first function, transpose, and feed it to the next one, concat.
We can chain as many functions as we wish as long as the types allow it.
In our case the composition creates a function [a] -> [a] -> [a]

How to get all subnumbers of a number in haskell

I would like to get all sub numbers of a number from a particular side.
In the case of the number 1234, the sub numbers from the left side are:
1, 12, 123, 1234
I implemented it with:
tail . inits $ show 1234
This way I get all the sub numbers in [[Char]] format.
["1","12","123","1234"]
I tried to convert them to Integer, with the following line.
map read . tail . inits $ show 1234
But I get the following error
[*** Exception: Prelude.read: no parse
What am I doing wrong?
because the interpreter does not know what type you want back
this will work:
λ> map read . tail . inits $ show 1234 :: [Int]
[1,12,123,1234]
of course you can just add a type-signature as well (most likely in your code file):
subnums :: Int -> [Int]
subnums = map read . tail . inits . show
in ghci:
λ> subnums 1234
[1,12,123,1234]
and a nice exercise can be to do this without show/read:
subnumbers :: Int -> [Int]
subnumbers 0 = []
subnumbers n =
n : subnumbers (n `div` 10)
Can you solve the problem with the order here?
A good approach is to use an unfold. While a fold (variously known as reduce, accumulate or aggregate in other languages) can process a list of numbers (or values of other types) to compute a single result value, an unfold starts with a single value and expands it into a list of values according to a given function. Let us examine the type of an unfold function:
Data.List.unfoldr :: (b -> Maybe (a, b)) -> b -> [a]
We see that unfoldr take a function (b -> Maybe (a, b), and a starting b. The result is a [a]. If the function evaluates to Just (a, b), the a will be appended to the result, and the unfold recurses with the new b. If the function evaluates to Nothing, the unfold is complete.
The function for your unfold is:
f :: Integral b => b -> Maybe (b, b)
f x = if x > 0
then Just (x, x `div` 10) -- append x to result; continue with x/10
else Nothing -- x = 0; we're done
Now we can solve your problem without any of this show and read hackery:
λ> let f = (\x -> if x > 0 then Just (x, x `div` 10) else Nothing)
λ> reverse $ unfoldr f 1234
[1,12,123,1234]
As Carsten suggests, you need to give some indication of what type you want. This is because read is polymorphic in its result type. Until the compiler knows what type you want, it doesn't know what parser to use! An explicit type annotation is usually the way to go, but you might sometimes consider the function
asTypeOf :: a -> a -> a
asTypeOf x _ = x
how to use this here
I see two obvious ways to use asTypeOf here:
λ> asTypeOf (map read . tail . inits $ show 1234) ([0] :: [Int])
[1,12,123,1234]
and
λ> map (asTypeOf read length) . tail . inits $ show 1234
[1,12,123,1234]
the first one seems hardly better at all and the second might be a bit tricky for beginners - but it works ;)
Why? Because length has type [a] -> Int and so the result type will be fixed to Int:
λ> :t (`asTypeOf` length)
(`asTypeOf` length) :: ([a] -> Int) -> [a] -> Int
which is just what we need for read
Please note that it's not important what length does - only it's type is important - any other function with an compatible signature would have worked as well (although I can come up only with length right now)
For example:
wantInt :: [a] -> Int
wantInt = undefined
λ> map (asTypeOf read wantInt) . tail . inits $ show 1234
[1,12,123,1234]
A working list comprehension solution:
subNums :: Int -> [Int]
subNums num = [read x | let str = show num, let size = length str, n <- [1 .. size], let x = take n str]
λ> subNums 1234
[1,12,123,1234]

Compute Most Frequent Occurance of Numbers of A Sorted List in Haskell

The question is to compute the mode (the value that occurs most frequently) of a sorted list of integers.
[1,1,1,1,2,2,3,3] -> 1
[2,2,3,3,3,3,4,4,8,8,8,8] -> 3 or 8
[3,3,3,3,4,4,5,5,6,6] -> 3
Just use the Prelude library.
Are the functions filter, map, foldr in Prelude library?
Starting from the beginning.
You want to make a pass through a sequence and get the maximum frequency of an integer.
This sounds like a job for fold, as fold goes through a sequence aggregating a value along the way before giving you a final result.
foldl :: (a -> b -> a) -> a -> [b] -> a
The type of foldl is shown above. We can fill in some of that already (I find that helps me work out what types I need)
foldl :: (a -> Int -> a) -> a -> [Int] -> a
We need to fold something through that to get the value. We have to keep track of the current run and the current count
data BestRun = BestRun {
currentNum :: Int,
occurrences :: Int,
bestNum :: Int,
bestOccurrences :: Int
}
So now we can fill in a bit more:
foldl :: (BestRun -> Int -> BestRun) -> BestRun -> [Int] -> BestRun
So we want a function that does the aggregation
f :: BestRun -> Int -> BestRun
f (BestRun current occ best bestOcc) x
| x == current = (BestRun current (occ + 1) best bestOcc) -- continuing current sequence
| occ > bestOcc = (BestRun x 1 current occ) -- a new best sequence
| otherwise = (BestRun x 1 best bestOcc) -- new sequence
So now we can write the function using foldl as
bestRun :: [Int] -> Int
bestRun xs = bestNum (foldl f (BestRun 0 0 0 0) xs)
Are the functions filter, map, foldr in Prelude library?
Stop...Hoogle time!
Did you know Hoogle tells you which module a function is from? Hoolging map results in this information on the search page:
map :: (a -> b) -> [a] -> [b]
base Prelude, base Data.List
This means map is defined both in Prelude and in Data.List. You can hoogle the other functions and likewise see that they are indeed in Prelude.
You can also look at Haskell 2010 > Standard Prelude or the Prelude hackage docs.
So we are allowed to map, filter, and foldr, as well as anything else in Prelude. That's good. Let's start with Landei's idea, to turn the list into a list of lists.
groupSorted :: [a] -> [[a]]
groupSorted = undefined
-- groupSorted [1,1,2,2,3,3] ==> [[1,1],[2,2],[3,3]]
How are we supposed to implement groupSorted? Well, I dunno. Let's think about that later. Pretend that we've implemented it. How would we use it to get the correct solution? I'm assuming it is OK to choose just one correct solution, in the event that there is more than one (as in your second example).
mode :: [a] -> a
mode xs = doSomething (groupSorted xs)
where doSomething :: [[a]] -> a
doSomething = undefined
-- doSomething [[1],[2],[3,3]] ==> 3
-- mode [1,2,3,3] ==> 3
We need to do something after we use groupSorted on the list. But what? Well...we should find the longest list in the list of lists. Right? That would tell us which element appears the most in the original list. Then, once we find the longest sublist, we want to return the element inside it.
chooseLongest :: [[a]] -> a
chooseLongest xs = head $ chooseBy (\ys -> length ys) xs
where chooseBy :: ([a] -> b) -> [[a]] -> a
chooseBy f zs = undefined
-- chooseBy length [[1],[2],[3,3]] ==> [3,3]
-- chooseLongest [[1],[2],[3,3]] ==> 3
chooseLongest is the doSomething from before. The idea is that we want to choose the best list in the list of lists xs, and then take one of its elements (its head does just fine). I defined this by creating a more general function, chooseBy, which uses a function (in this case, we use the length function) to determine which choice is best.
Now we're at the "hard" part. Folds. chooseBy and groupSorted are both folds. I'll step you through groupSorted, and leave chooseBy up to you.
How to write your own folds
We know groupSorted is a fold, because it consumes the entire list, and produces something entirely new.
groupSorted :: [Int] -> [[Int]]
groupSorted xs = foldr step start xs
where step :: Int -> [[Int]] -> [[Int]]
step = undefined
start :: [[Int]]
start = undefined
We need to choose an initial value, start, and a stepping function step. We know their types because the type of foldr is (a -> b -> b) -> b -> [a] -> b, and in this case, a is Int (because xs is [Int], which lines up with [a]), and the b we want to end up with is [[Int]].
Now remember, the stepping function will inspect the elements of the list, one by one, and use step to fuse them into an accumulator. I will call the currently inspected element v, and the accumulator acc.
step v acc = undefined
Remember, in theory, foldr works its way from right to left. So suppose we have the list [1,2,3,3]. Let's step through the algorithm, starting with the rightmost 3 and working our way left.
step 3 start = [[3]]
Whatever start is, when we combine it with 3 it should end up as [[3]]. We know this because if the original input list to groupSorted were simply [3], then we would want [[3]] as a result. However, it isn't just [3]. Let's pretend now that it's just [3,3]. [[3]] is the new accumulator, and the result we would want is [[3,3]].
step 3 [[3]] = [[3,3]]
What should we do with these inputs? Well, we should tack the 3 onto that inner list. But what about the next step?
step 2 [[3,3]] = [[2],[3,3]]
In this case, we should create a new list with 2 in it.
step 1 [[2],[3,3]] = [[1],[2],[3,3]]
Just like last time, in this case we should create a new list with 1 inside of it.
At this point we have traversed the entire input list, and have our final result. So how do we define step? There appear to be two cases, depending on a comparison between v and acc.
step v acc#((x:xs):xss) | v == x = (v:x:xs) : xss
| otherwise = [v] : acc
In one case, v is the same as the head of the first sublist in acc. In that case we prepend v to that same sublist. But if such is not the case, then we put v in its own list and prepend that to acc. So what should start be? Well, it needs special treatment; let's just use [] and add a special pattern match for it.
step elem [] = [[elem]]
start = []
And there you have it. All you have to do to write your on fold is determine what start and step are, and you're done. With some cleanup and eta reduction:
groupSorted = foldr step []
where step v [] = [[v]]
step v acc#((x:xs):xss)
| v == x = (v:x:xs) : xss
| otherwise = [v] : acc
This may not be the most efficient solution, but it works, and if you later need to optimize, you at least have an idea of how this function works.
I don't want to spoil all the fun, but a group function would be helpful. Unfortunately it is defined in Data.List, so you need to write your own. One possible way would be:
-- corrected version, see comments
grp [] = []
grp (x:xs) = let a = takeWhile (==x) xs
b = dropWhile (==x) xs
in (x : a) : grp b
E.g. grp [1,1,2,2,3,3,3] gives [[1,1],[2,2],[3,3,3]]. I think from there you can find the solution yourself.
I'd try the following:
mostFrequent = snd . foldl1 max . map mark . group
where
mark (a:as) = (1 + length as, a)
mark [] = error "cannot happen" -- because made by group
Note that it works for any finite list that contains orderable elements, not just integers.

Resources