Elementos que respetan la ordenación
Se dice que un elemento x de una lista xs respeta la ordenación si x es mayor o igual que todos lo que tiene delante en xs y es menor o igual que todos lo que tiene detrás en xs. Por ejemplo, en la lista lista [3,2,1,4,6,5,7,9,8] el número 4 respeta la ordenación pero el número 5 no la respeta (porque es mayor que el 6 que está delante).
Definir la función
respetuosos :: Ord a => [a] -> [a]
tal que (respetuosos xs) es la lista de los elementos de xs que respetan la ordenación. Por ejemplo,
respetuosos [3,2,1,4,6,4,7,9,8] == [4,7] respetuosos [2,1,3,4,6,4,7,8,9] == [3,4,7,8,9] respetuosos "abaco" == "aco" respetuosos "amor" == "amor" respetuosos "romanos" == "s" respetuosos [1..9] == [1,2,3,4,5,6,7,8,9] respetuosos [9,8..1] == []
Comprobar con QuickCheck que para cualquier lista de enteros xs se verifican las siguientes propiedades:
- todos los elementos de (sort xs) respetan la ordenación y
- en la lista (nub (reverse (sort xs))) hay como máximo un elemento que respeta la ordenación.
Soluciones
import Data.List (nub, sort) import Test.QuickCheck -- 1ª definición (por comprensión): respetuosos :: Ord a => [a] -> [a] respetuosos xs = [z | k <- [0..n-1] , let (ys,z:zs) = splitAt k xs , all (<=z) ys , all (>=z) zs] where n = length xs -- 2ª definición (por recursión): respetuosos2 :: Ord a => [a] -> [a] respetuosos2 xs = aux [] [] xs where aux zs _ [] = reverse zs aux zs ys (x:xs) | all (<=x) ys && all (>=x) xs = aux (x:zs) (x:ys) xs | otherwise = aux zs (x:ys) xs -- Comparación de eficiencia -- λ> length (respetuosos [1..3000]) -- 3000 -- (3.31 secs, 1,140,407,224 bytes) -- λ> length (respetuosos2 [1..3000]) -- 3000 -- (2.85 secs, 587,082,160 bytes) -- λ> length (respetuosos [3000,2999..1]) -- 0 -- (0.42 secs, 570,825,840 bytes) -- λ> length (respetuosos2 [3000,2999..1]) -- 0 -- (0.02 secs, 0 bytes) -- λ> length (respetuosos (take 5000 (cycle [1,2]))) -- 2 -- (3.48 secs, 2,003,235,448 bytes) -- λ> length (respetuosos2 (take 5000 (cycle [1,2]))) -- 2 -- (2.00 secs, 396,762,416 bytes) -- 1ª propiedad prop_respetuosos1 :: [Int] -> Bool prop_respetuosos1 xs = respetuosos (sort xs) == sort xs -- La comprobación es -- λ> quickCheck prop_respetuosos1 -- +++ OK, passed 100 tests. -- La 2ª propiedad prop_respetuosos2 :: [Int] -> Bool prop_respetuosos2 xs = length (respetuosos (nub (reverse (sort xs)))) <= 1 -- La comprobación es -- λ> quickCheck prop_respetuosos2 -- +++ OK, passed 100 tests.