Diagonales de matrices como listas
Las matrices se pueden representar como listas de listas de la misma longitud, donde cada uno de sus elementos representa una fila de la matriz.
Definir la función
1 |
diagonal :: [[a]] -> [a] |
tal que (diagonal xss) es la diagonal de la matriz xss. Por ejemplo,
1 2 3 4 |
diagonal [[3,5,2],[4,7,1],[6,9,0]] == [3,7,0] diagonal [[3,5],[4,7],[6,9]] == [3,7] diagonal [[3,5,2],[4,7,1]] == [3,7] sum (diagonal (replicate 20000 [1..20000])) == 200010000 |
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 32 33 34 35 36 37 38 39 |
import Data.Array ((!), listArray) import Data.Matrix (fromLists, getDiag) import Data.Vector (toList) -- 1ª definición (por recursión): diagonal1 :: [[a]] -> [a] diagonal1 ((x:_):xss) = x : diagonal1 [tail xs | xs <- xss] diagonal1 _ = [] -- 2ª definición (por comprensión): diagonal2 :: [[a]] -> [a] diagonal2 xss = [xs!!k | (xs,k) <- zip xss [0..n]] where n = length (head xss) - 1 -- 3ª definición (con Data.Matrix) diagonal3 :: [[a]] -> [a] diagonal3 = toList . getDiag . fromLists -- 4ª definición (con Data.Array) diagonal4 :: [[a]] -> [a] diagonal4 xss = [p!(i,i) | i <- [1..k]] where m = length xss n = length (head xss) k = min m n p = listArray ((1,1),(m,n)) (concat xss) -- Comparación de eficiencia -- λ> let n = 3000 in sum (diagonal1 (replicate n [1..n])) -- 4501500 -- (2.08 secs, 754,089,992 bytes) -- λ> let n = 3000 in sum (diagonal2 (replicate n [1..n])) -- 4501500 -- (0.06 secs, 0 bytes) -- λ> let n = 3000 in sum (diagonal3 (replicate n [1..n])) -- 4501500 -- (1.22 secs, 1,040,787,360 bytes) -- λ> let n = 3000 in sum (diagonal4 (replicate n [1..n])) -- 4501500 -- (0.96 secs, 624,463,632 bytes) |
Solución con Maxima
1 2 3 4 5 |
diagonal (xss) := block ([A], A : apply (matrix, xss), [m,n] : matrix_size (A), k : min (m,n), makelist (A[i,i],i,k))$ |
Utilizando las librerías, aunque es mucho más lento:
Con Maxima