I have a function with this type:
calculator :: [Float] -> [Int] -> Float
and I need:
Helper :: [String] -> [[Int]] -> [Float] -> [(String, Float)]
Following problem is given:
I just want to take every 2nd element of the [[Int]]
e.g.: I have an given Int [[1,0], [2,0], [3,0]].
I want to get the first element of each list in a list to put it into my calculator.
My idea was to concat the list of [Int].
e.g.:
[[1,0], [2,0], [3,0]].
concat [[1,0], [2,0], [3,0]] => [1,0,2,0,3,0]
I want this without the "0" values, due this is an indice which i dont need.
How can i remove every 2nd value in a list?
Is that possible with a higher order function?
The thinking goes like this: first, an empty list with every second value removed would be an empty list. Let's write that down:
withoutEverySecondValue [] = []
Now, if a list that consists of two values x and y, and then some tail xs, then to remove every second value from such list would mean (1) ignore y, (2) remove every second value from the tail xs, and (3) prepend x to the result of that. Let's write that down:
withoutEverySecondValue (x:y:xs) = x : withoutEverySecondValue xs
And that's it! Just add a type signature, and you're done!
withoutEverySecondValue :: [a] -> [a]
withoutEverySecondValue [] = []
withoutEverySecondValue (x:y:xs) = x : withoutEverySecondValue xs
There's one thing missing here though: what if a list is not empty, but also doesn't have two elements x and y? What should the result be then? I'll leave determining and writing that down as an exercise.
This function will give you all but the 2nd element of a list:
allBut2nd :: [a] -> [a]
allBut2nd [] = []
allBut2nd list = head list : tail (tail list)
Related
I am fairly new at Haskell and have been trying to solve this.
I have been trying to take a list of pairs and condense it down to a single list
For example if I had the pairs:
[(2,0),(4,5),(3,10)]
The list should return
[2,0,0,0,0,4,0,0,0,0,3]
The idea is that the first element of the pair is the value and the second value is the index.
Here is what I have tried so far:
finalList :: [(Int,Int)] -> [Int]
finalList ((x,y): xs) = replicate y 0 ++ [x] ++ finalList xs
finalList _ = []
However with this issue I am not getting the desired padding of 0s that I would like to have . I am instead getting something like:
[6,0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,0,12]
Any help would be greatly appreciated! Thanks!
I will provide a hint. I will also assume that the indices in the input list are in increasing order.
A possible approach is to first define an auxiliary function that takes one more argument, an "index" counting how many elements we have produces so far. Here is a sketch of a part of the code you might use.
f :: [(Int,Int)] -> Int -> [Int]
f [] _ = ... -- base case
f ((value, pos):xs) ix
| ix == pos = value : ... -- here we recurse
| otherwise = 0 : ... -- here we recurse too
Roughly put, the logic above is: keep track of the current position ix: if the position is the wanted one pos, emit value. Otherwise emit 0 as a filler.
In both cases we recurse, and we need to increment the current position ix. The current position is will be initially set to zero as follows:
finalList :: [(Int,Int)] -> [Int]
finalList xs = f xs 0
Note that when we recurse, we also need to understand what to do with the input list. I will leave that to you.
I am trying to transform an input list into a palindrome. For instance:
Input: [1,2,3]
Output: [1,2,3,3,2,1]
Basically I need to add a reversed list. My problem lies in the following:
palindrize::[a]->[a]
palindrize list | null list = []
palindrize (x:xs)=(x:xs)++revert(x:xs) where
revert list | null list =[]
revert (x:xs)= (revert xs):(x:[]) ---Here
How can I create a guard or a condition to when there is only one element create a list out of it (applying the (myelement:[]))? I would need somehow to say: revert can get a list or an element, if it's an element apply (element:[]) on it.
I think you make things too complex. First of all, Haskell has already a reverse :: [a] -> [a] that reverses the list, so we can make it:
palindrize :: [a] -> [a]
palindrize l = l ++ reverse l
Furthermore there is no need to use a guard here. We can perform pattern matching: this is safer since the compiler can then guarantee us that all patterns are covered. So we can write it like:
revert :: [a] -> [a]
revert [] = []
revert (x:xs) = (revert xs):(x:[]) -- error!
But this will result in a type error. Indeed, the (:) constructor has type (:) :: a -> [a] -> [a], but revert xs will result in type [a]. In situations like that one, it is best to use an accumulator: a parameter that we initialize for instance with the empty list, and then each recursive call update and at the end of the recursive process return. For example:
revert :: [a] -> [a]
revert = go []
where go xs [] = xs
go xs (x:ys) = go (x:xs) ys
First, you can not write list : element, nor list : (element : []) since types would not match: whatever is found at the left side of : must have the same type as the elements of the list found at the right side.
You can, however, append two lists using ++, like list ++ (element : []) or list ++ [element].
Second, to pattern match against a single element list, you can use
foo [] = ... -- empty list case
foo [x] = ... -- single element list case
foo (x1:x2:rest) = ... -- two elements or more case
If you prefer, the single element case can also be written foo (x:[]) = ....
Note that foo [] = ... is equivalent to foo list | null list = ..., but simpler. If possible, forget guards: they should only be used when pattern matching is not enough.
I'm trying to sequence a list of (Int, Int) tuples into a list of int lists [[Int]]
Why? I've found many use cases for this. Basically given a list like so:
[(1,5), (2,3), (3,4), (4,5), (6,7), (7,8)]
I want to return a list:
[[1,2,3,4,5],[6,7,8]]
Here's what I have so far:
pieces :: [(Int, Int)]
pieces = [(1,5), (2,3), (3,4), (4,5), (6,7), (7,8)]
linkStep :: [[Int]] -> (Int, Int) -> [[Int]]
linkStep (x:xs) (a, b)
| elem a x = (b : x) : xs
| elem b x = (a : x) : xs
| otherwise = (a : b : x) : xs
-- Now I fold the linkStep function over the list
links :: [(Int, Int)] -> [[Int]]
links list = foldl linkStep [[]] list
However when I call links with pieces I get
links pieces
--[[8,6,7,5,4,2,3,1,5]]
I'm not really sure what I'm doing wrong. The linkStep function is supposed to concatenate a tuple element that is in the resulting list to the target list in the result. If the tuple element is not yet in the resulting list a new list with the tuple element is added. But its not working... Please help!
There are a couple of issues that I see:
In linkStep, you only ever check if your tuple elements are members of the first inner list. From your example, it looks as if you're going to need to check all the lists, not just the first one.
In the cases of linkStep, you always add a, b, or both a and b to the first inner list. Thus all elements will eventually end up in the first list. Maybe you meant to create a new list here instead? But it might also be a good place to consider other lists than the first.
Hopefully this will help you to make progress.
The language I'm using is a subset of Haskell called Core Haskell which does not allow the use of the built-in functions of Haskell. For example, if I were to create a function which counts the number of times that the item x appears in the list xs, then I would write:
count = \x ->
\xs -> if null xs
then 0
else if x == head xs
then 1 + count x(tail xs)
else count x(tail xs)
I'm trying to create a function which outputs a list xs with its duplicate values removed. E.g. remdups (7:7:7:4:5:7:4:4:[]) => (7:4:5:[])
can anyone offer any advice?
Thanks!
I'm guessing that you're a student, and this is a homework problem, so I'll give you part of the answer and let you finish it. In order to write remdups, it would be useful to have a function that tells us if a list contains an element. We can do that using recursion. When using recursion, start by asking yourself what the "base case", or simplest possible case is. Well, when the list is empty, then obviously the answer is False (no matter what the character is). So now, what if the list isn't empty? We can check if the first character in the list is a match. If it is, then we know that the answer is True. Otherwise, we need to check the rest of the list -- which we do by calling the function again.
elem _ [] = False
elem x (y:ys) = if x==y
then True
else elem x ys
The underscore (_) simply means "I'm not going to use this variable, so I won't even bother to give it a name." That can be written more succinctly as:
elem _ [] = False
elem x (y:ys) = x==y || elem x ys
Writing remdups is a little tricky, but I suspect your teacher gave you some hints. One way to approach it is to imagine we're partway through processing the list. We have part of the list that hasn't been processed yet, and part of the list that has been processed (and doesn't contain any duplicates). Suppose we had a function called remdupHelper, which takes those two arguments, called remaining and finished. It would look at the first character in remaining, and return a different result depending on whether or not that character is in finished. (That result could call remdupHelper recursively). Can you write remdupHelper?
remdupHelper = ???
Once you have remdupHelper, you're ready to write remdups. It just invokes remdupHelper in the initial condition, where none of the list has been processed yet:
remdups l = remdupHelper l [] -- '
This works with Ints:
removeDuplicates :: [Int] -> [Int]
removeDuplicates = foldr insertIfNotMember []
where
insertIfNotMember item list = if (notMember item list)
then item : list
else list
notMember :: Int -> [Int] -> Bool
notMember item [] = True
notMember item (x:xs)
| item == x = False
| otherwise = notMember item xs
How it works should be obvious. The only "tricky" part is that the type of foldr is:
(a -> b -> b) -> b -> [a] -> b
but in this case b unifies with [a], so it becomes:
(a -> [a] -> [a]) -> [a] -> [a] -> [a]
and therefore, you can pass the function insertIfNotMember, which is of type:
Int -> [Int] -> [Int] -- a unifies with Int
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.