En la clase hoy de Informática de 1º del Grado en Matemáticas hemos comentado las soluciones de los ejercicios sobre vectores y matrices en Haskell de la relación 14.
Los ejercicios y su solución se muestran a continuación
-- --------------------------------------------------------------------- -- Introducción -- -- --------------------------------------------------------------------- -- El objetivo de esta relación es hacer ejercicios sobre vectores y -- matrices con el tipo de las tablas, definido en el módulo -- Data.Array y explicado en el tema 18 que se encuentra en -- http://www.cs.us.es/~jalonso/cursos/i1m-19/temas/tema-18.html -- --------------------------------------------------------------------- -- Importación de librerías -- -- --------------------------------------------------------------------- import Data.Array -- --------------------------------------------------------------------- -- Tipos de los vectores y de las matrices -- -- --------------------------------------------------------------------- -- Los vectores son tablas cuyos índices son números naturales. type Vector a = Array Int a -- Las matrices son tablas cuyos índices son pares de números -- naturales. type Matriz a = Array (Int,Int) a -- --------------------------------------------------------------------- -- Operaciones básicas con matrices -- -- --------------------------------------------------------------------- -- --------------------------------------------------------------------- -- Ejercicio 1. Definir la función -- listaVector :: Num a => [a] -> Vector a -- tal que (listaVector xs) es el vector correspondiente a la lista -- xs. Por ejemplo, -- ghci> listaVector [3,2,5] -- array (1,3) [(1,3),(2,2),(3,5)] -- --------------------------------------------------------------------- listaVector :: Num a => [a] -> Vector a listaVector xs = listArray (1,n) xs where n = length xs -- --------------------------------------------------------------------- -- Ejercicio 2. Definir la función -- listaMatriz :: Num a => [[a]] -> Matriz a -- tal que (listaMatriz xss) es la matriz cuyas filas son los elementos -- de xss. Por ejemplo, -- ghci> listaMatriz [[1,3,5],[2,4,7]] -- array ((1,1),(2,3)) [((1,1),1),((1,2),3),((1,3),5), -- ((2,1),2),((2,2),4),((2,3),7)] -- --------------------------------------------------------------------- listaMatriz :: Num a => [[a]] -> Matriz a listaMatriz xss = listArray ((1,1),(m,n)) (concat xss) where m = length xss n = length (head xss) -- --------------------------------------------------------------------- -- Ejercicio 3. Definir la función -- numFilas :: Num a => Matriz a -> Int -- tal que (numFilas m) es el número de filas de la matriz m. Por -- ejemplo, -- numFilas (listaMatriz [[1,3,5],[2,4,7]]) == 2 -- --------------------------------------------------------------------- numFilas :: Num a => Matriz a -> Int numFilas = fst . snd . bounds -- --------------------------------------------------------------------- -- Ejercicio 4. Definir la función -- numColumnas :: Num a => Matriz a -> Int -- tal que (numColumnas m) es el número de columnas de la matriz -- m. Por ejemplo, -- numColumnas (listaMatriz [[1,3,5],[2,4,7]]) == 3 -- --------------------------------------------------------------------- numColumnas :: Num a => Matriz a -> Int numColumnas = snd . snd . bounds -- --------------------------------------------------------------------- -- Ejercicio 5. Definir la función -- dimension :: Num a => Matriz a -> (Int,Int) -- tal que (dimension m) es la dimensión de la matriz m. Por ejemplo, -- dimension (listaMatriz [[1,3,5],[2,4,7]]) == (2,3) -- --------------------------------------------------------------------- dimension :: Num a => Matriz a -> (Int,Int) dimension = snd . bounds -- --------------------------------------------------------------------- -- Ejercicio 6. Definir la función -- separa :: Int -> [a] -> [[a]] -- tal que (separa n xs) es la lista obtenida separando los elementos de -- xs en grupos de n elementos (salvo el último que puede tener menos de -- n elementos). Por ejemplo, -- separa 3 [1..11] == [[1,2,3],[4,5,6],[7,8,9],[10,11]] -- --------------------------------------------------------------------- separa :: Int -> [a] -> [[a]] separa _ [] = [] separa n xs = take n xs : separa n (drop n xs) -- --------------------------------------------------------------------- -- Ejercicio 7. Definir la función -- matrizLista :: Num a => Matriz a -> [[a]] -- tal que (matrizLista x) es la lista de las filas de la matriz x. Por -- ejemplo, -- ghci> let m = listaMatriz [[5,1,0],[3,2,6]] -- ghci> m -- array ((1,1),(2,3)) [((1,1),5),((1,2),1),((1,3),0), -- ((2,1),3),((2,2),2),((2,3),6)] -- ghci> matrizLista m -- [[5,1,0],[3,2,6]] -- --------------------------------------------------------------------- matrizLista :: Num a => Matriz a -> [[a]] matrizLista p = separa (numColumnas p) (elems p) -- --------------------------------------------------------------------- -- Ejercicio 8. Definir la función -- vectorLista :: Num a => Vector a -> [a] -- tal que (vectorLista x) es la lista de los elementos del vector -- v. Por ejemplo, -- ghci> let v = listaVector [3,2,5] -- ghci> v -- array (1,3) [(1,3),(2,2),(3,5)] -- ghci> vectorLista v -- [3,2,5] -- --------------------------------------------------------------------- vectorLista :: Num a => Vector a -> [a] vectorLista = elems -- --------------------------------------------------------------------- -- Suma de matrices -- -- --------------------------------------------------------------------- -- --------------------------------------------------------------------- -- Ejercicio 9. Definir la función -- sumaMatrices:: Num a => Matriz a -> Matriz a -> Matriz a -- tal que (sumaMatrices x y) es la suma de las matrices x e y. Por -- ejemplo, -- ghci> let m1 = listaMatriz [[5,1,0],[3,2,6]] -- ghci> let m2 = listaMatriz [[4,6,3],[1,5,2]] -- ghci> matrizLista (sumaMatrices m1 m2) -- [[9,7,3],[4,7,8]] -- --------------------------------------------------------------------- -- 1ª definición sumaMatrices :: Num a => Matriz a -> Matriz a -> Matriz a sumaMatrices p q = array ((1,1),(m,n)) [((i,j),p!(i,j)+q!(i,j)) | i <- [1..m], j <- [1..n]] where (m,n) = dimension p -- 2ª definición sumaMatrices2 :: Num a => Matriz a -> Matriz a -> Matriz a sumaMatrices2 p q = listArray (bounds p) (zipWith (+) (elems p) (elems q)) -- --------------------------------------------------------------------- -- Ejercicio 10. Definir la función -- filaMat :: Num a => Int -> Matriz a -> Vector a -- tal que (filaMat i p) es el vector correspondiente a la fila i-ésima -- de la matriz p. Por ejemplo, -- ghci> let p = listaMatriz [[5,1,0],[3,2,6],[4,5,7]] -- ghci> filaMat 2 p -- array (1,3) [(1,3),(2,2),(3,6)] -- ghci> vectorLista (filaMat 2 p) -- [3,2,6] -- --------------------------------------------------------------------- filaMat :: Num a => Int -> Matriz a -> Vector a filaMat i p = array (1,n) [(j,p!(i,j)) | j <- [1..n]] where n = numColumnas p -- --------------------------------------------------------------------- -- Ejercicio 11. Definir la función -- columnaMat :: Num a => Int -> Matriz a -> Vector a -- tal que (columnaMat j p) es el vector correspondiente a la columna -- j-ésima de la matriz p. Por ejemplo, -- ghci> let p = listaMatriz [[5,1,0],[3,2,6],[4,5,7]] -- ghci> columnaMat 2 p -- array (1,3) [(1,1),(2,2),(3,5)] -- ghci> vectorLista (columnaMat 2 p) -- [1,2,5] -- --------------------------------------------------------------------- columnaMat :: Num a => Int -> Matriz a -> Vector a columnaMat j p = array (1,m) [(i,p!(i,j)) | i <- [1..m]] where m = numFilas p -- --------------------------------------------------------------------- -- Producto de matrices -- -- --------------------------------------------------------------------- -- --------------------------------------------------------------------- -- Ejercicio 12. Definir la función -- prodEscalar :: Num a => Vector a -> Vector a -> a -- tal que (prodEscalar v1 v2) es el producto escalar de los vectores v1 -- y v2. Por ejemplo, -- ghci> let v = listaVector [3,1,10] -- ghci> prodEscalar v v -- 110 -- --------------------------------------------------------------------- -- 1ª solución prodEscalar :: Num a => Vector a -> Vector a -> a prodEscalar v1 v2 = sum [i*j | (i,j) <- zip (elems v1) (elems v2)] -- 2ª solución prodEscalar2 :: Num a => Vector a -> Vector a -> a prodEscalar2 v1 v2 = sum (zipWith (*) (elems v1) (elems v2)) -- --------------------------------------------------------------------- -- Ejercicio 13. Definir la función -- prodMatrices:: Num a => Matriz a -> Matriz a -> Matriz a -- tal que (prodMatrices p q) es el producto de las matrices p y q. Por -- ejemplo, -- ghci> let p = listaMatriz [[3,1],[2,4]] -- ghci> prodMatrices p p -- array ((1,1),(2,2)) [((1,1),11),((1,2),7),((2,1),14),((2,2),18)] -- ghci> matrizLista (prodMatrices p p) -- [[11,7],[14,18]] -- ghci> let q = listaMatriz [[7],[5]] -- ghci> prodMatrices p q -- array ((1,1),(2,1)) [((1,1),26),((2,1),34)] -- ghci> matrizLista (prodMatrices p q) -- [[26],[34]] -- --------------------------------------------------------------------- prodMatrices :: Num a => Matriz a -> Matriz a -> Matriz a prodMatrices p q = array ((1,1),(m,n)) [((i,j), prodEscalar (filaMat i p) (columnaMat j q)) | i <- [1..m], j <- [1..n]] where m = numFilas p n = numColumnas q -- --------------------------------------------------------------------- -- Matriz identidad -- -- --------------------------------------------------------------------- -- --------------------------------------------------------------------- -- Ejercicio 14. Definir la función -- identidad :: Num a => Int -> Matriz a -- tal que (identidad n) es la matriz identidad de orden n. Por ejemplo, -- ghci> identidad 3 -- array ((1,1),(3,3)) [((1,1),1),((1,2),0),((1,3),0), -- ((2,1),0),((2,2),1),((2,3),0), -- ((3,1),0),((3,2),0),((3,3),1)] -- --------------------------------------------------------------------- identidad :: Num a => Int -> Matriz a identidad n = array ((1,1),(n,n)) [((i,j),f i j) | i <- [1..n], j <- [1..n]] where f i j | i == j = 1 | otherwise = 0 -- --------------------------------------------------------------------- -- Ejercicio 15. Definir la función -- potencia :: Num a => Matriz a -> Int -> Matriz a -- tal que (potencia p n) es la potencia n-ésima de la matriz cuadrada -- p. Por ejemplo, si q es la matriz definida por -- q1 :: Matriz Int -- q1 = listArray ((1,1),(2,2)) [1,1,1,0] -- entonces -- ghci> potencia q1 2 -- array ((1,1),(2,2)) [((1,1),2),((1,2),1),((2,1),1),((2,2),1)] -- ghci> potencia q1 3 -- array ((1,1),(2,2)) [((1,1),3),((1,2),2),((2,1),2),((2,2),1)] -- ghci> potencia q1 4 -- array ((1,1),(2,2)) [((1,1),5),((1,2),3),((2,1),3),((2,2),2)] -- ¿Qué relación hay entre las potencias de la matriz q y la sucesión de -- Fibonacci? -- --------------------------------------------------------------------- q1 :: Matriz Int q1 = listArray ((1,1),(2,2)) [1,1,1,0] potencia :: Num a => Matriz a -> Int -> Matriz a potencia p 0 = identidad n where (_,(n,_)) = bounds p potencia p n = prodMatrices p (potencia p (n-1)) -- --------------------------------------------------------------------- -- Traspuestas -- -- --------------------------------------------------------------------- -- --------------------------------------------------------------------- -- Ejercicio 16. Definir la función -- traspuesta :: Num a => Matriz a -> Matriz a -- tal que (traspuesta p) es la traspuesta de la matriz p. Por ejemplo, -- ghci> let p = listaMatriz [[5,1,0],[3,2,6]] -- ghci> traspuesta p -- array ((1,1),(3,2)) [((1,1),5),((1,2),3), -- ((2,1),1),((2,2),2), -- ((3,1),0),((3,2),6)] -- ghci> matrizLista (traspuesta p) -- [[5,3],[1,2],[0,6]] -- --------------------------------------------------------------------- traspuesta :: Num a => Matriz a -> Matriz a traspuesta p = array ((1,1),(n,m)) [((i,j), p!(j,i)) | i <- [1..n], j <- [1..m]] where (m,n) = dimension p -- --------------------------------------------------------------------- -- Submatriz -- -- --------------------------------------------------------------------- -- --------------------------------------------------------------------- -- Tipos de matrices -- -- --------------------------------------------------------------------- -- --------------------------------------------------------------------- -- Ejercicio 17. Definir la función -- esCuadrada :: Num a => Matriz a -> Bool -- tal que (esCuadrada p) se verifica si la matriz p es cuadrada. Por -- ejemplo, -- ghci> let p = listaMatriz [[5,1,0],[3,2,6]] -- ghci> esCuadrada p -- False -- ghci> let q = listaMatriz [[5,1],[3,2]] -- ghci> esCuadrada q -- True -- --------------------------------------------------------------------- esCuadrada :: Num a => Matriz a -> Bool esCuadrada x = numFilas x == numColumnas x -- --------------------------------------------------------------------- -- Ejercicio 18. Definir la función -- esSimetrica :: (Num a, Eq a) => Matriz a -> Bool -- tal que (esSimetrica p) se verifica si la matriz p es simétrica. Por -- ejemplo, -- ghci> let p = listaMatriz [[5,1,3],[1,4,7],[3,7,2]] -- ghci> esSimetrica p -- True -- ghci> let q = listaMatriz [[5,1,3],[1,4,7],[3,4,2]] -- ghci> esSimetrica q -- False -- --------------------------------------------------------------------- esSimetrica :: (Num a, Eq a) => Matriz a -> Bool esSimetrica x = x == traspuesta x -- --------------------------------------------------------------------- -- Diagonales de una matriz -- -- --------------------------------------------------------------------- -- --------------------------------------------------------------------- -- Ejercicio 19. Definir la función -- diagonalPral :: Num a => Matriz a -> Vector a -- tal que (diagonalPral p) es la diagonal principal de la matriz p. Por -- ejemplo, -- ghci> let p = listaMatriz [[5,1,0],[3,2,6]] -- ghci> diagonalPral p -- array (1,2) [(1,5),(2,2)] -- ghci> vectorLista (diagonalPral p) -- [5,2] -- --------------------------------------------------------------------- diagonalPral :: Num a => Matriz a -> Vector a diagonalPral p = array (1,n) [(i,p!(i,i)) | i <- [1..n]] where n = min (numFilas p) (numColumnas p) -- --------------------------------------------------------------------- -- Ejercicio 20. Definir la función -- diagonalSec :: Num a => Matriz a -> Vector a -- tal que (diagonalSec p) es la diagonal secundaria de la matriz p. Por -- ejemplo, -- ghci> let p = listaMatriz [[5,1,0],[3,2,6]] -- ghci> diagonalSec p -- array (1,2) [(1,1),(2,3)] -- ghci> vectorLista (diagonalSec p) -- [1,3] -- ghci> let q = traspuesta p -- ghci> matrizLista q -- [[5,3],[1,2],[0,6]] -- ghci> vectorLista (diagonalSec q) -- [3,1] -- --------------------------------------------------------------------- diagonalSec :: Num a => Matriz a -> Vector a diagonalSec p = array (1,n) [(i,p!(i,n+1-i)) | i <- [1..n]] where n = min (numFilas p) (numColumnas p) -- --------------------------------------------------------------------- -- Submatrices -- -- --------------------------------------------------------------------- -- --------------------------------------------------------------------- -- Ejercicio 21. Definir la función -- submatriz :: Num a => Int -> Int -> Matriz a -> Matriz a -- tal que (submatriz i j p) es la matriz obtenida a partir de la p -- eliminando la fila i y la columna j. Por ejemplo, -- ghci> let p = listaMatriz [[5,1,0],[3,2,6],[4,6,9]] -- ghci> submatriz 2 3 p -- array ((1,1),(2,2)) [((1,1),5),((1,2),1),((2,1),4),((2,2),6)] -- ghci> matrizLista (submatriz 2 3 p) -- [[5,1],[4,6]] -- --------------------------------------------------------------------- submatriz :: Num a => Int -> Int -> Matriz a -> Matriz a submatriz i j p = array ((1,1), (m-1,n -1)) [((k,l), p ! f k l) | k <- [1..m-1], l <- [1.. n-1]] where (m,n) = dimension p f k l | k < i && l < j = (k,l) | k >= i && l < j = (k+1,l) | k < i && l >= j = (k,l+1) | otherwise = (k+1,l+1) -- --------------------------------------------------------------------- -- Determinante -- -- --------------------------------------------------------------------- -- --------------------------------------------------------------------- -- Ejercicio 22. Definir la función -- determinante:: Matriz Double -> Double -- tal que (determinante p) es el determinante de la matriz p. Por -- ejemplo, -- ghci> determinante (listArray ((1,1),(3,3)) [2,0,0,0,3,0,0,0,1]) -- 6.0 -- ghci> determinante (listArray ((1,1),(3,3)) [1..9]) -- 0.0 -- ghci> determinante (listArray ((1,1),(3,3)) [2,1,5,1,2,3,5,4,2]) -- -33.0 -- --------------------------------------------------------------------- determinante :: Matriz Double -> Double determinante p | (m,n) == (1,1) = p!(1,1) | otherwise = sum [((-1)^(i+1))*(p!(i,1))*determinante (submatriz i 1 p) | i <- [1..m]] where (_,(m,n)) = bounds p |