I am trying to write a function detadj :: String -> Bool
that takes a string and returns true if
the string contains two adjacent characters that are identical. For example:
detadj "" == False
detadj "s" == False
detadj "ss" == True
detadj "Misisipi" == False
detadj "Mississippi" == True
detadj "single-dash" == False
detadj "double--dash" == True
I have two versions of the function one in list comprehension, which is faulty in many cases, but the most prevalent one is when detadjlc ["ss"]
which will output an empty list due to the usage of the (x:y:xs)
bit:
detadjlc :: String -> Bool
detadjlc [] = False
detadjlc [x] = False
detadjlc (x:y:xs) = head[ x == y && isAlpha x == isAlpha y | (x,y) <- zip (x:y:xs) xs ]
And recursion (this does not work when the input is something like detadjr [" ee"]
which produces False
instead of True
):
detadjr :: String -> Bool
detadjr [] = False
detadjr [x] = False
detadjr (x:y:xs) | x == y = True
| otherwise = d xs
What are some ways to fix these?
CodePudding user response:
Your recursive function is fine, except for one small detail: you forgot to put y
back on the list for the recursive call. (I assume d
is a typo for detadjr
.) Just because x
and y
are different doesn't mean y
and the first character of xs
might not be the same.
detadjr :: String -> Bool
detadjr (x:y:xs) = (x == y) || detadjr (y:xs)
detadjr _ = False
(If you check strings of 2 or more characters first, then singleton and empty lists can be collapsed into a single base case.)
CodePudding user response:
Following is an iterative solution using list comprehension. We create a list of tuples containing adjacent elements of the input list. Then we compare those elements in the tuple.
detadjlc :: String -> Bool
detadjlc xs = or [x == y | (x, y) <- zip xs (tail xs)]
The recursive solution is best done as @chepner already posted.