La bandera tricolor
El problema de la bandera tricolor consiste en lo siguiente: Dada un lista de objetos xs que pueden ser rojos, amarillos o morados, se pide devolver una lista ys que contiene los elementos de xs, primero los rojos, luego los amarillos y por último los morados.
Definir el tipo de dato Color para representar los colores con los constructores R, A y M correspondientes al rojo, azul y morado y la función
banderaTricolor :: [Color] -> [Color]
tal que (banderaTricolor xs) es la bandera tricolor formada con los elementos de xs. Por ejemplo,
bandera [M,R,A,A,R,R,A,M,M] == [R,R,R,A,A,A,M,M,M] bandera [M,R,A,R,R,A] == [R,R,R,A,A,M]
Soluciones
import Data.List (sort) import Test.Hspec (Spec, describe, hspec, it, shouldBe) data Color = R | A | M deriving (Show, Eq, Ord, Enum) -- 1ª definición (con sort): banderaTricolor1 :: [Color] -> [Color] banderaTricolor1 = sort -- 2ª definición (por comprensión): banderaTricolor2 :: [Color] -> [Color] banderaTricolor2 xs = [x | x <- xs, x == R] ++ [x | x <- xs, x == A] ++ [x | x <- xs, x == M] -- 3ª definición (por comprensión y concat): banderaTricolor3 :: [Color] -> [Color] banderaTricolor3 xs = concat [[x | x <- xs, x == c] | c <- [R,A,M]] -- 4ª definición (por recursión): banderaTricolor4 :: [Color] -> [Color] banderaTricolor4 xs = aux xs ([],[],[]) where aux [] (as,rs,ms) = as ++ rs ++ ms aux (R:ys) (as,rs,ms) = aux ys (R:as, rs, ms) aux (A:ys) (as,rs,ms) = aux ys ( as, A:rs, ms) aux (M:ys) (as,rs,ms) = aux ys ( as, rs, M:ms) -- 5ª definición (por recursión): banderaTricolor5 :: [Color] -> [Color] banderaTricolor5 xs = aux xs (0,0,0) where aux [] (as,rs,ms) = replicate as R ++ replicate rs A ++ replicate ms M aux (R:ys) (as,rs,ms) = aux ys (1+as, rs, ms) aux (A:ys) (as,rs,ms) = aux ys ( as, 1+rs, ms) aux (M:ys) (as,rs,ms) = aux ys ( as, rs, 1+ms) -- Verificación -- ============ verifica :: IO () verifica = hspec spec specG :: ([Color] -> [Color]) -> Spec specG banderaTricolor = do it "e1" $ banderaTricolor [M,R,A,A,R,R,A,M,M] `shouldBe` [R,R,R,A,A,A,M,M,M] it "e2" $ banderaTricolor [M,R,A,R,R,A] `shouldBe` [R,R,R,A,A,M] spec :: Spec spec = do describe "def. 1" $ specG banderaTricolor1 describe "def. 2" $ specG banderaTricolor2 describe "def. 3" $ specG banderaTricolor3 describe "def. 4" $ specG banderaTricolor4 describe "def. 5" $ specG banderaTricolor5 -- La verificación es -- λ> verifica -- 10 examples, 0 failures -- Comparación de eficiencia: -- λ> bandera n = concat [replicate n c | c <- [M,R,A]] -- λ> :set +s -- λ> length (banderaTricolor1 (bandera 1000000)) -- 3000000 -- (2.92 secs, 1,024,602,024 bytes) -- λ> length (banderaTricolor2 (bandera 1000000)) -- 3000000 -- (1.91 secs, 1,168,601,536 bytes) -- λ> length (banderaTricolor3 (bandera 1000000)) -- 3000000 -- (3.55 secs, 1,440,602,120 bytes) -- λ> length (banderaTricolor4 (bandera 1000000)) -- 3000000 -- (1.30 secs, 1,000,601,376 bytes) -- λ> length (banderaTricolor5 (bandera 1000000)) -- 3000000 -- (1.56 secs, 1,245,461,400 bytes)