Acá va el ejercicio de matrices cuadradas... y un módulo implementado.
Aclaración 1: el módulo de matrices funciona con matrices cuadradas de dimensión 3... está modelado como una lista de tres tuplas ternarias, y viene con una funcion "crearM" que le pasan los valores de las filas todos seguidos y les crea la matriz (hay un ejemplo ahí). Si a alguien se le ocurre un módulo más flexible (matrices cuadradas se cualquier dimensión) es bienvenido!
Aclaración 2: algunos items no quedaron muy declarativos que digamos... si no se entiende bien pregunten.
Recomendación: el módulo lo hice después de escribir el ejercicio como para poder cargarlo y que el hugs me tire los errores antes de subirlo (para no subir cualquier batata). de paso sirve para testear, pero la idea del ejercicio me parece que es que uno se acostumbre a pensar el problema sin tener el módulo hecho...
Ejercicio y módulo (para bajar)
CÓDIGO
todosIguales :: MatrizCuadrada -> Bool
todosIguales m = (chequeaColumnas m) && (chequeaFilas m)
where d = dimension m
identidad :: MatrizCuadrada -> Bool
identidad m = auxId m d
where d = dimension m
maximo :: MatrizCuadrada -> Int
maximo m = maxi valores
where valores = columnasConcat m (dimension m)
minimo :: MatrizCuadrada -> Int
minimo m = mini valores
where valores = columnasConcat m (dimension m)
todosIguales2 :: MatrizCuadrada -> Bool
todosIguales2 m = (minimo m) == (maximo m)
esDegrade :: MatrizCuadrada -> Bool
esDegrade m = (creciente (fila m d)) && (auxDegrade m (d-1))
where d = dimension m
-- AUXILIARES --
chequeaColumnas :: MatrizCuadrada -> Bool
chequeaColumnas m = evaluarTuplas (auxTupCol m d d)
where d = dimension m
chequeaFilas :: MatrizCuadrada -> Bool
chequeaFilas m = evaluarTuplas (auxTupFil m d d)
where d = dimension m
evaluaColumna :: MatrizCuadrada -> Int -> Int -> (Bool,Int) -- Se pasa la matriz, su dimension (que va a ir bajando) y la columna a evaluar.
evaluaColumna m f c
| f==1 = ( True , (valor m 1 c) )
| (valor m f c) == (valor m (f-1) c) = evaluaColumna m (f-1) c
| otherwise = (False,0)
evaluaFila :: MatrizCuadrada -> Int -> Int -> (Bool,Int) -- Se pasa la matriz, la fila a evaluar y su dimension (que va a ir bajando).
evaluaFila m f c
| c==1 = ( True , (valor m f 1) )
| (valor m f c) == (valor m f (c-1)) = evaluaColumna m f (c-1)
| otherwise = (False,0)
auxTupCol :: MatrizCuadrada -> Fila -> Columna -> [(Bool,Int)]
auxTupCol m df 1 = [evaluaColumna m df 1]
auxTupCol m df dc = (evaluaColumna m df dc):(auxTupCol m df (dc -1))
auxTupFil :: MatrizCuadrada -> Fila -> Columna -> [(Bool,Int)]
auxTupFil m 1 dc = [evaluaFila m 1 dc]
auxTupFil m df dc = (evaluaColumna m df dc):(auxTupCol m (df-1) dc)
evaluarTuplas :: [(Bool, Int)] -> Bool
evaluarTuplas (x:[])
| (fst x)==True = True
| otherwise = False
evaluarTuplas (x:(y:ys))
| (fst x)==(fst y) && (snd x)==(snd y) = evaluarTuplas (y:ys)
| otherwise = False
-------------
auxId :: MatrizCuadrada -> Int -> Bool
auxId m 1 = chequeaDiagonal m 1
auxId m n = (chequeaDiagonal m n) && (chequeaDiagonal m (n-1))
chequeaDiagonal :: MatrizCuadrada -> Int -> Bool
chequeaDiagonal m n = (valor m n n)==1 && (cerosAbajo m n n) && (cerosArriba m n n)
cerosAbajo :: MatrizCuadrada -> Fila -> Columna -> Bool
cerosAbajo m f c
| f==(dimension m) =True
| otherwise = (valor m (f+1) c)==0 && (cerosAbajo m (f+1) c)
cerosArriba :: MatrizCuadrada -> Fila -> Columna -> Bool
cerosArriba m f c
| f==1 =True
| otherwise = (valor m (f-1) c)==0 && (cerosArriba m (f-1) c)
-------------
columna :: MatrizCuadrada -> Fila -> Columna -> [Int] --como fila siempre se va a pasar la dimension de la matriz.
columna m 1 c = [valor m 1 c]
columna m f c = (columna m (f-1) c) ++ [valor m f c]
columnasConcat :: MatrizCuadrada -> Columna -> [Int] --como columna siempre se va a pasar la dimension de la matriz.
columnasConcat m 1 = columna m d 1
where d = dimension m
columnasConcat m c = (columna m d c)++(columnasConcat m (c-1))
where d = dimension m
maxi :: [Int] -> Int
maxi (x:[]) = x
maxi (x:xs)
| x>(head xs) = maxi (x:(tail xs))
| otherwise = maxi xs
mini :: [Int] -> Int
mini (x:[]) = x
mini (x:xs)
| x<(head xs) = mini (x:(tail xs))
| otherwise = mini xs
--------------
auxFila :: MatrizCuadrada -> Fila -> Columna -> [Int] --busco las filas básicamente igual que hice con las columnas antes.
auxFila m f 1 = [valor m f 1]
auxFila m f c = (auxFila m f (c-1)) ++ [valor m f c]
fila :: MatrizCuadrada -> Fila -> [Int]
fila m f = auxFila m f (dimension m)
creciente :: [Int] -> Bool
creciente (x:[]) = True
creciente (x:xs)
| x < (head xs) = creciente xs
| otherwise = False
esFilaSiguiente :: [Int] -> [Int] -> Bool --se fija si la primer fila es la que va arriba de la segunda
esFilaSiguiente l1 l2 = (init l1)==(tail l2) && (creciente l1)
auxDegrade :: MatrizCuadrada -> Fila -> Bool --se va a pasar siempre como fila la dimension -1
auxDegrade m 1 = esFilaSiguiente (fila m 1) (fila m 2)
auxDegrade m f = (esFilaSiguiente (fila m f) (fila m (f+1))) && (auxDegrade m (f-1))