Home > Enterprise >  Process a string using foldr where '#' means deleting the previous character
Process a string using foldr where '#' means deleting the previous character

Time:11-23

I need to process a string using foldr where '#' means deleting the previous character. For example:

>backspace "abc#d##c"
"ac"

>backspace "#####"
""

It needs to be done using foldr through one pass of the list, without using reverse and/or ( ).

Here what I have got so far:

backspace :: String -> String
backspace xs = foldr func [] xs where
  func c cs | c /= '#' = c:cs
            | otherwise = cs

But it just filter the '#' from the string. I thought about deleting the last element of current answer every time c == '#' and got something like that

backspace :: String -> String
backspace xs = foldr func [] xs where
  func c cs | c /= '#' = c:cs
            | cs /= [] = init cs
            | otherwise = cs

but it is not working properly,

ghci> backspace "abc#d##c" 
"abc"

CodePudding user response:

You can use (Int, String) as state for your foldr where the first Int is the number of backspaces, and the String is the current string constructed.

This thus means that you can work with:

backspace :: String -> String
backspace = snd . foldr func (0, [])
  where func '#' (n, cs) = (n 1, cs)
        func c (n, cs)
                 | n > 0 = …      -- (1)
                 | otherwise = …  -- (2)

In case we have a character that is not a #, but n > 0 it means we need to remove that character, and thus ignore c and decrement n. In case n == 0 we can add c to the String.

I leave filling in the parts as an exercise.

  • Related