Tema

P8, ej 2 + Módulo para testear

6 respuestas 8379 visitas

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))

Este es mi modulo, hice un poquito de trampa xq mi idea era hacer el modulo como sea (usando cualqueir funcion) y despues hacer los ejercicios restringiendome a las funciones q nos dieron.
La idea de esto es que toma una lista de Int, de longitud n, siendo n un cuadrado (sino el modulo te putea, como veran ahi). Funciona para cualquier dimension, y de paso arme las matrices que estaban de ejemplo y las exporte para usarlas en los ejercicios.
Me iba a hacer un Show para que se vieran lindas las matrices, pero la idea quedo ahi y no lo hice...

module MatrizCuadrada (MatrizCuadrada,dimension,valor, matriz1,matriz2,matriz3,matriz4,matriz5) where

data MatrizCuadrada = Elems [Int]
	
type Fila    = Int
type Columna = Int

matriz1 = Elems [3,1,6,2,5,3,5,4,1]
matriz2 = Elems [4,6,25,75,99,3,4,6,25,75,2,3,4,6,25,1,2,3,4,6,0,1,2,3,4]
matriz3 = Elems [4,6,25,75,3,4,6,25,8,3,4,6,1,8,3,4]
matriz4 = Elems [99,8,7,8,7,3,7,3,1]
matriz5 = Elems [7,11,13,2,8,11,1,2,9]

dimension:: MatrizCuadrada -> Int
dimension (Elems x) | (isqrt len)*(isqrt len) == len = isqrt len
                    | otherwise                 = error"eh wacho, esa matriz no vale gato"
	where len = length x

valor :: MatrizCuadrada -> Fila -> Columna -> Int
valor x i j | i > dimension x || j > dimension x || i<1 || j<1 = error"eeeeeeeEEEEEEEeeeeeeeeee"
valor (Elems x) i j  = x !! ((i-1)*(dimension (Elems x))+(j-1))	  

isqrt :: Integral a => a -> a
isqrt = floor . sqrt . fromIntegral

Buenísimo, había pensado algo parecido cuando me fui a dormir pero ni daba prender la compu de nuevo y ponerme pensar jaja.

Igual me parece re pro que puedas cambiar todo el módulo y sigan funcionando las funciones igual, no?

Nico sos un hereje!
dejá de ver las cosas que no vas a poder usar en el parcial xq ya veo que no vas a poder pensar los ejercicios con las limitaciones.

A alguien se le ocurre una definición linda del módulo MatrizCuadrada genérico usando únicamente las cosas que permite la materia? yo estuve un buen rato pensando y no llegué a ninguna idea aceptable.

Firma

"If debugging is the process of removing bugs, then programming must be the process of putting them in." -- Dijkstra

acá hay otra implementación bastante simple...

quedó bastante parecida a la de nico igual.

esa matriz "mat" que quedó es un degradé que la dejé para probar la función del ejercicio.

saludos!

module Mcuad (MatrizCuadrada, Fila, Columna, valor, dimension, crearM, mat)
	where
	
data MatrizCuadrada = M Int [Int]
	deriving (Eq, Show)

type Fila = Int
type Columna = Int

valor :: MatrizCuadrada -> Fila -> Columna -> Int
valor (M dim coef) f c = coef!!(dim*(f-1)+(c-1))

dimension :: MatrizCuadrada -> Int
dimension (M dim coef) = dim

crearM :: Int -> [Int] -> MatrizCuadrada
crearM dim coef | (length coef)==(dim^2) = (M dim coef)

mat = M 4 [6,7,8,9,5,6,7,8,4,5,6,7,3,4,5,6]

Esa era la solución "fea" que se me había ocurrido.. lo que intentaba hacer es que la matriz esté hecha "recursivamente" con constructores, pero creo que no hay manera.

che dani, ese modulo mio re valee
jaja
en el instance del show q no subi, era mas ilegal, aca lo unico ilegal q quedo es

isqrt :: Integral a => a -> a
isqrt = floor . sqrt . fromIntegral

el "." es composicion de funciones, eso vendria a ser algo tipo

isqrt = floor ( sqrt ( fromIntegral a ) )

y desp nada mas esta ilegal xD