Ordered occurrences of characters in string - haskell

I want to get all the occurrences of the characters I have in a string.
So for example if I have the string "nunddrdr" I want to get "nnudddrr".
This is how the code looks like which should achieve this:
usort :: String -> String
l :: String
l = ""
usort (x:xs)
| xs == [] = l ++ [x]
| otherwise = l ++ [n | n <- (x:xs), n = x] ++ usort (xs)
It doesn't work correctly because it also proccesses already used characters.

You have correctly observed that your recursive calls to usort are not removing the characters that have already been used, so you will need to modify the function so that it does this. You can use filter to select only the elements of the list that match some criteria, so we can remove the already used characters like so:
filter (\=x) xs
We can select all of the characters that match x in the same manner, by using
filter (==x) xs
You can use these two things to create your usort function:
usort (x:xs) = x : (filter (==x) xs) ++ usort (filter (/=x) xs)
However, you have failed to consider the case when you will be trying to sort an empty list, so you will also need to add:
usort [] = []
Putting this together, you get
usort::(Eq a)=>[a]->[a]
usort [] = []
usort (x:xs) = x : filter (==x) xs ++ usort (filter (/=x) xs)

Related

separate even and odd elements of list haskell

I am trying to separate elements of a list into to further lists, one for the odd and one for even numbers.
For Example,
input: [1,2,3,4,10]
output: ([2,4,10],[1,3])
sepList :: [Int]->([Int],[Int])
sepList [] = ([],[])
sepList (x:xs) | (x mod 2) ==0 = (([x],[]) ++ sepList xs)
| (x mod 2) /=0 = (([],[x]) ++ sepList xs)
| otherwise = ([],[])
It gives error on ...++ sepList xs
anyone could guide me here?
The operator++ is used to concatenate 2 lists and neither of your arguments to ++ is a list,
([x],[]) ++ sepList xs
both ([x],[]) and sepList xs are pairs of lists. So what you want is to pattern match on sepList xs e.g. using a let binding,
let (ys,zs) = sepList xs in
and then return,
(x:ys,zs)
You aren't concatenating two lists; you want to add a single element to a list, selected from the tuple output of the recursive call. Don't use (++); use (:).
sepList (x:xs) = let (evens, odds) = sepList xs
in if even x
then (x:evens, odds)
else (evens, x:odds)
More simply, though, sepList = partition even. (partition can be found in Data.List.)
There are two answers so far which suggest basically doing this by hand (by pattern-matching on the result of the recursive call), but there is actually an operator already defined for the types that you're working with that does exactly what you want! Lists form a monoid with (<>) = (++), but you don't have two lists: you have two pairs of lists. Happily, the type of pairs are also a monoid if each element of the pair is a monoid: (a,b) <> (c,d) = (a <> c, b <> d). So, you can simply replace your ++ call with <>, which will result in concatenating the corresponding lists in your pairs.
For enthusiasts, following one line will also work for separating list in even and odd.
sepList xs = (filter even xs , filter odd xs)
import Data.List
sepList :: [Int]->([Int],[Int])
sepList = partition even
sepList [1,2,3,4,10]
In this case i would use an accumulator to create the tuple containing the two lists.In our case the accumulator is ([],[]).
split::[Int]->([Int],[Int])
split ls= go ([],[]) ls where
go accu [] = accu
go (odd,even) (x:xs) | x `mod` 2==0 = go (x:odd,even) xs
| otherwise = go (odd, x:even) xs
As you can see the elements need to be reversed since we are pushing on top of our lists with the : operator.
I do not know if this is optimal but i would write it like this with reverse:
module Split where
split::[Int]->([Int],[Int])
split ls=let rev tupl=(reverse . fst $ tupl ,reverse .snd $ tupl) in
rev $ go ([],[]) ls where
go accu [] = accu
go (odd,even) (x:xs) | x `mod` 2==0 = go (x:odd,even) xs
| otherwise = go (odd, x:even) xs

How to loop through a list of string?

I suppose to input a list of words. If a word's last letter is the same as the first letter of another word, then we connect them and output a list of lists, which contain all possible connections.
Example: convert(["apple","elephant","eraser", "tower","rank"]) will give
[["elephant", "eraser"], ["tower"], ["rank"], ["rank"], []]
I implemented my code as following:
convert :: [String] -> [[String]]
convert [] = []
convert [x] = []
convert (x : xs) = if last x == head (head xs)
then [head xs] : [] : convert (x : (tail xs))
else convert (x : (tail xs))
But this can only check the first element. How can I loop through the whole list and check each word?
===========================================================================
Ok. I have it done.
convert :: [String] -> [[String]]
convert [] = []
convert (x:xs) = [u | u <- xs, last x == head u] : convert (xs)

Base case for not going out of the list?

Im very new to haskell and would like to know if theres a basic case for not going out of the list when going threw it!
For example in this code im trying to make a list where it compares the number on the right, and it if its bigger it stays on the list, otherwise we remove it, but it keeps giving me Prelude.head:empty list, since its comparing to nothing in the end im assuming. I've tried every base case i could think off... can anyone help me?
maiores:: [Int]->[Int]
maiores [] = []
maiores (x:xs) | x > (head xs) = [x] ++ [maiores xs)
| otherwise = maiores xs
If your function is passed a list with one element, it will match (x:xs), with xs matching []. Then you end up with head [] and thus your error. To avoid this, add an additional base case maiores (x:[]) = ... between your two existing cases, and fill it in appropriately.
Also: you can write [x] ++ maiores xs as x : maiores xs, which is more natural because you deconstruct a : and then immediately reconstruct it with the modified value, as opposed to indirectly using ++.
Never use head or tail in your code, unless you can't avoid it. These are partial functions, which will crash when their input is empty.
Instead, prefer pattern matching: instead of
foo [] = 4
foo (x:xs) = x + head xs + foo (tail xs)
write
foo [] = 4
foo (x1:x2:xs) = x1 + x2 + foo xs
Now, if we turn on warnings with -Wall, GHC will suggest that the match in not exhaustive: we forgot to handle the [_] case. So, we can fix the program accordingly
foo [] = 4
foo [x] = x
foo (x1:x2:xs) = x1 + x2 + foo xs
Just make pattern matching more specific. Since (:) is right associative:
maiores:: [Int]->[Int]
maiores [] = []
maiores (x : y : xs) | x > y = [x] ++ maiores (y:xs)
maiores (_ : xs) = maiores xs

Haskell: String splitting. Learning algo

I've seen the other threads about missing split function but I didn't want to peek as I do this for learning purposes and want to figure out myself. So here it is:
split :: Char -> String -> [String]
split c xs | null f = []
| otherwise = f : split c s'
where (f,s) = break (== c) xs
s' | null s = s
| otherwise = tail s
It seems to work fine (please tell me if anything is wrong with it) but when I use a splitting character that is not in the string then the function returns a list with a single element of the original string whereas I want it to return an empty list. I can't figure out how to do it.
Any ideas?.
You can simply write a wrapper function, changing the result of your original one:
split' x xs = go (split x xs) where
go [_] = []
go ys = ys
There are many ways to write a split function, e.g.
split x xs = foldl' go [[]] xs where
go (ys:yss) y | y == x = []:ys:yss
| otherwise = (y:ys):yss
or
import Data.List
split x xs = map tail $ groupBy (const (/=x)) (x:xs)

Removes occurrences a given element within a list of lists

I have this function which removes occurrences of a given element within the list of lists.
remove :: Eq a => a -> [[a]] -> [[a]]
remove y [] = error "Can't remove an element from an empty list"
remove y xs = map (filter(/=y)) xs
How would I be able to do the same using List comprehension
Thank you
For each l in xs, add filter (/= xs) l to the resulting list:
remove y xs = [filter (/= y) l | l <- xs]
or, removing filter by nesting comprehensions.
For each xs in xss and for each x in xs, keep x only if it's different from y:
remove y xss = [ [x| x <- xs, x /= y] | xs <- xss]
It's OK if you're just practicing , but your version with map is way better :)
I guess something along the lines of:
remove y ls = [f|l <- ls, let f = filter (/= y) l]
should be fine.
It basicly states that for every binding l you can make in the list ls, add the filtered list f to the resulting list.

Resources