Delete consecutive characters from a list in Haskell

0

Very good to all, to see if you can help me. I have a problem when I want to remove all the consecutive items from a list that comply with the condition of being an upper case and a lowercase one and returning the rest of the list to me. Example: Given a sequence:   "aAbBaa" the result is "aa" or this other example "cCBb" the result is "" I have this implementation:

removerInversos :: secuencia -> secuencia
removerInversos []  = []
removerInversos (x:xs)
    | isInverse x cabezaCola == True = cola
    | otherwise =  x: removerInversos  cola 
    where
    cabezaCola = head xs
    cola = tail xs

The isInverse function:

isInverse :: Operador -> Operador -> Bool
isInverse x y = (match x y) && ( ((isUpper x) && (isLower y))|| ((isLower x) && (isUpper y)) )

Function match :

match :: Operador -> Operador -> Bool
match x y = (toUpper x) == (toUpper y)
    
asked by champion2k 25.03.2018 в 19:42
source

1 answer

2

Why it fails

To see what happens to you, let's see what your code does for removerInversos "ab" :

  • removerInversos "ab"
  • As isInverse x cabezaCola == False - > 'a' : removerInversos cola
  • In this step, cabezaCola == 'b' and cola == "" . You're losing cabezaCola , that's where you lose items.

    First version: recursive

    Let's do it another way:

    removerInversos :: Secuencia -> Secuencia
    removerInversos []  = []
    removerInversos [x] = [x]
    removerInversos (x:y:xs) | isInverse x y = removerInversos xs
                             | otherwise     = x: removerInversos (y:xs) 
    
    isInverse :: Operador -> Operador -> Bool
    isInverse x y = (toUpper x == toUpper y) && (isUpper x /= isUpper y)
    

    This pattern check avoids having to use head and tail .

    But you say to repeat again in case the condition is again fulfilled, that it could be done like this:

    removerInversos' :: Secuencia -> Secuencia
    removerInversos' xs | sinMasCambios = xs
                        | otherwise     = removerInversos' ys
      where
        ys = removerInversos xs
        sinMasCambios = length xs == length ys
    

    Although it is not elegant at all.

    Second version: foldr

    There would be another way to approach the problem. If we make a fold on the right, foldr , we are sure that the queue has already been processed before doing the check, something that prevents us from applying recursion:

    removerInversos :: Secuencia -> Secuencia
    removerInversos = foldr aux []
      where 
        aux :: Operador -> Secuencia -> Secuencia
        aux x [] = [x]
        aux x (y:ys) | isInverse x y = ys
                     | otherwise     = x:y:ys
    
        
    answered by 26.03.2018 / 15:04
    source