Haskell check in list - haskell

I have a string which has several words in it, and I have to check if the first character is the same as the previous word last character. I've been told to use the the words built in function.
Here is what I've done:
validGame1 :: [String] -> Bool
validGame1 [] = True
validGame1 [x] = True
validGame1 (a:b:xs)
|last a == head b = validGame1 (b:xs)
|otherwise = False
but i'm getting exceptions when the input should be True
example : validGame "bread door room mad" (this should be True but it throws an exception)
validGame "bread car room mad" (this should be False and it works well)

It seems like you are forgetting to use words. This works for me:
ghci> validGame1 (words "bread door room mad")
True
ghci> validGame1 (words "bread car room mad")
False
If you want to encapsulate that into one function you can write:
validGame1 :: String -> Bool
validGame1 inp = go (words inp) where
go [] = True
go [x] = True
go (a:b:xs)
| last a == head b = go (b:xs)
| otherwise = False

As an addendum, it's possible to solve this problem without ever using words simply with recursion and pattern matching.
check :: [Char] -> Bool
check "" = True
check [_, _] = True
check (a:tl#(' ':b:c))
| a == b = check tl
| otherwise = False
check (_:tl) = check tl
We can consider any one or two character string to meet the specifications laid out.
For three or more characters, if the middle character is a space, if the two characters on either side are the same, we can check the tail of the string. Otherwise we know the string does not pass the check and return False.
If the string is three or more characters, but the middle character is not a space, continue checking the tail of the string.
Note: this does not handle a string where words are separate by multiple spaces.
If we want to handle that scenario, we can add a few patterns to our function.
check :: [Char] -> Bool
check "" = True
check [_, _] = True
check (' ':tl#(' ':b:_)) = check tl
check (a:tl#(' ':' ':_)) = check $ a:' ':(dropWhile (== ' ') tl)
check (a:tl#(' ':b:_))
| a == b = check tl
| otherwise = False
check (_:tl) = check tl

Related

Haskell: Replace a subString in a String without Data.List package

I'm very new in Haskell and I want to know how I can replace a predetermined word in a String by another word. This is my code so far, I know I can't do this for now:
treat :: String -> String
treat text = text
main::IO()
main = do argv <- getArgs
texte <- readFile "intputText"
print (separation text)
print ( treat text )
separation :: String -> [String]
separation [] = [""]
separation (c:cs) | c == "\Graph" = "Graphic : " : rest
| c == '}' = "" : rest
| c == '{' = "" : rest
| otherwise = (c : head rest) : tail rest
where rest = separation cs
So basically I know I can't put a String in the first c == "\Graph" so I want to know
how I can basically replace every word "\Graph" in my String text by "Graphic".
I want to be able to do that without importing any package.
If anyone can help me out I'd really appreciate it.
Thank you very much!
replace :: String -> String -> String-> String
replace [] token repl = []
replace str#(s:ss) token#(t:tx) repl
-- check if first char of string equal to first char of token
| s == t = case validateToken token str of
Just list -> repl ++ replace list token repl
Nothing -> s : replace ss token repl
-- if not equal then continue recursion step
| otherwise = s: replace ss token repl
where
-- validate if token matches the following chars of the string
-- returns Nothing if token is not matched
-- returns the remaining string after the token if token is matched
validateToken:: String -> String -> Maybe String
validateToken (a:as) [] = Nothing
validateToken [] list = Just list
validateToken (a:as) (x:xs)
| a == x = validateToken as xs
| otherwise = Nothing
example = replace "yourString" "token" "new"

Haskell - Decode message with pattern

I am new to Haskell and I am currently learning it in school. I got a school task where I have to decode a message that contain certain patterns but I have got no idea how to do this.
The pattern looks something like this: If a letter has a consonant followed by the character 'o' and then once again followed by the same consonant as before it should replace that substring ("XoX" where X is a consonant) with only the consonant. For example if I decode the string "hohejoj" it should return "hej". Sorry if I am explaining this poorly but I think you understand.
This is the code I have so far (but it doesn't work):ยจ
karpsravor :: String->String
karpsravor s = karpsravor_help s ""
where karpsravor_help s res
|s == "" && (last res) == 'o' = (init res)
|s==""=res
|otherwise = karpsravor_help (drop 3 s) (res ++ (consDecode (take 3 s)))
consDecode :: String->String
consDecode a
|(length a) < 3 = ""
|a == [(head a)]++"o"++[(head a)] = [(head a)]
|otherwise = a
The code is completely broken and poorly written (dumb method) but I have no other idea for how to solve this. Please help!
Pattern match to find occurrences of 'o'. I.e., use
karpsravorhelp (a:'o':b:rest) res = ...
You can't have a:'o':a:rest in the above, you can't pattern match for equality; you'll need to use a guard to make sure that a == b:
karpsravorhelp (a:'o':b:rest) res
| a == b = ...
| otherwise = ...
You'll also have to make sure a and b are consonants, which will just be an 'and' condition for the first guard. For the otherwise condition, make sure that the recursive call calls (b:rest) since you could have something like a:'o':b:'o':b:....
Also make sure to match for two other patterns:
Empty List, []
x:rest, which must go after the above pattern; this way, it will first attempt to match on the a:'o':b:rest pattern, and if that's not there, just take the next letter.
One way to do it would be with unfoldr from Data.List. You can use a case expression to pattern match on a : 'o' : b : rest, and then check that a and b are equal and not vowels using a guard |. Then just include the base cases for when the pattern doesn't match.
notVowel :: Char -> Bool
notVowel = (`notElem` "aeiouAEIOU")
karpsravor :: String -> String
karpsravor = unfoldr $ \str -> case str of
a : 'o' : b : rest
| a == b && notVowel a -> Just (a, rest)
a : rest -> Just (a, rest)
"" -> Nothing

Haskell - Pattern Matching form (x:y:zs)

I am having difficulty understanding how to use pattern matching in guards.
I have this sample function, whose purpose is to return the last character in a string.
myFun :: [Char] -> Char
myFun str#(f:s:rst)
| str == "" = error "0 length string"
| length str == 1 = head str
| rst == "" = s
| otherwise = lame (s:rst)
It is failing with "Non-exhaustive patterns in function" when passed a string with a single character.
I assume that Haskell realizes it can't use the form (f:s:rst) to match a single element list, and then fails prior to trying to evaluate the call to length.
How do I make a guard that will tell Haskell what to do when there is only a single element?
You are pattern matching at the function definition level. The way you have described it, you are only covering the case where the string is at least two characters long:
myFun str#(f:s:rst)
You need to handle other cases as well. You can have a catch-all handler like this (needs to go as the last pattern):
myFun _ = ...
Or if you want to handle, for instance, the empty string, like this (prior to the catch-all):
myFun [] = ...
As to the purpose of your function, you are probably better off just using pattern matching and not using guards.
myFun :: [Char] -> Char
myFun [] = error "empty string"
myFun [x] = x
myFun (x:xs) = myFun xs
(Note that it would be more idiomatic to return a Maybe Char instead of crashing your program)
Based on the particularly helpful answer from Chad Gilbert, and some additional tinkering,
I have found a way to have my cake and eat it to.
In case anyone has a similar stumbling block, here is a way to specify uncovered cases prior to declaring your guards:
myFun :: [Char] -> Char
myFun "" = ""
myFun str#(s:rst)
| rst == "" = s
| otherwise = myFun (s:rst)
This also works with multiple args :
strSplit :: [Char] -> [[Char]] -> [[Char]]
strSplit str [] = strSplit str [""]
strSplit "" _ = [""]
strSplit str#(s1:ns) list#(x:xs)
| s1 == '|' = strSplit ns ("":list)
| ns == "" = map reverse $ ((s1 : x) : xs)
| otherwise = strSplit ns ((s1 : x) : xs)
Or with stuff using the original pattern#(first:second:rest) idea:
lastTwo :: [Char]->[Char]
lastTwo "" = ""
lastTwo [x] = [x]
lastTwo str#(f:s:rst)
| rst =="" = [f,s]
| otherwise = lastTwo (s:rst)
This is probably super obvious to folks more familiar with Haskell, but I didn't realize that you were "allowed" to just declare the function multiple times using different syntax to cover different cases.

Check if a string contains a certain character using recursion

I know how to check if a string contains a certain character like this:
charFound :: Char -> String -> Bool
charFound c s = c `elem` s
Now, how could I have the same approach using recursion?
Also, using Pattern Matching to check if one of the parameters is empty, I'm getting
Parse Error In pattern: ' ' s
charFound:: Char->String->Bool
charFound '' s = error "Something is empty." -- ERROR
charFound c "" = error "Something is empty." -- OK
Am I allowed to use the _ to ignore a parameter with something that's not a list ?
Update Currently code
charFound :: Char->String->Bool
charFound c (x:xs)
| c == x = True
| xs == "" = False
| otherwise = contido c xs
Also
charFound :: Char->String->Bool
charFound _ "" = False -- returns false if I type > charFound 'a' "Leh"
charFound c (x:xs)
| c == x = True
| otherwise = contido c xs
We can keep the same signature, because the function does the same thing.
charFound :: Char -> String -> Bool
When you are performing recursion you always want to make sure you consider your base case, in this case it would be when you are looking for a character in an empty String, which should obviously always return false.
charFound c "" = False
Now you have to consider the other case, where the String is not empty. If the string is not empty, then it is of the form (x:xs), and if x equals our character then we return true, otherwise we check whether c is in xs.
charFound c (x:xs)
| c == x = True
| otherwise = charFound c xs
Alternatively,
charFound c (x:xs) = c == x || charFound c xs
Edit:
To answer your additional question about pattern matching, you are getting that warning because '' is not a character! A character can never be empty, so you don't need to consider that possibility.
Also, you definitely can use _ to match on something that is not a list. You can use _ to match any parameter you like. For example, the base case could have been written as
charFound _ "" = False
Because we don't actually need to know what the value of the character is when the String is empty, so we don't need to give it a name.

Haskell Get position from first digit in string

What I got is
digitIndex :: String -> Int
digitIndex [] = 1
digitIndex (x:xs) =
if
isDigit x == True
then
-- Count list
else
-- Create list with x(x is not a digit)
What my idea is is to make a list with all the x that he is passing so when he passes a digit he only needs to count the list and that will be the position of the digit(when you count a +1).
Only thing is I don't know how to get the job more done. Can you guys help me out with tips?
You can use findIndex:
import Data.List
digitIndex :: String -> Int
digitIndex = maybe 0 id . findIndex isDigit
Just the normal recursion:
digitIndex :: String -> Int
digitIndex [] = 0
digitIndex (x:xs) = if isDigit x
then 1
else 1 + digitIndex xs
If the first character itself is a digit, then the function returns 1 else it just adds 1 and passes the remaining string (xs) to the function and the recursion goes on.
Also note that the above function doesn't work properly when the String doesn't have a number at all.
And also checking isDigit == True isn't necessary.

Resources