Repetición cíclica
Enunciado
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
-- Definir la función -- ciclica :: [a] -> [a] -- tal que (ciclica xs) es la lista obtenida repitiendo cíclicamente los -- elementos de xs. Por ejemplo, -- take 10 (ciclica [3,5]) == [3,5,3,5,3,5,3,5,3,5] -- take 10 (ciclica [3,5,7]) == [3,5,7,3,5,7,3,5,7,3] -- take 10 (ciclica [3,5..]) == [3,5,7,9,11,13,15,17,19,1] -- ciclica [] == [] -- -- Comprobar con QuickCheck que la función ciclica es equivalente a la -- predefinida cycle; es decir, para cualquier número entero n y -- cualquier lista no vacía xs, se verifica que -- take n (ciclica xs) == take n (cycle xs) -- -- Nota. Al hacer la comprobación limitar el tamaño de las pruebas como -- se indica a continuación -- ghci> quickCheckWith (stdArgs {maxSize=7}) prop_ciclica -- +++ OK, passed 100 tests. |
Soluciones
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
import Test.QuickCheck -- 1ª definición ciclica1 :: [a] -> [a] ciclica1 [] = [] ciclica1 xs = xs ++ ciclica1 xs -- 2ª definición ciclica2 :: [a] -> [a] ciclica2 [] = [] ciclica2 xs = ys where ys = xs ++ ys -- Comprobación de eficiencia -- ghci> last (take 10000000 (ciclica1 [1,2])) -- 2 -- (3.69 secs, 1521758928 bytes) -- -- ghci> last (take 10000000 (ciclica2 [1,2])) -- 2 -- (0.21 secs, 561468144 bytes) -- La 2ª definición es más eficiente. -- La propiedad es prop_ciclica :: Int -> [Int] -> Property prop_ciclica n xs = not (null xs) ==> take n (ciclica2 xs) == take n (cycle xs) -- La comprobación es -- ghci> quickCheckWith (stdArgs {maxSize=7}) prop_ciclica -- +++ OK, passed 100 tests. |
Una definición más eficiente sería:
Mi definición es la misma que la de Jesús pero añadiendo el caso de la lista vacía porque creo que es necesario.