Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Haskell function that takes out last occurrence of input character

I'm having trouble writing this function that takes a character and a list of characters, then eliminates the last occurrence of that input character in the list. I was able to take out the first occurrence of the input character with my function below:

fun :: Char -> String -> String
fun c (s:ss)
 | s == c   = ss
 | otherwise = s : fun c ss
fun _ [] = []

What I need help on is how I should modify this function to take out the last occurrence of the input character, instead of the first. The result should be something like fun 'c' "abcdccytrc" returning "abcdccytr".

like image 287
T-Bird Avatar asked Dec 27 '25 18:12

T-Bird


2 Answers

As Numeri suggests, removing the last occurrence by removing the first occurrence in the reversed list is one way:

removeFirst :: Char -> String -> String
removeFirst _ [] = []
removeFirst c1 (c2:cs) = if c1 == c2 then cs else c2:removeFirst c1 cs

removeLast :: Char -> String -> String
removeLast c1 = reverse . removeFirst c1 . reverse

As Will Ness suggests, returning the string in which the last occurrence is removed, and a boolean to indicate whether the current occurrence should be removed or not, is another:

removeLast :: Char -> String -> String
removeLast c1 = snd . remLast
  where
    remLast :: String -> (Bool, String)
    remLast [] = (False, [])
    remLast (c2:cs) =
      case remLast cs of
        (True, cs') -> (True, c2:cs')
        (False, cs') -> if c1 == c2 then (True, cs') else (False, c2:cs')
like image 191
sshine Avatar answered Dec 30 '25 09:12

sshine


Okay, here's what I came up with:

fun :: Char -> String -> String
fun c (s:ss)
 | ((fun c ss) == ss) && (s == c) = ss
 | otherwise                      = s : fun c ss
fun _ [] = []

Essentially, if s == c, and the rest of the string (ss) is unchanged by running this function on it (i.e., it contains no character c), then return the remaining characters.

If this requirement isn't met (i.e., the rest of the string has the character c at least one time), retain the current character and apply the function to the rest of the string.

Aside from this, I think reversing the string and then calling your original function, then reversing it again, like I suggested in a comment, might be more understandable, but that's just opinion.

like image 33
Numeri Avatar answered Dec 30 '25 09:12

Numeri