Selección hasta el primero que falla inclusive
Definir la función
seleccionConFallo :: (a -> Bool) -> [a] -> [a]
tal que (seleccionConFallo p xs)
es la lista de los elementos de xs
que cumplen el predicado p
hasta el primero que no lo cumple inclusive. Por ejemplo,
seleccionConFallo (<5) [3,2,5,7,1,0] == [3,2,5] seleccionConFallo odd [1..4] == [1,2] seleccionConFallo odd [1,3,5] == [1,3,5] seleccionConFallo (<5) [10..20] == [10]
Soluciones
import Test.Hspec (Spec, describe, hspec, it, shouldBe) import Test.QuickCheck.HigherOrder (quickCheck') -- 1ª solución -- =========== seleccionConFallo1 :: (a -> Bool) -> [a] -> [a] seleccionConFallo1 _ [] = [] seleccionConFallo1 p (x:xs) | p x = x : seleccionConFallo1 p xs | otherwise = [x] -- 2ª solución -- =========== seleccionConFallo2 :: (a -> Bool) -> [a] -> [a] seleccionConFallo2 p xs = ys ++ take 1 zs where (ys,zs) = span p xs -- 3ª solución -- =========== seleccionConFallo3 :: (a -> Bool) -> [a] -> [a] seleccionConFallo3 = ((uncurry (++) . fmap (take 1)) .) . span -- Ejemplo de cálculo: -- seleccionConFallo (<5) [3,2,5,7,1,0] -- = (((uncurry (++) . fmap (take 1)) .) . span) (<5) [3,2,5,7,1,0] -- = (uncurry (++) . fmap (take 1)) ([3,2],[5,7,1,0]) -- = uncurry (++) ([3,2],[5]) -- = [3,2,5] -- Nota: (fmap f (x,y)) es equivalente a (x,f y). -- Verificación -- ============ verifica :: IO () verifica = hspec spec specG :: ((Int -> Bool) -> [Int] -> [Int]) -> Spec specG seleccionConFallo = do it "e1" $ seleccionConFallo (<5) [3,2,5,7,1,0] `shouldBe` [3,2,5] it "e2" $ seleccionConFallo odd [1..4] `shouldBe` [1,2] it "e3" $ seleccionConFallo odd [1,3,5] `shouldBe` [1,3,5] it "e4" $ seleccionConFallo (<5) [10..20] `shouldBe` [10] spec :: Spec spec = do describe "def. 1" $ specG seleccionConFallo1 describe "def. 2" $ specG seleccionConFallo2 describe "def. 3" $ specG seleccionConFallo3 -- La verificación es -- λ> verifica -- 12 examples, 0 failures -- Comprobación de equivalencia -- ============================ -- La propiedad es prop_seleccionConFallo :: (Int -> Bool) -> [Int] -> Bool prop_seleccionConFallo p xs = all (== seleccionConFallo1 p xs) [seleccionConFallo2 p xs, seleccionConFallo3 p xs] -- La comprobación es -- λ> quickCheck' prop_seleccionConFallo -- +++ OK, passed 100 tests. -- Comparación de eficiencia -- ========================= -- La comparación es -- λ> length (seleccionConFallo1 (<5*10^6) [1..]) -- 5000000 -- (1.92 secs, 1,240,601,360 bytes) -- λ> length (seleccionConFallo2 (<5*10^6) [1..]) -- 5000000 -- (1.36 secs, 1,280,601,504 bytes) -- λ> length (seleccionConFallo3 (<5*10^6) [1..]) -- 5000000 -- (1.17 secs, 1,280,601,544 bytes)