Count elements on ordered list - list

I want to do a Haskell function where the input (a list of Strings) is ordered (always. input is valid only if is ordered) and I want to get the number of occurrences of each different string.
Example:
ContaOcs["a", "a", "b", "c", "c", "c", "d"]
Should return:
[(2,"a"), (1,"b"), (3,"c"), (1,"d")]
Here is What I'm trying to do:
module Main where
contaOcs :: [String] -> [(Int, String)]
contaOcs [] = [_,_]
contaOcs [x] = [1,x]
contaOcs (i, x1:x2:xs)
| x1 == x2 = (i+1,(x2:xs))
| otherwise = (0, (x2:xs))
But this code have some errors and I'm not so sure how I should do to accomplish this
I'm new to functional programing and Haskell. Can anyone help me with some information?
Thanks for any help.

There are some syntactical problems as well as problems with the types. The first line looks like:
contaOcs [] = [_,_]
But an underscore (_) in the result does not makes any sense, you can only construct lists with values in it. When we count the number of occurences of an empty list, the result will be an empty list, so contaOcs [] = [].
As for the second:
contaOcs [x] = [1,x]
Here you aim to return a list with two elements: a 1 and an x (which is a String). In Haskell the elements of a list all have the same type. What you can do is return a list of 2-tuples with the first item an Int, and the second a String, like the signature suggests, but then you need to wrap the values in a 2-tuple, like contaOcs [x] = [(1,x)].
In your last clause, you write:
contaOcs (i, x1:x2:xs) = ...
which does not make much sense: the input type is a list (here of Strings), not a 2-tuple with an Int, and a list of strings.
So the input will look like:
contaOcs (x1:x2:xs) = ...
The output, like (i+1,(x2:xs)) also is not in "harmony" with the proposed output type in the signature, this looks like a 2-tuple with an Int, and a list of Strings, so (Int, [String]), not [(Int, String)].
Based on the above comments, we have derived something like:
contaOcs :: [String] -> [(Int, String)]
contaOcs [] = []
contaOcs [x] = [(1,x)]
contaOcs (x1:x2:xs)
| x1 == x2 = -- ...
| otherwise = -- ...
So now there are two parts to fill in. In case x1 and x2 are not equal, that means that we can first yield a tuple (1, x1) in the list, followed by the result of contaOcs on the rest of the list (x2 included), so:
(1, x1) : contaOcs (x2:xs)
In the latter case, it means that we first make a recursive call to contaOcs with (x2:xs), and then increment the counter of the first item of that list. We are sure such element exists, since we make a recursive call with a list containing at least one element, and by induction, that means the result contains at least one element as well, since the base case contains one element, and the recursive case either prepends elements to the result, or updates these.
So we can use a pattern guard, and maniplate the result, like:
contaOcs :: [String] -> [(Int, String)]
contaOcs [] = []
contaOcs [x] = [(1,x)]
contaOcs (x1:x2:xs)
| x1 == x2, ((yi, yv):ys) <- contaOcs (x2:xs) = (yi+1, yv) : ys
| otherwise = (1, x1) : contaOcs (x2:xs)
We can also use an "as-pattern": we only need a reference to the tail of the list starting with x2, not xs:
contaOcs :: [String] -> [(Int, String)]
contaOcs [] = []
contaOcs [x] = [(1,x)]
contaOcs (x1:xs#(x2:_))
| x1 == x2, ((yi, yv):ys) <- contaOcs xs = (yi+1, yv) : ys
| otherwise = (1, x1) : contaOcs xs
The above is however not very elegantly. It might be better to use an accumulator here, I leave this as an exercise.

Let's look at some of the errors mentioned by ghc. Always pay close attention to when GHC talks about Expected and Actual types, as these messages are always illuminating. Expected indicates what GHC thinks you should write. Actual indicates what you wrote. You either need to change what you wrote (read: change your code), or change what GHC thinks you should write (read: change your type annotations). In this case it's mostly the former.
hw.hs:2:16: error:
• Found hole: _ :: (Int, String)
• In the expression: _
In the expression: [_, _]
In an equation for ‘contaOcs’: contaOcs [] = [_, _]
• Relevant bindings include
contaOcs :: [String] -> [(Int, String)] (bound at hw.hs:2:1)
|
2 | contaOcs [] = [_,_]
| ^
hw.hs:2:18: error:
• Found hole: _ :: (Int, String)
• In the expression: _
In the expression: [_, _]
In an equation for ‘contaOcs’: contaOcs [] = [_, _]
• Relevant bindings include
contaOcs :: [String] -> [(Int, String)] (bound at hw.hs:2:1)
|
2 | contaOcs [] = [_,_]
| ^
The underscore is used as a placeholder (or "hole"), to be filled in later. GHC is telling you that you should figure out something to put in these holes.
hw.hs:3:19: error:
• Couldn't match type ‘[Char]’ with ‘(Int, String)’
Expected type: (Int, String)
Actual type: String
• In the expression: x
In the expression: [1, x]
In an equation for ‘contaOcs’: contaOcs [x] = [1, x]
|
3 | contaOcs [x] = [1,x]
|
You have declared that the return type of the function is [(Int, String)], in other words, a List, where each element of the list is a Tuple of Int and String.
Therefore, each element in the list should be a Tuple. The syntax [1,x] means a list with two elements: 1 and x. GHC has noticed that x, however, is known to be a String, which is not a Tuple. (GHC failed to notice that 1 is not a tuple, for... reasons. Numbers in Haskell are a little weird and GHC is not so helpful with those.)
Perhaps you meant to write (1, x), which is a tuple of 1 (an Int) and x (a String). However, don't forget to also put that tuple into a list somehow, since your return type is a list of tuples.
hw.hs:4:10: error:
• Couldn't match expected type ‘[String]’
with actual type ‘(Integer, [a0])’
• In the pattern: (i, x1 : x2 : xs)
In an equation for ‘contaOcs’:
contaOcs (i, x1 : x2 : xs)
| x1 == x2 = (i + 1, (x2 : xs))
| otherwise = (0, (x2 : xs))
|
4 | contaOcs (i, x1:x2:xs)
| ^^^^^^^^^^^^^
GHC is again reminding you that it expects a list of tuples, but in this case, you gave it just one tuple.
The errors are mostly the same as this.

contaOcs :: [String] -> [(Int, String)]
contaOcs consumes a list of strings: xss, for each unique string: xs in xss, we produce a pair: p, whose first element represents the number of occurrences of xs in xss, and the second element of p is that xs itself.
We know we need to group strings by their uniqueness and count each unique string's total occurrences. You can follow this idea and implement the rest yourself. contaOcs takes a list and produces a new list so list comprehension should give you what you want. You're transforming one list to another, so fmap a function that accumulates should work. You can also just use natural recursion or accumulator. Here is one way to write contaOcs:
contaOcs = (return . liftA2 (,) length head =<<) . group
Write down the signature, purpose statement, some sample data and test cases first, then it's just a matter of finding the solutions that best fit your need.

This is a good example of when a co-recursive function is helpful.
contaOcs :: [String] -> [(Int, String)]
We'll define contaOcs as the outer function that takes the list of strings and returns the tuples. First let's look at the trivial cases:
contaOcs [] = []
contaOcs [x] = [(1,x)]
Pass an empty list, and you should get back an empty list. Pass a single element list, and you should get back a list with one element: (1, x). Now we can guarantee that any other list is 2+ elements long.
contaOcs (x:xs) = go x xs
go? What is go you might ask? Well let's define it in the where clause:
where
go cur xs = let (this, rest) = span (==x) xs
in (succ . length $ this, cur) : contaOcs diff
That's kind of a lot, so let's unpack. go is an idiomatic term for a function helper (this could as easily be named f or frobnicator, it doesn't matter). It takes the character we're counting, which is split separately from the rest of its list, and calls it x. It runs a span (==x) against the rest of the list, which splits it into a tuple (longestPrefixThatMatches, rest). We return the length of that longest prefix (plus one, since we've stripped off the front character) paired with the character itself in a tuple, then cons that with the recursive case -- handing the rest of the list back to the outer function to handle.

What you want can be done by a one-liner
Prelude> import Data.List
Prelude Data.List> ls = ["a", "a", "b", "c", "c", "c", "d"]
Prelude Data.List> [(length x, head x) | x <- group ls]
[(2,"a"),(1,"b"),(3,"c"),(1,"d")]
I mix list comprehension with the group function. Basic concepts you can make yourselves familiar with.

contaOcs :: [String] -> [(Int, String)]
contaOcs xs = foldr foldContaOcs [] xs
where foldContaOcs s [] = (1, s):[]
foldContaOcs s ((n, ch):xs) = if ch == s then (n + 1, s) : xs
else (1, s): (n, ch): xs

Related

How do you write more than 1 line in an if statement in Haskell

I have an if-else statement, and in the else block I want it to first recurse to the function, except for the last two elements of the list, and then return two elements.
In the following function, after the if-else statement, I have 2 lines of code. however this doesnt compile. I believe the compiler reads these two lines as a single line of code. How do you fix that?
doubleEveryOther :: [Integer] -> [Integer] --outputs the input list, but every 2nd element(from the right) is doubled
doubleEveryOther [] = []
doubleEveryOther x = if (length x <2)
then
x
else
doubleEveryOther init (init x) -- These two lines
[2*last(init x), last x] -- These two lines
The compiler says:
* Couldn't match expected type: [Integer]
with actual type: [a0] -> [a0]
* Probable cause: `init' is applied to too few arguments
In the first argument of `doubleEveryOther', namely `init'
In the expression: doubleEveryOther init (init x)
In the expression:
[doubleEveryOther init (init x), 2 * last (init x), last x]
|
19 | [doubleEveryOther init (init x), 2*last(init x), last x]
|
You can not return two lists. If you have two results you want to combine, you use some function, like (++) :: [a] -> [a] -> [a].
That being said, you here don't need this. You can work with simple pattern matching:
doubleEveryOtherFromLeft :: Num a => [a] -> [a]
doubleEveryOtherFromLeft (x:y:xs) = 2*x : y : doubleEveryOtherFromLeft xs
doubleEveryOtherFromLeft xs = xs
then our doubleEveryOther can reverse the list twice:
doubleEveryOther:: Num a => [a] -> [a]
doubleEveryOther = reverse . doubleEveryOtherFromLeft . reverse
I think you are just missing the append operator ++:
doubleEveryOther (init (init x))
++ [2 * last (init x), last x]
I have an if-else statement, and in the else block I want it to first
recurse to the function, except for the last two elements of the list,
and then return two elements
OK. I sort of understand what you're doing. The function name is good - the best name is verb-noun, here doubleEveryOther. However, the code looks a lot like Lisp, probably Scheme - the repeated use of init gives it away. That's not how you write Haskell. (I also write Lisp in Haskell syntax too much...)
Haskell recursion works using pattern matching.
lst = [2,3,4]
1 : [2,3,4] -- [1,2,3,4]
lst = [1,2,3,4]
(x:xs) = lst -- x is 1, xs = [2,3,4]
So, in this case, you want to match your list against x:y:xs:
lst = [1,2,3,4]
(x:y:xs) = lst -- x is 1, y is 2, xs=[3,4]
Hence:
doubleEveryOther :: Num a => [a] -> [a]
doubleEveryOther [] = []
doubleEveryOther [x] = [2*x]
doubleEveryOther (x:y:xs) = (2*x):doubleEveryOther xs
Please note the number of special cases which need to be handled. If I am given an empty list, I should return an empty list. If I am given a single value, I need to double it (in analogy to your if .. else clause). If I am given two or more values, this matches x=first, y=second, xs=[] or more.
As for returning more than one value, you can return only one thing from a function. It can be a single value, a single tuple, a single list, and so on.
In this case, you have written a function which says doubleEveryOther - good - but then you want to return the last two values unchanged. You would be better taking off the last two values, running the simple doubleEveryOther and then bolting the last two values on the end. Otherwise, you are overburdening your function.

How to compare elements in a [[]]?

I am dealing with small program with Haskell. Probably the answer is really simple but I try and get no result.
So one of the part in my program is the list:
first = [(3,3),(4,6),(7,7),(5,43),(9,9),(32,1),(43,43) ..]
and according to that list I want to make new one with element that are equal in the () =:
result = [3,7,9,43, ..]
Even though you appear to have not made the most minimal amount of effort to solve this question by yourself, I will give you the answer because it is so trivial and because Haskell is a great language.
Create a function with this signature:
findIdentical :: [(Int, Int)] -> [Int]
It takes a list of tuples and returns a list of ints.
Implement it like this:
findIdentical [] = []
findIdentical ((a,b) : xs)
| a == b = a : (findIdentical xs)
| otherwise = findIdentical xs
As you can see, findIdentical is a recursive function that compares a tuple for equality between both items, and then adds it to the result list if there is found equality.
You can do this for instance with list comprehension. We iterate over every tuple f,s) in first, so we write (f,s) <- first in the right side of the list comprehension, and need to filter on the fact that f and s are equal, so f == s. In that case we add f (or s) to the result. So:
result = [ f | (f,s) <- first, f == s ]
We can turn this into a function that takes as input a list of 2-tuples [(a,a)], and compares these two elements, and returns a list [a]:
f :: Eq a => [(a,a)] -> [a]
f dat = [f | (f,s) <- dat, f == s ]
An easy way to do this is to use the Prelude's filter function, which has the type definition:
filter :: (a -> Bool) -> [a] -> [a]
All you need to do is supply predicate on how to filter the elements in the list, and the list to filter. You can accomplish this easily below:
filterList :: (Eq a) => [(a, a)] -> [a]
filterList xs = [x | (x, y) <- filter (\(a, b) -> a == b) xs]
Which behaves as expected:
*Main> filterList [(3,3),(4,6),(7,7),(5,43),(9,9),(32,1),(43,43)]
[3,7,9,43]

Creating a lists of lists with new element in each position

i'm new in the haskell world and i'd like to know how to insert a value in each position of a list in haskell, and return a lists of sublists containing the value in each position. For example:
insert' :: a -> [a] -> [[a]]
insert' a [] = [[a]]
insert' a list = ??
To get something like:
insert' 7 [1,2,3] = [[7,1,2,3],[1,7,2,3],[1,2,7,3],[1,2,3,7]]
insert' :: a -> [a] -> [[a]]
insert' y [] = [[y]]
insert' y xss#(x:xs) = (y : xss) : map (x :) (insert' y xs)
While the empty list case comes natural, let's take a look at insert' y xss#(x:xs). We essentially have two cases we need to cover:
y appears in front of x. Then we can just use y : xss.
y appears somewhere after x. We therefore just insert it in the rest of our list and make sure that x is the first element with map (x:).
Although #delta's answer is definitely more elegant, here a solution with difference lists. If we insert an element x on every location of list ys = [y1,y2,...,yn], the first time we will insert it as head, so that means we can construct x : ys.
. For the second element of the resulting list, we want to construct a list [y1,x,y2,...,yn]. We can do this like y1 : x : y2s. The next lists will all have a structure y1 : ....
The question is: how can we write a recursive structure that keeps track of the fact that we want to put elements in the head. We can use a function for that: we start with a function id. If we now call id (x:ys) then we will of course generate the list (x:ys).
We can however, based on the id function, construct a new function id2 = \z -> id (y1:z). This function will thus put y1 in the head of the list and then add the list with which we call id2 as tail. Next we can construct id3 = \z -> id2 (y2:z). This will put y1 and y2 as first elements followed by the tail z.
So we can put this into the following recursive format:
insert' :: a -> [a] -> [[a]]
insert' x = go id
where go d [] = [d [x]]
go d ys#(yh:yt) = (d (x : ys)) : go (d . (yh :)) yt
So we redirect insert' to go where the initial difference list is simply the id function. Each time we check if we have reached the end of the given list. If that is the case, we return the basecase: we call [x] (as tail) on the difference list, and thus construct a list where we append x as last element.
In case we have not yet reached the last element, we will first emit d (x : ys): we prepend x to the list and provide this as argument to the difference list d. d will prepend y1 : y2 : ... : yk up to the point where we insert x. Furthermore we call recursively go (d . (yh :)) yt on the tail of the list: we thus construct a new difference list, wehere we insert (yh :) as tail of the list. We thus produce a new function with one argument: the tail after the yh element.
This function produces the expected results:
*Main> insert' 4 []
[[4]]
*Main> insert' 4 [1,2,5]
[[4,1,2,5],[1,4,2,5],[1,2,4,5],[1,2,5,4]]
*Main> insert' 7 [1,2,3]
[[7,1,2,3],[1,7,2,3],[1,2,7,3],[1,2,3,7]]
You may also do as follows;
import Data.List
spread :: a -> [a] -> [[a]]
spread x xs = zipWith (++) (inits xs) ((x:) <$> tails xs)
*Main> spread 7 [1,2,3]
[[7,1,2,3],[1,7,2,3],[1,2,7,3],[1,2,3,7]]
*Main> spread 7 []
[[7]]
So this is about three stages.
(x:) <$> tails xs is all about applying the (x:) function to all elements of tails xs function. So tails [1,2,3] would return [[1,2,3],[2,3],[3],[]] and we are to apply an fmap which is designated by <$> in the inline form. This is going to be the third argument of the zipWith function.
(inits xs) which would return [[],[1],[1,2],[1,2,3]], is going to be the second argument to zipWith.
zipWith (++) is obviously will zip two list of lists by concatenating the list elements.
So we may also express the same functionality with applicative function functors as follows;
spread :: a -> [a] -> [[a]]
spread x = zipWith (++) <$> inits <*> fmap (x:) . tails
In this case we fmap the zipWith (++) function with type [[a]] -> [[a]] -> [[a]] over inits and then apply it over to fmap (x:) . tails.
It could get more pointfree but becomes more complicated to read through (at least for me). In my opinion this is as best as it gets.

F# take a list, return list of tuples

I've done some research and I see that the List.zip function takes two lists and returns one list of tuples, but how do you change one list into a list of tuples?
let rec combinePair xs =
match xs with
| [] -> []
| [x1] -> []
| x1::x2::x3::xs -> [(x1, x2)]
| x1::x2::xs -> [(x1, x2)]
If an odd number of elements exist in the list, the last element should be dropped, if an even number of elements exist they should be returned as a list of tuples. For example
combinePair [x1; x2; x3; x4] = [(x1, x2); (x3, x4)]
Your code is almost there.
Here's the thinking:
when given an empty list, the result is an empty list (you already got that).
when given a list of one element, the result is an empty list (got that too).
otherwise, the first item of result is a tuple composed of the first two elements, and the rest of result is the result of applying the same process to the rest of the input.
This can be almost identically translated to F#:
let rec combinePair xs =
match xs with
| [] | [_] -> []
| x1::x2::rest -> (x1, x2) :: (combinePair rest)
(note how I combined the first two cases on one line, [] | [_] ->)
I'm sure there are prettier solutions but for those who are allergic to recursion:
let xsOdd = [1;2;3;4;5]
List.chunkBySize 2 xsOdd
|> List.filter (fun x -> x.Length = 2)
|> List.map (fun x -> x.[0],x.[1])
//val it : (int * int) list = [(1, 2); (3, 4)]

How can I find the index where one list appears as a sublist of another?

I have been working with Haskell for a little over a week now so I am practicing some functions that might be useful for something. I want to compare two lists recursively. When the first list appears in the second list, I simply want to return the index at where the list starts to match. The index would begin at 0. Here is an example of what I want to execute for clarification:
subList [1,2,3] [4,4,1,2,3,5,6]
the result should be 2
I have attempted to code it:
subList :: [a] -> [a] -> a
subList [] = []
subList (x:xs) = x + 1 (subList xs)
subList xs = [ y:zs | (y,ys) <- select xs, zs <- subList ys]
where select [] = []
select (x:xs) = x
I am receiving an "error on input" and I cannot figure out why my syntax is not working. Any suggestions?
Let's first look at the function signature. You want to take in two lists whose contents can be compared for equality and return an index like so
subList :: Eq a => [a] -> [a] -> Int
So now we go through pattern matching on the arguments. First off, when the second list is empty then there is nothing we can do, so we'll return -1 as an error condition
subList _ [] = -1
Then we look at the recursive step
subList as xxs#(x:xs)
| all (uncurry (==)) $ zip as xxs = 0
| otherwise = 1 + subList as xs
You should be familiar with the guard syntax I've used, although you may not be familiar with the # syntax. Essentially it means that xxs is just a sub-in for if we had used (x:xs).
You may not be familiar with all, uncurry, and possibly zip so let me elaborate on those more. zip has the function signature zip :: [a] -> [b] -> [(a,b)], so it takes two lists and pairs up their elements (and if one list is longer than the other, it just chops off the excess). uncurry is weird so lets just look at (uncurry (==)), its signature is (uncurry (==)) :: Eq a => (a, a) -> Bool, it essentially checks if both the first and second element in the pair are equal. Finally, all will walk over the list and see if the first and second of each pair is equal and return true if that is the case.