Ir al contenido principal

Sin consecutivos repetidos


Definir la función

sinConsecutivosRepetidos :: Eq a => [a] -> [a]

tal que (sinConsecutivosRepetidos xs) es la lista obtenida a partir de xs de forma que si hay dos o más elementos idénticos consecutivos, borra las repeticiones y deja un elemento. Por ejemplo,

λ> sinConsecutivosRepetidos "eesssooo essss   toodddooo"
"eso es todo"

Soluciones

import Data.List (group)
import Test.Hspec (Spec, describe, hspec, it, shouldBe)
import Test.QuickCheck

-- 1ª solución
-- ===========

sinConsecutivosRepetidos1 :: Eq a => [a] -> [a]
sinConsecutivosRepetidos1 [] = []
sinConsecutivosRepetidos1 [x] = [x]
sinConsecutivosRepetidos1 (x : y : xs)
  | x == y    = sinConsecutivosRepetidos1 (y : xs)
  | otherwise = x : sinConsecutivosRepetidos1 (y : xs)

-- 2ª solución
-- ===========

sinConsecutivosRepetidos2 :: Eq a => [a] -> [a]
sinConsecutivosRepetidos2 [] = []
sinConsecutivosRepetidos2 (x:xs) =
  x : sinConsecutivosRepetidos2 (dropWhile (==x) xs)

-- 3ª solución
-- ===========

sinConsecutivosRepetidos3 :: Eq a => [a] -> [a]
sinConsecutivosRepetidos3 xs = foldr aux [] xs
  where
    aux x [] = [x]
    aux x (y:ys)
      | x == y    = y : ys
      | otherwise = x : y : ys

-- 4ª solución
-- ===========

sinConsecutivosRepetidos4 :: Eq a => [a] -> [a]
sinConsecutivosRepetidos4 xs =
  [x | (x:_) <- group xs]


-- 5ª solución
-- ===========

sinConsecutivosRepetidos5 :: Eq a => [a] -> [a]
sinConsecutivosRepetidos5 = map head . group

-- Verificación
-- ============

verifica :: IO ()
verifica = hspec spec

specG :: (String -> String) -> Spec
specG sinConsecutivosRepetidos = do
  it "e1" $
    sinConsecutivosRepetidos "eesssooo essss   toodddooo"
    `shouldBe` "eso es todo"

spec :: Spec
spec = do
  describe "def. 1" $ specG sinConsecutivosRepetidos1
  describe "def. 2" $ specG sinConsecutivosRepetidos2
  describe "def. 3" $ specG sinConsecutivosRepetidos3
  describe "def. 4" $ specG sinConsecutivosRepetidos4
  describe "def. 5" $ specG sinConsecutivosRepetidos5

-- La verificación es
--    λ> verifica
--    4 examples, 0 failures

-- Comprobación de equivalencia
-- ============================

-- La propiedad es
prop_equivalencia :: [Int] -> Bool
prop_equivalencia xs =
  all (== sinConsecutivosRepetidos1 xs)
      [sinConsecutivosRepetidos2 xs,
       sinConsecutivosRepetidos3 xs,
       sinConsecutivosRepetidos4 xs,
       sinConsecutivosRepetidos5 xs]

-- La comprobación es
--    λ> quickCheck prop_equivalencia
--    +++ OK, passed 100 tests.

-- Comparación de eficiencia
-- =========================

-- La comparación es
--    λ> length (sinConsecutivosRepetidos1 (take (5*10^6) (cycle "aaabb ")))
--    2500000
--    (2.15 secs, 1,420,601,960 bytes)
--    λ> length (sinConsecutivosRepetidos2 (take (5*10^6) (cycle "aaabb ")))
--    2500000
--    (1.54 secs, 1,080,602,240 bytes)
--    λ> length (sinConsecutivosRepetidos3 (take (5*10^6) (cycle "aaabb ")))
--    2500000
--    (2.94 secs, 1,575,252,040 bytes)
--    λ> length (sinConsecutivosRepetidos4 (take (5*10^6) (cycle "aaabb ")))
--    2500000
--    (0.86 secs, 1,360,602,312 bytes)
--    λ> length (sinConsecutivosRepetidos5 (take (5*10^6) (cycle "aaabb ")))
--    2500000
--    (0.29 secs, 1,400,602,512 bytes)