Related
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]
I need to take the elements of a list and put them into two seperate lists of odd and evens in haskell. Here is what I have so far.
classEvenOdd :: [Int] -> ([Int], [Int])
classEvenOdd [] = ([] , [])
classEvenOdd (x:xs) = (even [xs] | odd [xs])
The error is as follows:
ERROR "new_1.hs":62 - Type error in explicitly typed binding
*** Term : classEvenOdd
*** Type : [Int] -> [a]
*** Does not match : [Int] -> ([Int],[Int])
I'm not quite sure how your code works but I'll work you through my approach to making the function. When I thought about it I thought about doing this:
classEvenOdd :: [Int] -> ([Int],[Int])
classEvenOdd xs = (filter odd xs, filter even xs)
But that requires the list to be filtered through twice and thus double the time taken to execute*. So we want to define a function over the list that sorts it into the two lists. This sounds like we want a list of Eithers ([Either Int Int]). The list can then be converted into the tuple (([Int],[Int])) using partitionEithers ().
import Data.Either
classEvenOdd' :: [Int] -> ([Int],[Int])
classEvenOdd' xs = partitionEithers (map eitherEvenOdd xs)
eitherEvenOdd :: Int -> Either Int Int
eitherEvenOdd i
| even i = Right i
| odd i = Left i
This can also be done point free
import Data.Either
classEvenOdd' :: [Int] -> ([Int],[Int])
classEvenOdd' = partitionEithers.(map eitherEvenOdd)
eitherEvenOdd :: Int -> Either Int Int
eitherEvenOdd i
| even i = Right i
| odd i = Left i
*Subject to non-strictness
The error you are getting stems from the line:
classEvenOdd [] = []
This snippet, on it's own, has the type
classEvenOdd :: [a] -> [a]
which is not the type you stated (classEvenOdd :: [Int] -> ([Int],[Int])). Your base case is solved by changing the type to:
classEvenOdd [] = ([], []).
However, there is an additional error in your code, even once this issue has been solved. You do not keep the x value at the head of your list, so once any syntax issues have been solved (as the syntax in the latter snippet looks unfamiliar to me) you will always end up with empty lists!
You should either keep a partial result and continue passing that down as you check each element of your input list, or you should assume the completion of the sub-list xs and then add the result to the correct element of the tuple.
This second approach would look like this:
classEvenOdd :: [Int] -> ([Int], [Int])
classEvenOdd [] = ([], [])
classEvenOdd (x:xs) = let (evens, odds) = classEvenOdd xs in if even x
then (x:evens, odds)
else (evens, x:odds)
However, this approach will leak space (at least without optimisations turned on) due to relying on the completed value at every stage.
A better approach is to carry the partial result as an extra parameter:
classEvenOdd :: [Int] -> ([Int], [Int])
classEvenOdd [] = ([], [])
classEvenOdd x = go ([], []) x
where go (e,o) (x:xs) = if even x
then go xs (x:e, o)
else go xs (e, x:o)
go (e,o) [] = (e, o)
isTogether' :: String -> Bool
isTogether' (x:xs) = isTogether (head xs) (head (tail xs))
For the above code, I want to go through every character in the string. I am not allowed to use recursion.
isTogether' (x:xs) = isTogether (head xs) (head (tail xs))
If I've got it right, you are interested in getting consequential char pairs from some string. So, for example, for abcd you need to test (a,b), (b,c), (c,d) with some (Char,Char) -> Bool or Char -> Char -> Bool function.
Zip could be helpful here:
> let x = "abcd"
> let pairs = zip x (tail x)
it :: [(Char, Char)]
And for some f :: Char -> Char -> Bool function we can get uncurry f :: (Char, Char) -> Bool.
And then it's easy to get [Bool] value of results with map (uncurry f) pairs :: [Bool].
In Haskell, a String is just a list of characters ([Char]). Thus, all of the normal higher-order list functions like map work on strings. So you can use whichever higher-order function is most applicable to your problem.
Note that these functions themselves are defined recursively; in fact, there is no way to go through the entire list in Haskell without either recursing explicitly or using a function that directly or indirectly recurses.
To do this without recursion, you will need to use a higher order function or a list comprehension. I don't understand what you're trying to accomplish so I can only give generic advice. You probably will want one of these:
map :: (a -> b) -> [a] -> [b]
Map converts a list of one type into another. Using map lets you perform the same action on every element of the list, given a function that operates on the kinds of things you have in the list.
filter :: (a -> Bool) -> [a] -> [a]
Filter takes a list and a predicate, and gives you a new list with only the elements that satisfy the predicate. Just with these two tools, you can do some pretty interesting things:
import Data.Char
map toUpper (filter isLower "A quick test") -- => "QUICKTEST"
Then you have folds of various sorts. A fold is really a generic higher order function for doing recursion on some type, so using it takes a bit of getting used to, but you can accomplish pretty much any recursive function on a list with a fold instead. The basic type of foldr looks like this:
foldr :: (a -> b -> b) -> b -> [a] -> b
It takes three arguments: an inductive step, a base case and a value you want to fold. Or, in less mathematical terms, you could think of it as taking an initial state, a function to take the next item and the previous state to produce the next state, and the list of values. It then returns the final state it arrived at. You can do some pretty surprising things with fold, but let's say you want to detect if a list has a run of two or more of the same item. This would be hard to express with map and filter (impossible?), but it's easy with recursion:
hasTwins :: (Eq a) => [a] -> Bool
hasTwins (x:y:xs) | x == y = True
hasTwins (x:y:xs) | otherwise = hasTwins (y:xs)
hasTwins _ = False
Well, you can express this with a fold like so:
hasTwins :: (Eq a) => [a] -> Bool
hasTwins (x:xs) = snd $ foldr step (x, False) xs
where
step x (prev, seenTwins) = (x, prev == x || seenTwins)
So my "state" in this fold is the previous value and whether we've already seen a pair of identical values. The function has no explicit recursion, but my step function passes the current x value along to the next invocation through the state as the previous value. But you don't have to be happy with the last state you have; this function takes the second value out of the state and returns that as the overall return value—which is the boolean whether or not we've seen two identical values next to each other.
EDIT FOR CLARITY: I know what the 'head of empty list' error is and why it is thrown. What I don't know is why there is no error when I use 'elem' but there is if I use 'mElem'. That's the only change I make to cause the error.
If I use the 'Prelude.elem' function the program runs but with one small error. I wrote my version of 'elem' (mElem) to counter this error. I looked at the source code for 'elem' and wrote my function in a similar style. However, the program crashes due to a 'head of empty list error' resulting from the function 'getExisting'
genTupleCount :: [F.Record] -> [(String, Int)] -> [(String, Int)]
genTupleCount [] tuples = tuples
genTupleCount (x:xs) tuples | mElem (F.club x) (map fst tuples) = genTupleCount xs $ getNewTuples tuples existing
| otherwise = genTupleCount xs $ (F.club x, 1):tuples
where
existing = getExisting x tuples
getExisting :: F.Record -> [(String, Int)] -> (String, Int)
getExisting x tuples = head $ filter ((==F.club x).fst) tuples
getNewTuples :: [(String, Int)] -> (String, Int) -> [(String, Int)]
getNewTuples old e = (fst e, 1 + (snd e)):(delete e old)
mElem :: String -> [String] -> Bool
mElem _ [] = False
mElem str (x:xs) = (map toLower str) == (map toLower x) || mElem str xs
As Matt Fenwick said, you're assuming there is an element that satisfies your condition. I suggest using find instead:
getExisting :: F.Record -> [(String, Int)] -> Maybe (String, Int)
getExisting x = find ((==F.club x).fst)
This handles the case of there not being any such element by returning Nothing, and let's you skip mElem entirely; just check the result of getExisting to find out whether there is any such element, and if there is, what its value is.
As to why using mElem instead of elem causes your program to crash, it is because it does not verify that there is an element that satisfies the condition getExisting searches for. getExisting doesn't normalise the capitalisation as mElem does, so if nElem returns True only because of its case-folding, then the call to getExisting will occur, and it will perform head on the empty list, because filter will find no elements matching getExisting's stricter condition.
The find solution avoids this potential for error, since it only has the condition in one place.
Your function getExisting assumes that the result of filter ((==F.club x).fst) tuples has at least one element.
Example:
Prelude> head [3,4]
3
Prelude> head []
*** Exception: Prelude.head: empty list
It looks like switching to mElem causes an empty list to eventually be passed to head. Apparently, this doesn't happen using elem.
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.