-- | -- Module : Lista_cuadrada -- Description : Lista cuadrada. -- Copyright : Exercitium (06-05-14) -- License : GPL-3 -- Maintainer : JoseA.Alonso@gmail.com -- -- Definir la función -- -- > listaCuadrada :: Int -> a -> [a] -> [[a]] -- -- tal que __(listaCuadrada n x xs)__ es una lista de n listas de longitud n -- formadas con los elementos de xs completada con x, si no xs no tiene -- suficientes elementos. Por ejemplo, -- -- >>> listaCuadrada 3 7 [0,3,5,2,4] -- [[0,3,5],[2,4,7],[7,7,7]] -- >>> listaCuadrada 3 7 [0..] -- [[0,1,2],[3,4,5],[6,7,8]] -- >>> listaCuadrada 2 'p' "eva" -- ["ev","ap"] -- >>> listaCuadrada 2 'p' ['a'..] -- ["ab","cd"] -- >>> listaCuadrada 1 0 ([]::[Int]) -- [[0]] module Lista_cuadrada where import Test.QuickCheck -- | 1ª definición (con auxiliar). listaCuadrada :: Int -> a -> [a] -> [[a]] listaCuadrada n x xs = take n (grupos n (xs ++ repeat x)) -- | (grupos n xs) es la lista obtenida agrupando los elementos de xs en -- grupos de n elementos, salvo el último que puede tener menos. Por -- ejemplo, -- -- >>> grupos 2 [4,2,5,7,6] -- [[4,2],[5,7],[6]] -- >>> take 3 (grupos 3 [1..]) -- [[1,2,3],[4,5,6],[7,8,9]] grupos :: Int -> [a] -> [[a]] grupos _ [] = [] grupos n xs = take n xs : grupos n (drop n xs) -- | 2ª definición (por comprensión). listaCuadrada2 :: Int -> a -> [a] -> [[a]] listaCuadrada2 n x xs = take n [take n (drop m xs ++ repeat x) | m <- [0,n..n*n]] -- | 3ª definición (por iteración). listaCuadrada3 :: Int -> a -> [a] -> [[a]] listaCuadrada3 n x xs = take n [take n ys | ys <- iterate (drop n) (xs ++ repeat x)] -- | 4ª definición (por iteración sin el último argumento). listaCuadrada4 :: Int -> a -> [a] -> [[a]] listaCuadrada4 n x = take n . map (take n) . iterate (drop n) . (++ repeat x) -- | (prop_listaCuadrada n x xs) se verifica si las definiciones de -- listaCuadrada son equivalentes sobre n, x, xs. Por ejemplo, -- -- >>> prop_listaCuadrada (NonNegative 3) 7 [0,3,5,2,4] -- True -- >>> prop_listaCuadrada (NonNegative 3) 7 [0..] -- True prop_listaCuadrada :: NonNegative Int -> Int -> [Int] -> Bool prop_listaCuadrada (NonNegative n) x xs = all (== listaCuadrada n x xs) [f n x xs | f <- [ listaCuadrada2 , listaCuadrada2 , listaCuadrada4 ]] -- | Comprueba la equivalencia de las definiciones de listaCuadrada. -- -- >>> verifica_listaCuadrada -- +++ OK, passed 100 tests. verifica_listaCuadrada :: IO () verifica_listaCuadrada = quickCheck prop_listaCuadrada