Remove all vowels of a string with recursive function - haskell

I can remove the vowels without a recursive function like this:
NoVowels:: String -> String
NoVowels xs = filter f xs where f x = not (x == ’a’ || x == ’e’ || x == ’i’ || x == ’o’ || x == ’u’)
But how may I do that with a recursive function ?
I tried something like this but of course did not work (parse Error):
NoVowels :: String -> String
NoVowels "" = error "Empty String!!"
NoVowels (x:xs)
| x in (x == 'a'|| x == 'e' || x == 'i' || x == 'o' || x == 'u') = NoVowels (tail x)
If the head is a vowel then I CUT it from the string and pass recursively the tail, if its not a vowel how may I verify the other string without removing it.
Update obs: I want to return the function without the vowels.

I thins it makes sense to define a function isVowel :: Char->Bool and after that write something like this :
noVowels :: String -> String
noVowels [] = []
noVowels (x:xs)
|isVowel x = noVowels xs
|otherwise = x : noVowels xs
If you don't want to define one more function you can try next code :
noVowels :: String ->String
noVowels [] = []
noVowels (x:xs)
|not( x `elem` "aeiou") = x: noVowels xs
|otherwise = noVowels xs

Here's a bit of an improvement on the code. Just in case you missed out on preserving the cases involved.
module Disemvowel where
disemvowel :: String -> String
disemvowel [] = []
disemvowel " " = " "
disemvowel (x:xs)
| x `elem` "aeiouAEIOU" = disemvowel xs
| otherwise = [x] ++ disemvowel xs

Related

How to remove space from a String?

I'm trying to do removing space (" ") from a string without using the strip function. How to implement if 'head' == " " (space) in the program?
skipSpaces :: (Eq a) => [a] -> [a]
skipSpaces [] = []
skipSpaces (h:t)
| h `elem` " " = skipSpaces t -- condition if 'head' is equal to " "(space),do nothing.
| otherwise = h : skipSpaces t -- produce the result
I don't know how to declare aboutif 'head' == " " (space)
nor if 'head' == "(contain_strings)"(a collection of letters)".
Example:
Input: "I am twenty one"
Output Expectation: "Iamtwentyone"
You can match the space directly:
skipSpaces [] = []
skipSpaces (' ':t) = skipSpaces t
skipSpaces (h:t) = h : skipSpaces t
One trick, though, is to think about what function to apply to skipSpaces t, depending on the value of h. Consider a slight modification of the above:
skipSpaces [] = []
skipSpaces (' ':t) = id (skipSpaces t)
skipSpaces (h:t) = (h :) (skipSpaces t)
Note the similarity between the last two cases. We can factor out the recursive call as follows:
skipSpaces [] = []
skipSpaces (h:t) = (if h == ' ' then id else (h :)) (skipSpaces t)

Error return Haskell

i have some troubles here with this.
I'm trying to do something like that:
Prelude> func ["abacate", "aba", "baaba"]
["cate", "", "ba"]
this exercise, must return words without the substring aba.
elimLetras :: String -> String
elimLetras [] = []
elimLetras (x:y:z:xs)
| elem x "aA" || elem y "bB" || elem z "aA" = elimLetras xs
| otherwise = x : elimLetras (x:xs)
| otherwise = y : elimLetras (y:xs)
| otherwise = z : elimLetras (z:xs)
elimLetras (x:xs) = x:xs
this code it's not working right.
On ghci, i'ts return:
prelude> elimLetras "abacate"
output: "cce"
Any tips?
So you are trying to remove the case insensitive substring aba from a String. Your method of checking for a substring isn't bad. It wouldn't scale very well but you can keep it like this if you want. The main issue is with the multiple otherwise statements. You should only ever have one otherwise statement, as only the first one will ever be reached.
Here is a rewrite of your function with a couple of helper function:
import Data.Char (toLower)
elimLetras :: String -> String
elimLetras (x:y:z:xs)
| stringEquals "aba" [x,y,z] = elimLetras xs
| otherwise = x : elimLetras (y:z:xs)
elimLetras xs = xs -- anything that has fewer than 3 letters is returned "as is".
-- Check if two strings are the same (case insensitive)
stringEquals :: String -> String -> Bool
stringEquals a b = stringToLower a == stringToLower b
stringToLower :: String -> String
stringToLower [] = []
stringToLower (x:xs) = toLower x : stringToLower xs
If you know about the map function, here is how I would probably write it:
elimLetras' :: String -> String
elimLetras' (x:y:z:xs)
| "aba" == map toLower [x,y,z] = elimLetras' xs
| otherwise = x : elimLetras' (y:z:xs)
elimLetras' xs = xs

Type error in explicitly typed binding (Haskell)

I am writing a very simple function which transforms a string by replacing a certain combinations of characters into another. (e.g. "ab" to "a")
I am a noob in Haskell, and I get error: "Type error in explicitly typed binding"
Could you please tell me what is the problem?
Code:
transform :: String -> String
transform [] = []
transform [x] = x
transform (x:y:xs)
| x == "a" && y == "b" = "a" ++ (transform xs)
| x == "b" && y == "a" = "b" ++ (transform xs)
| x == "b" && y == "b" = "a" ++ (transform xs)
| x == "a" && y == "a" = "aaa" ++ (transform xs)
Thank you!
In the final transform pattern, you are using string literals for "a" and "b" when they should be characters.
transform :: String -> String
transform [] = []
transform [x] = [x]
transform (x:y:xs)
| x == 'a' && y == 'b' = "a" ++ (transform xs)
| x == 'b' && y == 'a' = "b" ++ (transform xs)
| x == 'b' && y == 'b' = "a" ++ (transform xs)
| x == 'a' && y == 'a' = "aaa" ++ (transform xs)
Also, there was a bug in the second transform definition, where you needed to wrap x in brackets because it was returning a list of characters.
(You may also want to have a final pattern match to handle any other input, since you'll get a non-exhaustive error if you run this against a string like "zzz")

Foldl on string

I would like to foldl a string so that any occurrence of zero which is preceded by # is replaced with "k". So "a.#0.1.2.0" becomes, "a.#k.1.2.0". How do I do that? So far my attempt is
test = foldl(\x acc-> if((last acc) == "#" && x == "0" then acc ++ "k" else acc ++ x)) "" "a.#0.1.2.0"
However, it doesn't work. Foldl is expecting list of string and what I'm providing is just a string. How do I overcome that?
Taking chi's advice,
rep "" = ""
rep ('#' : '0' : xs) = "#k" ++ rep xs
rep (x : xs) = x : rep xs
If we want to get fancier,
rep = snd . mapAccumL go False
where
go True '0' = (False, 'k')
go _ '#' = (True, '#')
go _ x = (False, x)
or even
rep = snd . mapAccumL go 'x'
where
go '#' '0' = ('0', 'k')
go _ y = (y, y)
To use foldr with this second approach (just because it's shorter; the first will work fine too, and allows generalization),
rep xs = foldr go (const "") xs 'x'
where
go '0' r '#' = 'k' : r '0'
go x r _ = x : r x
To use zipWith (which is more awkward to generalize):
rep xs = zipWith go ('x' : xs) xs where
go '#' '0' = 'k'
go _ x = x
As others have commented, foldl would not fit well for this task. However, using the idea of difference list, you may still do this efficiently using foldl:
repl :: String -> String
repl a = foldl loop id a ""
where
loop :: (String -> String) -> Char -> (String -> String)
loop f '#' ('0':rest) = f ('#':'k':rest)
loop f x xs = f (x:xs)
Just for the purpose of demonstration and the fact that the question has asked for a foldl solution. (not that I would recommend doing it this way).

Implementing Backtracking on Haskell

I have a problem making Backtracking on Haskell, I know how to do recursive functions but I get troubles when I try to get multiple solutions or the best one (backtracking).
There's a list with some strings, then I need to get the solutions to get from a string to another one changing one letter from the string, I will get the list, the first string and the last one. If there is solution return the count of steps that it did, if there is not solution it returns -1. here's an example:
wordF ["spice","stick","smice","stock","slice","slick","stock"] "spice" "stock"
Then I have my list and I need to start with "spice" and get to "stock"
and the best solution is ["spice","slice","slick","stick","stock"] with four steps to get from "spice" to "stock". then it return 4.
Another solution is ["spice","smice","slice","slick","stick","stock"] with five steps to get to "stock" then it return `5. But this is a wrong solution because there's another one that's better with lesser steps than this one.
I'm having troubles making a backtracking to get the best solution, because I don't know how to make that my code search another solutions and just not one..
Here's a code that i tried to make but i get some errors, btw i dont know if my way to "make" backtracking is good or if there are some mistakes that im not seeing..
wordF :: [String] -> String -> String -> (String, String, Int)
wordF [] a b = (a, b, -1)
wordF list a b | (notElem a list || notElem b list) = (a, b, -1)
| otherwise = (a, b, (wordF2 list a b [a] 0 (length list)))
wordF2 :: [String] -> String -> String -> [String] -> Int -> Int -> Int
wordF2 list a b list_aux cont maxi | (cont==maxi) = 1000
| (a==b) = length list_aux
| (a/=b) && (cont<maxi) && notElemFound && (checkin /= "ThisWRONG") && (wording1<=wording2) = wording1
| (a/=b) && (cont<maxi) && notElemFound && (checkin /= "ThisWRONG") && (wording1>wording2) = wording2
| (a/=b) && (checkin == "ThisWRONG") = wordF2 list a b list_aux (cont+1) maxi
where
checkin = (check_word2 a (list!!cont) (list!!cont) 0)
wording1 = (wordF2 list checkin b (list_aux++[checkin]) 0 maxi)
wording2 = (wordF2 list checkin b (list_aux++[checkin]) 1 maxi)
notElemFound = ((any (==(list!!cont)) list_aux) == False)
check_word2 :: String -> String -> String -> Int -> String
check_word2 word1 word2 word3 dif | (dif > 1) = "ThisWRONG"
| ((length word1 == 1) && (length word2 == 1) && (head word1 == head word2)) = word3
| ((length word1 == 1) && (length word2 == 1) && (head word1 /= head word2) && (dif<1)) = word3
| ((head word1) == (head word2)) = check_word2 (tail word1) (tail word2) word3 dif
| otherwise = check_word2 (tail word1) (tail word2) word3 (dif+1)
My first function wordF2 get the list, the start, the end, an auxiliary list to get the current solution with the first element that always will be there ([a]), a counter with 0, and the max size of the counter (length list)..
and the second function check_word2 it checks if a word can pass to another word, like "spice" to "slice" if it cant like "spice" to "spoca" it returns "ThisWRONG".
This solution gets an error of pattern match failure
Program error: pattern match failure: wordF2 ["slice","slick"] "slice" "slick" ["slice"] 0 1
I was trying with little cases and nothing, and I'm restricting that i get a wrong position of the list with the count and the max.
Or may be I dont know how to implement backtracking on haskell to get multiple solutions, the best solution, etc..
UPDATE: I did a solution but its not backtracking
wordF :: [String] -> String -> String -> (String, String, Int)
wordF [] a b = (a, b, -1)
wordF list a b | (notElem a list || notElem b list) = (a, b, -1)
| otherwise = (a, b, (wordF1 list a b))
wordF1 :: [String] -> String -> String -> Int
wordF1 list a b | ((map length (wordF2 (subconjuntos2 (subconjuntos list) a b))) == []) = -1
| (calculo > 0) = calculo
| otherwise = -1
where
calculo = (minimum (map length (wordF2 (subconjuntos2 (subconjuntos list) a b))))-1
wordF2 :: [[String]] -> [[String]]
wordF2 [[]] = []
wordF2 (x:xs) | ((length xs == 1) && ((check_word x) == True) && ((check_word (head xs)) == True)) = x:xs
| ((length xs == 1) && ((check_word x) == False) && ((check_word (head xs)) == True)) = xs
| ((length xs == 1) && ((check_word x) == True) && ((check_word (head xs)) == False)) = [x]
| ((length xs == 1) && ((check_word x) == False) && ((check_word (head xs)) == False)) = []
| ((check_word x) == True) = x:wordF2 xs
| ((check_word x) == False ) = wordF2 xs
check_word :: [String] -> Bool
check_word [] = False
check_word (x:xs) | ((length xs == 1) && ((check_word2 x (head xs) 0) == True)) = True
| ((length xs >1) && ((check_word2 x (head xs) 0) == True)) = True && (check_word xs)
| otherwise = False
check_word2 :: String -> String -> Int -> Bool
check_word2 word1 word2 dif | (dif > 1) = False
| ((length word1 == 1) && (length word2 == 1) && (head word1 == head word2)) = True
| ((length word1 == 1) && (length word2 == 1) && (head word1 /= head word2) && (dif<1)) = True
| ((head word1) == (head word2)) = check_word2 (tail word1) (tail word2) dif
| otherwise = check_word2 (tail word1) (tail word2) (dif+1)
subconjuntos2 :: [[String]] -> String -> String -> [[String]]
subconjuntos2 [] a b = []
subconjuntos2 (x:xs) a b | (length x <= 1) = subconjuntos2 xs a b
| ((head x == a) && (last x == b)) = (x:subconjuntos2 xs a b)
| ((head x /= a) || (last x /= b)) = (subconjuntos2 xs a b)
subconjuntos :: [a] -> [[a]]
subconjuntos [] = [[]]
subconjuntos (x:xs) = [x:ys | ys <- sub] ++ sub
where sub = subconjuntos xs
Mmm may be its inefficient but at least it does the solution..
i search all posible solutions, i compare head == "slice" and last == "stock", then i filter the ones that are solution and print the shorter one,
thanks and if you guys have any suggest say it :)
Not thoroughly tested, but this hopefully will help:
import Data.Function (on)
import Data.List (minimumBy, delete)
import Control.Monad (guard)
type Word = String
type Path = [String]
wordF :: [Word] -> Word -> Word -> Path
wordF words start end =
start : minimumBy (compare `on` length) (generatePaths words start end)
-- Use the list monad to do the nondeterminism and backtracking.
-- Returns a list of all paths that lead from `start` to `end`
-- in steps that `differByOne`.
generatePaths :: [Word] -> Word -> Word -> [Path]
generatePaths words start end = do
-- Choose one of the words, nondeterministically
word <- words
-- If the word doesn't `differByOne` from `start`, reject the choice
-- and backtrack.
guard $ differsByOne word start
if word == end
then return [word]
else do
next <- generatePaths (delete word words) word end
return $ word : next
differsByOne :: Word -> Word -> Bool
differsByOne "" "" = False
differsByOne (a:as) (b:bs)
| a == b = differsByOne as bs
| otherwise = as == bs
Example run:
>>> wordF ["spice","stick","smice","stock","slice","slick","stock"] "spice" "stock"
["spice","slice","slick","stick","stock"]
The list monad in Haskell is commonly described as a form of nondeterministic, backtracking computation. What the code above is doing is allowing the list monad to take on the responsibility of generating alternatives, testing whether they satisfy criteria, and backtracking on failure to the most recent choice point. The bind of the list monad, e.g. word <- words, means "nondeterministically pick one of the words. guard means "if the choices so far don't satisfy this condition, backtrack and make a different choice. The result of a list monad computation is the list of all the results that stem from choices that did not violate any guards.
If this looks like list comprehensions, well, list comprehensions are the same thing as the list monad—I chose to express it with the monad instead of comprehensions.
There have been several articles published recently on classic brute-force search problems.
Mark Dominus published a simple example of using lists for a simple exhaustive search.
Justin Le followed up with a small modification to the previous article that simplified tracking the current state of the search.
I followed up with a further modification that allowed measuring the gains from early rejection of part of the search tree.
Note that the code in my article is quite slow because it's measuring the amount of work done as well as doing it. My article has good examples for how to quickly reject parts of the search tree, but it should be considered only an illustration - not production code.
A brute force approach using recursion:
import Data.List (filter, (\\), reverse, delete, sortBy)
import Data.Ord (comparing)
neighbour :: String -> String -> Bool
neighbour word = (1 ==) . length . (\\ word)
process :: String -> String -> [String] -> [(Int, [String])]
process start end dict =
let
loop :: String -> String -> [String] -> [String] -> [(Int,[String])] -> [(Int,[String])]
loop start end dict path results =
case next of
[] -> results
xs ->
if elem end xs
then (length solution, solution) : results
else results ++ branches xs
where
next = filter (neighbour start) dict'
dict' = delete start dict
path' = start : path
branches xs = [a | x <- xs, a <- loop x end dict' path' results]
solution = reverse (end : path')
in
loop start end dict [] []
shortestSolution :: Maybe Int
shortestSolution = shortest solutions
where
solutions = process start end dict
shortest s =
case s of
[] -> Nothing
xs -> Just $ fst $ head $ sortBy (comparing fst) xs
start = "spice"
end = "stock"
dict = ["spice","stick","smice","slice","slick","stock"]
Notes:
This code computes all possibles solutions (process) and select the shortest one (shortestSolution), as Carl said, you might want to prune parts of the search tree for better performance.
Using a Maybe instead of returning -1 when a function can fail to return results is preferred.
Another way using a tree with breadth-first search:
import Data.Tree
import Data.List( filter, (\\), delete )
import Data.Maybe
node :: String -> [String] -> Tree String
node label dict = Node{ rootLabel = label, subForest = branches label (delete label dict) }
branches :: String -> [String] -> [Tree String]
branches start dict = map (flip node dict) (filter (neighbour start) dict)
neighbour :: String -> String -> Bool
neighbour word = (1 ==) . length . (\\ word)
-- breadth first traversal
shortestBF tree end = find [tree] end 0
where
find ts end depth
| null ts = Nothing
| elem end (map rootLabel ts) = Just depth
| otherwise = find (concat (map subForest ts)) end (depth+1)
result = shortestBF tree end
tree :: Tree String
tree = node start dict
start = "spice"
end = "stock"
dict = ["spice","stick","smice","slice","slick","stock"]

Resources