Last active
November 19, 2019 07:10
-
-
Save vitaminac/1f3fe97ce71784ff7366894c8d4d12c2 to your computer and use it in GitHub Desktop.
Haskell Ejercicio URJC
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module HashkellEj where | |
import Data.Char | |
import Data.List | |
---------------------- TEMA 2 ---------------------- | |
-- Implementar una función en Haskell que dados tres números enteros | |
-- determine si están ordenados de menor a mayor. | |
estanOrdenados :: Int -> Int -> Int -> Bool | |
estanOrdenados x y z = (x < y) && (y < z) | |
-- Implementar una función en Haskell que dados tres números enteros | |
-- los devuelva ordenados de menor a mayor | |
ordenarTresNumeros :: Int -> Int -> Int -> [Int] | |
ordenarTresNumeros x y z | |
| ((x <= y) && (y <= z)) = [x, y, z] | |
| ((x <= z) && (z <= y)) = [x, z, y] | |
| ((y <= x) && (x <= z)) = [y, x, z] | |
| ((y <= z) && (z <= x)) = [y, z, x] | |
| ((z <= x) && (x <= y)) = [z, x, y] | |
| otherwise = [z, y, x] | |
-- Implementar en Haskell una función que reciba un número real | |
-- y devuelva una tupla con su parte entera | |
-- y sus dos primeros decimales (como número entero). | |
tuplarDecimal :: Double -> (Int, Int) | |
tuplarDecimal n = (truncate n, mod (truncate (n * 100)) 100) | |
-- Crear una función que reciba el radio de una circunferencia | |
-- y devuelva una 2-tupla con la longitud de la circunferencia | |
-- y con el área del círculo. | |
-- Emplea una definición local | |
-- con la cláusula where para almacenar el valor de Pi | |
longArea :: Float -> (Float, Float) | |
longArea r = (2 * p_i * r, p_i * r^2) | |
where | |
p_i = 3.1415926 | |
-- A continuación crear una función | |
-- con el mismo cometido empleando la definición local let | |
longAreaLet :: Float -> (Float, Float) | |
longAreaLet r = let p_i = 3.1415926 in (2 * p_i * r, p_i * r^2) | |
-- Implementar la función predefinida de listas concat, | |
-- que se llamará concatenar, | |
-- utilizando la definición de listas por comprensión | |
concatenar :: [[Int]] -> [Int] | |
concatenar l = [y |x <- l, y <- x] | |
-- Implementar una función que dado un número entero | |
-- devuelva en una lista todos los | |
-- factores de dicho número. | |
-- Se debe utilizar la definición | |
-- de listas por comprensión. | |
factores :: Int->[Int] | |
factores n = [x | x <- [1..div n 2], mod n x == 0] ++ [n] | |
-- Implementar una función que diga si un número es primo. | |
-- Para ello se debe utilizar la función | |
-- que calcula el número de factores de un número (ejercicio f). | |
esPrimo :: Int -> Bool | |
esPrimo n = (length (factores n)) == 2 | |
-- Implementar una función que diga | |
-- cuántos caracteres en mayúscula están contenidos | |
-- en una frase dada. | |
-- Se deberá utilizar la definición de listas por comprensión. | |
cuantasMayusculas :: [Char] -> Int | |
cuantasMayusculas string = length ([c | c <- string, isUpper c]) | |
-- Implementar una función que dada una tupla de tres elementos, donde cada uno de | |
-- ellos es a su vez una tupla de dos elementos de tipo String e Int respectivamente, | |
-- retorne el primer elemento de cada tupla interna. Se deberá utilizar ajuste de patrones. | |
primerElemento :: ((String, Int), (String, Int), (String, Int)) -> [String] | |
primerElemento ((x1, y1), (x2, y2), (x3, y3)) = [x1, x2, x3] | |
-- Implementar una función que devuelve True si la suma de los cuatro primeros | |
-- elementos de una lista de números enteros es un valor menor a 10 y devolverá False | |
-- en caso contrario. Se deberá utilizar ajuste de patrones. | |
sumaMayor10 :: [Int] -> Bool | |
sumaMayor10 l = (sum (take 4 l)) < 10 | |
-- Implementar una función que dado un carácter, | |
-- que representa un punto cardinal, | |
-- devuelva su descripción. Por ejemplo, dado ‘N’ devuelva “Norte” | |
puntoCardenal :: Char -> String | |
puntoCardenal 'N' = "Norte" | |
puntoCardenal 'S' = "Sur" | |
puntoCardenal 'E' = "Este" | |
puntoCardenal 'O' = "Oeste" | |
-- Implementar una función que dada una frase | |
-- retorne un mensaje donde se indique cuál | |
-- es la primera y última letra de la frase original. | |
procesarFrase :: [Char] -> [Char] | |
procesarFrase frase = "La primera letra de la frase ''" ++ frase ++ "'' es '" ++ [frase!!0] ++ "' y la ultima letra es '" ++ [last frase] ++ "'" | |
-- Implementar una función que dado un número entero devuelva mensajes indicando en | |
-- qué rango de valores se encuentra dicho número (menor de 10, entre 10 y 20 o mayor | |
-- de 20). Se debe utilizar definiciones locales. | |
rango20 :: Int -> [Char] | |
rango20 n = | |
if n < 10 then mensaje1 | |
else if (n >= 10) && (n <= 20) then mensaje2 | |
else mensaje3 | |
where | |
mensaje1 = "El valor de entrada es menor que 10" | |
mensaje2 = "El valor de entrada es mayor o igual a 10 y menor o igual a 20" | |
mensaje3 = "El valor de entrada es mayor que 20" | |
-- Implementar una función que dada una cadena de caracteres y un carácter, indique el | |
-- número de apariciones del carácter en la cadena. No se debe utilizar recursividad, sí | |
-- ajuste de patrones. Pista: utilizar la definición de listas por comprensión. | |
contarAparicion :: String -> Char -> Int | |
contarAparicion [] c = 0 | |
contarAparicion str c = length ([x | x <- str, x == c]) | |
---------------------- TEMA 4 ---------------------- | |
-- Implementa una función en Haskell que elimine de una lista de enteros aquellos | |
-- números múltiplo de x. | |
-- listas por comprensión | |
eliminarMultiplo1 :: [Int] -> Int -> [Int] | |
eliminarMultiplo1 l x = [e | e <- l, mod e x /= 0] | |
-- no final | |
eliminarMultiplo2 :: [Int] -> Int -> [Int] | |
eliminarMultiplo2 [] n = [] | |
eliminarMultiplo2 (x:xs) n | |
| mod x n == 0 = new_rest | |
| otherwise = x:new_rest | |
where new_rest= eliminarMultiplo2 xs x | |
-- final | |
eliminarMultiplo3 :: [Int] -> Int -> [Int] -> [Int] | |
eliminarMultiplo3 [] x ac = ac | |
eliminarMultiplo3 (e:rest) x ac | |
| (mod e x) == 0 = eliminarMultiplo3 rest x ac | |
| otherwise = eliminarMultiplo3 rest x (ac ++ [e]) | |
-- Dada la siguiente definición de función | |
-- doble :: Int -> Int | |
-- doble x = x + x | |
-- ¿Cómo cambiaría la definición utilizando expresiones lambda? | |
doubl = (\x -> x + x) | |
-- Se pide una función en Haskell | |
-- que dada una lista de números enteros obtenga un | |
-- número entero con el resultado de | |
-- calcular el doble de cada uno de los elementos de la | |
-- lista original y sumarlos todos. | |
-- Se piden diferentes versiones de la misma función: | |
-- Con recursividad no final | |
sumarDouble1 :: [Int] -> Int | |
sumarDouble1 [] = 0 | |
sumarDouble1 (x:xs) = (doubl x) + (sumarDouble1 xs) | |
-- Con recursividad final | |
sumarDouble2 :: [Int] -> Int -> Int | |
sumarDouble2 [] ac = ac | |
sumarDouble2 (x:xs) ac = sumarDouble2 xs ((doubl x) + ac) | |
-- Utilizando expresiones lambda u orden superior (se puede hacer uso de la | |
-- función predefinida de Haskell map) | |
sumarDouble3 :: [Int] -> Int | |
sumarDouble3 l = foldr (+) 0 (map(doubl) l) | |
-- Implementa una función que sume los cuadrados de los números pares contenidos en | |
-- una lista de números enteros. | |
-- Una versión que haga uso de las funciones de orden superior de | |
-- listas map y filter para definir la nueva función. | |
sumarCuadrado1 :: [Int] -> Int | |
sumarCuadrado1 l = sum (map (^2) (filter even l)) | |
-- Una versión que utilice la definición | |
-- de listas por comprensión. | |
sumarCuadrado2 :: [Int] -> Int | |
sumarCuadrado2 l = sum [x^2 | x <- l, even x] | |
-- Dada una lista de enteros, implementar una función para devolver tuplas formadas por | |
-- los elementos (sin repetir) de la lista, junto con la primera posición en la que aparecen. | |
primeraPos :: [Int] -> [(Int, Int)] | |
primeraPos l = filter (\(ee, ii) -> all (\(eee, iii) -> (eee /= ee) || (ii <= iii)) tuples) tuples | |
where tuples = [(e, idx) | (e,idx) <- enumerate l] | |
where enumerate x = zip x [1..] | |
-- Implementar en Haskell una función que | |
-- calcule el número de secuencias de ceros que | |
-- hay en una lista de números | |
secuenciaCeros :: [Int] -> Int | |
secuenciaCeros [] = 0 | |
secuenciaCeros [0] = 1 | |
secuenciaCeros [_] = 0 | |
secuenciaCeros (x:y:zs) = if (x == 0 && y /= 0) then 1 + secuenciaCeros (y:zs) else secuenciaCeros (y:zs) | |
-- Implementar una función en Haskell | |
-- que reciba una lista de números enteros y devuelva | |
-- dos listas: una con los elementos sin repetir | |
-- y otra con los elementos que están repetidos. | |
partirRepetido :: [Int] -> ([Int], [Int]) | |
partirRepetido l = foldl (\(ns,rs) x -> if (repetido x) then (ns++[x],rs) else (if all (\y -> y /= x) rs then (ns,rs++[x]) else (ns,rs))) ([],[]) l | |
where repetido x = length (filter (\y -> (y == x)) l) == 1 | |
-- Dada una lista de números enteros | |
-- implementar una función que devuelva una lista con | |
-- los n elementos mayores de la lista original. | |
nMayores :: [Int] -> Int -> [Int] | |
nMayores l n = [x | x <- l, length (filter (>x) l) < n] | |
-- Implementa una función incluye en Haskell | |
-- que reciba dos listas de números enteros y | |
-- nos diga si la primera de las listas | |
-- está contenida en la segunda. Se dice que una lista | |
-- está contenida en otra si los elementos | |
-- de la primera aparecen dentro de la segunda, en | |
-- el mismo orden y de forma consecutiva. | |
lista_contains :: [Int] -> [Int] -> Bool | |
lista_contains [] _ = True | |
lista_contains _ [] = False | |
lista_contains (x:xs) (y:ys) = (x == y && xs == (take (length xs) ys)) || (lista_contains (x:xs) ys) | |
-- Dada una lista de enteros, | |
-- se pide implementar una función que ordene dicha lista de | |
-- menor a mayor utilizando un algoritmo de inserción. | |
-- Dicho algoritmo de inserción | |
-- consiste en recorrer la lista L, | |
-- insertando cada elemento L[i] en el lugar correcto entre | |
-- los elementos ya ordenados L[1] ,...,L[i-1]. | |
insertar_uno :: Int -> [Int] -> [Int] | |
insertar_uno num [] = [num] | |
insertar_uno num (x:xs) = if (num < x) then num:x:xs else x:(insertar_uno num xs) | |
insert_sort :: [Int] -> [Int] | |
insert_sort l = foldr (\x l2 -> insertar_uno x l2) [] l | |
-- Implementa una función polimórfica en Haskell | |
-- que reciba 2 listas y vaya cogiendo un | |
-- elemento de la primera y dos de la segunda, | |
-- creando una lista final de ternas. En caso | |
-- de que una de las dos listas se acabe, | |
-- mostrará la lista de ternas construidas hasta ese | |
-- momento | |
concat_one_dos [] _ = [] | |
concat_one_dos _ [] = [] | |
concat_one_dos (x:xs) (y:z:zs) = (x,y,z):concat_one_dos xs zs | |
-- Se pide una función polimórfica en Haskell | |
-- que dado un elemento y una lista añada | |
-- dicho elemento al final de la lista. | |
insertar_final :: a -> [a] -> [a] | |
insertar_final n lista = lista ++ [n] | |
-- Mediante la programación de orden superior | |
-- se pide implementar una de las funciones | |
-- predefinidas en la librería estándar de Haskell: | |
-- la función zipWith. | |
-- Esta función recibe | |
-- como parámetros una función y dos listas | |
-- y une ambas listas aplicado la función entre | |
-- los correspondientes parámetros. | |
zipWith_ :: (a -> b -> c) -> [a] -> [b] -> [c] | |
zipWith_ f l1 l2 = [f x y |(x,y) <- zip l1 l2] | |
-- Define una función polimórfica | |
-- que sea capaz de invertir los elementos de una lista. | |
-- Se piden diferentes versiones: | |
-- recursividad no final | |
invertir_lista1 :: [a] -> [a] | |
invertir_lista1 [] = [] | |
invertir_lista1 (x:xs) = invertir_lista1 xs ++ [x] | |
-- recursividad de cola o final | |
invertir_lista2 :: [a] -> [a] -> [a] | |
invertir_lista2 [] l = l | |
invertir_lista2 (x:xs) l = invertir_lista2 xs (x:l) | |
-- Utilizando la función de orden superior foldr | |
invertir_lista3 :: [a] -> [a] | |
invertir_lista3 l = foldr (\x xs -> xs ++ [x]) [] l | |
-- Define una función polimórfica | |
-- que sea capaz de invertir | |
-- los elementos de una lista de listas. | |
invertir_lista_lista :: [[a]] -> [[a]] | |
invertir_lista_lista l = map (invertir_lista3) (invertir_lista3 l) | |
-- Implementar la función predefinida de la librería estándar flip. | |
-- Esta función lo que hace es recibir una función | |
-- y devolver otra función que es idéntica a la función original, | |
-- salvo que intercambia los dos primeros parámetros. | |
flip_ :: (a -> b -> c) -> b -> a -> c | |
flip_ f y x = f x y | |
-- Implementar la función polimórfica predefinida de la librería estándar map. | |
-- Esta función lo que hace es recibir una función | |
-- y una lista y devuelve la lista resultante de aplicar la | |
-- función a cada elemento de la lista original. | |
map_ :: (a -> b) -> [a] -> [b] | |
map_ f l = [f x | x <- l] | |
---------------------- TEMA 5 ---------------------- | |
-- Parte 1 | |
-- Se pide una función que dada una lista de racionales, | |
-- donde cada racional se define como | |
-- dos números enteros (numerador y denominador), | |
-- y un número racional, | |
-- devuelva otra lista | |
-- con todos los racionales equivalentes al dado. | |
-- Empleando type | |
type Racional1 = (Int, Int) | |
eq_lista1 :: [Racional1] -> Racional1 -> [Racional1] | |
eq_lista1 l (n1,n2) = [(x,y) | (x,y) <- l, n1*y == n2*x] | |
-- Empleando data | |
type Numerador = Int | |
type Denominador = Int | |
data Racional2 = R (Numerador,Denominador) | |
eq_lista2 :: [Racional2] -> Racional2 -> [Racional2] | |
eq_lista2 l (R (n1,n2)) = [(R (x,y)) | (R (x,y)) <- l, n1*y == n2*x] | |
instance Show Racional2 where | |
show (R (n1,n2)) = "R ("++ Prelude.show(n1) ++ "," ++ Prelude.show(n2)++ ")" | |
-- b) | |
-- Función que dado un punto de coordenadas | |
-- y una dirección (Norte, Sur, Este u Oeste) | |
-- mueva el punto hacia la dirección indicada. | |
-- Un ejemplo de aplicación de la función sería: | |
type Coordenada = (Float,Float) | |
data PuntoCardinal = Norte | Sur | Este | Oeste deriving Show | |
mover:: Coordenada -> PuntoCardinal -> Coordenada | |
mover (x,y) Norte = (x,y+1) | |
mover (x,y) Sur = (x,y-1) | |
mover (x,y) Este = (x+1,y) | |
mover (x,y) Oeste = (x-1,y) | |
-- Función que dados dos puntos de coordenadas | |
-- indique cuál está más al sur. | |
-- Ejemplos de aplicación de la función son: | |
masSur :: Coordenada -> Coordenada -> Coordenada | |
masSur (x1,y1) (x2,y2)= if(y1 > y2) then (x2,y2) else (x1,y1) | |
-- Función que calcule la distancia entre dos puntos | |
distancia :: Coordenada -> Coordenada -> Float | |
distancia (x1,y1) (x2,y2) = sqrt ((x2-x1)*(x2-x1) + (y2-y1)*(y2-y1)) | |
-- Función que dado un punto y una lista de direcciones, | |
-- retorne el camino que forman todos los puntos | |
-- después de cada movimiento sucesivo desde el punto original | |
camino :: Coordenada -> [PuntoCardinal] -> [Coordenada] | |
camino (x,y) l = foldl (\r dir -> if (r == []) then r ++ [mover (x,y) dir] else r ++ [mover (last r) dir]) [] l | |
-- Definir una función que dado un día de la semana, | |
-- indique si éste es o no laborable. | |
-- Para representar el día de la semana | |
-- se deberá crear un nuevo tipo enumerado. | |
data Dia = Lunes|Martes|Miercoles|Jueves|Viernes|Sabado|Domingo | |
es_laborable Sabado = False | |
es_laborable Domingo = False | |
es_laborable _ = True | |
-- La empresa RealTimeSolutions, Inc. | |
-- está trabajando en un controlador para una central domótica. | |
-- El controlador recibe información | |
-- de termostatos situados en diferentes | |
-- habitaciones de la vivienda | |
-- y basándose en esta información, | |
-- activa o desactiva el aire acondicionado | |
-- en cada una de las habitaciones. | |
-- Los termostatos pueden enviar la información | |
-- sobre la temperatura en grados Celsius o Fahrenheit. | |
-- A su vez, los aparatos de aire acondicionado | |
-- reciben dos tipos de órdenes: | |
-- apagar y encender (on y off). | |
-- Definir un tipo de datos para representar | |
-- las temperaturas en ambos tipos de unidades. | |
data Temperatura = Celsius Double | Fahrenheit Double deriving Show | |
data Estado = On|Off deriving Show | |
-- Definir una función convert | |
-- que dada una temperatura | |
-- en grados Celsius la convierta | |
-- a grados Fahrenheit y viceversa. | |
convertir :: Temperatura -> Double | |
convertir (Celsius temp) =(temp * (9/5) + 32) | |
convertir (Fahrenheit temp) =((temp-32) * 5/9) | |
-- Definir un tipo de datos | |
-- para representar las órdenes a los aparatos de a/a | |
controlar :: Temperatura -> Estado | |
controlar (Celsius temp) = if(temp<28) then On else Off | |
controlar (Fahrenheit temp) = controlar (Celsius (convertir (Fahrenheit temp))) | |
-- Definir un tipo moneda para representar euros y dólares USA. | |
-- Definir una función que convierte entre ambas monedas | |
-- sabiendo que el factor de conversión de euros a dólares es 1.14. | |
data Moneda = Euro | Dolar | |
convertir_moneda :: Moneda -> Double -> Double | |
convertir_moneda Euro n = n * 1.14 | |
convertir_moneda Dolar n = n / 1.14 | |
-- Dada el siguiente tipo de datos recursivo | |
-- que representa expresiones aritméticas | |
data Expr = Valor Integer | |
|Expr :+: Expr | |
|Expr :-: Expr | |
|Expr :*: Expr | |
evaluar :: Expr -> Integer | |
evaluar (Valor n) = n | |
evaluar (e1 :+: e2) = evaluar(e1) + evaluar(e2) | |
evaluar (e1 :-: e2) = evaluar(e1) - evaluar(e2) | |
evaluar (e1 :*: e2) = evaluar(e1) * evaluar(e2) | |
-- Se pide una función para calcular | |
-- el número de constantes de una expresión | |
contar :: Expr -> Integer | |
contar (Valor n) = 1 | |
contar (e1 :+: e2) = contar(e1) + contar(e2) | |
contar (e1 :-: e2) = contar(e1) + contar(e2) | |
contar (e1 :*: e2) = contar(e1) + contar(e2) | |
------------Parte 2-------------------------------------- | |
-- Se quiere ordenar los elementos de una lista | |
-- (cuyos elementos son comparables) | |
-- mediante el algoritmo del quicksort. | |
quicksort :: (Ord a) => [a] -> [a] | |
quicksort [] = [] | |
quicksort (x:xs) = (quicksort [y | y <- xs, y < x]) ++ x:(quicksort [y | y <- xs, y > x]) | |
-- Se pide implementar una función que dada un número | |
-- (de cualquier tipo que soporte la operación de división) | |
-- y una lista de números del mismo tipo, | |
-- divida a ese número por cada uno de los elementos | |
-- contenidos en la lista y devuelva una lista con el resultado. | |
-- Ejemplos de aplicación de la función son: | |
divide :: (Fractional a) => a -> [a] -> [a] | |
divide n l = [x / n | x <- l] | |
-- Dado un nuevo tipo de datos | |
-- para representar un árbol binario de cualquier tipo | |
data Arbol a = AV | Rama (Arbol a) a (Arbol a) | |
instance (Show a) => Show (Arbol a) where | |
show AV = "*" | |
show (Rama l r d) = "(" ++ show l ++ "-|" ++ show r ++ "|-"++ show d ++ ")" | |
-- Se pide definir una función que calcule el espejo de un árbol. | |
espejo :: Arbol a -> Arbol a | |
espejo AV = AV | |
espejo (Rama l r d) = Rama (espejo d) r (espejo l) | |
-- Se quiere poder mostrar por pantalla | |
-- los datos de los estudiantes matriculados en una | |
-- universidad que pertenezcan a alguna | |
-- de las asociaciones de ésta | |
-- (culturales, deportivas, de representación estudiantil, etc.). | |
-- Para ello se deberán | |
-- crear nuevos tipos de datos que representen | |
data Titulacion = Grado_II | Grado_II_ADE | Grado_ADE deriving Show | |
type Nombre = String | |
data Estudiante = Est Nombre Titulacion deriving Show | |
data Asociation = Culturales | Deportivas | Representante deriving Show | |
type Estudiante_Matriculados = [Estudiante] | |
type Est_ASO = [(Estudiante, Asociation)] | |
instance Eq Estudiante where | |
(Est n1 t1) == (Est n2 t2) = n1 == n2 | |
in_aso :: Estudiante -> [Estudiante] -> Bool | |
in_aso _ [] = False | |
in_aso e (x:xs) = if e == x then True else in_aso e xs | |
estidiantes_in_aso :: Est_ASO -> [Estudiante] | |
estidiantes_in_aso a = map (\(x,y) -> x) a | |
mostrar :: (Estudiante_Matriculados, Est_ASO) -> [Estudiante] | |
mostrar (m,a) = [e | e <- m, in_aso e (estidiantes_in_aso a)] | |
-- Se quiere poder representar una fecha de la siguiente forma: | |
-- dd/mm/aaaa, para ello se deberá | |
-- crear un nuevo tipo de datos en Haskell. | |
-- Por ejemplo, si se crea un nuevo tipo de datos | |
-- cuyo constructor de datos es Fecha, | |
-- en el intérprete al poner fechas concretas nos | |
-- devolvería la representación de la fecha | |
-- que hayamos definido | |
data Fecha = F Int Int Int | |
instance Show Fecha where | |
show (F day month year) = show day ++ "/" ++ show month ++ "/" ++ show year | |
-- Teniendo en cuenta el nuevo tipo de datos Fecha | |
-- definido anteriormente, | |
-- se pide una función que sea capaz de comparar dos fechas. | |
-- Ejemplos de aplicación de la función serían: | |
instance Eq Fecha where | |
(F d1 m1 y1) == (F d2 m2 y2) = (d1 == d2) && (m1 == m2) && (y1 == y2) | |
-- Teniendo en cuenta la definición de la función qs | |
-- del apartado (b) de este listado de ejercicios, | |
-- se pide ordenar una lista de fechas mediante quicksort. | |
instance Ord Fecha where | |
compare (F d1 m1 y1) (F d2 m2 y2) = if ((compare y1 y2) == EQ) then (if ((compare m1 m2) == EQ) then compare d1 d2 else compare m1 m2) else compare y1 y2 | |
-- Se pide crear una nueva clase de tipos, | |
-- llamada Coleccion, para representar colecciones | |
-- de datos de cualquier tipo, | |
-- donde los tipos pertenecientes a esta clase | |
-- tendrán el siguiente comportamiento | |
class Collection c where | |
-- función para saber si la colección está vacía | |
esVacia :: c -> Bool | |
-- insertará un nuevo elemento en la colección. | |
insertar :: a -> c -> c | |
-- devolverá el primer elemento de la colección. | |
primero :: c -> a | |
-- eliminará un elemento de la colección. | |
eliminar :: c -> c | |
-- devolverá el número de elementos de la colección. | |
size :: c -> Int | |
data Pila a = Pil [a] deriving Show | |
data Cola a = Col [a] deriving Show | |
-- instance Collection (Pila a) where | |
-- esVacia (Pil l) = (length l == 0) | |
-- insertar e (Pil l) = Pil (e:l) | |
-- dos recursivadad pura y dura | |
calcular :: [Int] -> [Int] | |
calcular [] = [] | |
calcular [_] = [] | |
calcular (x:y:zs) = (x+y):(calcular (y:zs)) | |
triangulo :: Int -> [Int] | |
triangulo 0 = [1] | |
triangulo 1 = [1, 1] | |
triangulo 2 = [1, 2 ,1] | |
triangulo n = 1:(calcular(triangulo (n-1))) ++ [1] | |
-- la primera | |
esta_en_resultado :: (Eq a) => a -> [(a,Int)] -> Bool | |
esta_en_resultado _ [] = False | |
esta_en_resultado e ((x,idx):es) = if (e == x) then True else esta_en_resultado e es | |
primeraAparicion :: (Eq a) => [a] -> [(a,Int)] | |
primeraAparicion l = foldl (\resultado (e,idx) -> if (esta_en_resultado e resultado) then resultado else resultado ++ [(e,idx)]) [] (zip l [1..]) | |
-- tipo de datos | |
data Monomio = M (Int, Int) | |
data Polinomio = P [Monomio] | |
-- a) (0.5 puntos) Instanciar a la clase Show ambos tipos | |
instance Show Monomio where | |
show (M (a, b)) = (show a) ++ "*x^" ++ (show b) | |
instance Show Polinomio where | |
show (P (m:ms)) = show m ++ (if ms == [] then "" else "+" ++ show (P ms)) | |
-- b) (0.75 puntos) Instanciar a la clase Eq ambos tipos. | |
-- Dos monomios serán iguales cuando sean iguales sus coeficientes | |
-- y sus exponentes. | |
-- Dos polinomios serán iguales cuando tengan los mismos monomios. | |
instance Eq Monomio where | |
(M (a1,b1)) == (M (a2,b2)) = (a1 == a2 && b1 == b2) | |
instance Eq Polinomio where | |
(P []) == (P []) = True | |
(P []) == (P _) = False | |
(P _) == (P []) = False | |
(P (m1:ms1)) == (P (m2:ms2)) = (m1 == m2) && (ms1 == ms2) | |
-- c) (1 punto) Instanciar a la clase Ord ambos tipos. | |
-- Un monomio es mayor que otro cuando tiene mayor exponente | |
-- o bien cuando a igualdad de exponente, | |
-- uno tiene un coeficiente mayor que el otro. | |
-- Un polinomio será mayor que otro cuando su monomio | |
-- de mayor grado sea mayor que el monomio de mayor grado del otro. | |
-- En caso de igualdad, se compararían los siguientes monomios | |
instance Ord Monomio where | |
compare (M (a1,b1)) (M (a2,b2)) = if cmp_b == EQ then compare a1 a2 else cmp_b where cmp_b = compare b1 b2 | |
instance Ord Polinomio where | |
compare (P []) (P []) = EQ | |
compare (P []) (P _) = LT | |
compare (P _) (P []) = GT | |
compare (P (m1:ms1)) (P (m2:ms2)) = if cmp_m == EQ then compare ms1 ms2 else cmp_m where cmp_m = compare m1 m2 | |
-- d) (0.75 puntos) Implementar la función evaluaPolinomio, | |
-- que recibirá un valor entero y un polinomio | |
-- y nos devolverá su resultado | |
evaluaPolinomio :: Int -> Polinomio -> Int | |
evaluaPolinomio x (P []) = 0 | |
evaluaPolinomio x (P (M (a,b):ps)) = (a * (x^b)) + (evaluaPolinomio x (P ps)) | |
-- e) (1 punto) Implementar la función insertaMonomio, | |
-- que recibirá un monomio y un polinomio | |
-- y lo insertará en el mismo. | |
concat_p :: Monomio -> Polinomio -> Polinomio | |
concat_p m (P l) = P (m:l) | |
insertaMonomio :: Monomio -> Polinomio -> Polinomio | |
insertaMonomio m (P []) = P [m] | |
insertaMonomio m (P (x:xs)) = if m > x then (P (m:x:xs)) else concat_p x (insertaMonomio m (P xs)) | |
-- f) (1 punto) Implementar la función eliminaMonomio, | |
-- que recibirá un número entero | |
-- (representativo del exponente de un monomio) | |
-- y un polinomio y eliminará el monomio con dicho exponente | |
-- (en el caso de que estuviese). | |
eliminaMonomio :: Int -> Polinomio -> Polinomio | |
eliminaMonomio n (P []) = (P []) | |
eliminaMonomio n (P ((M (a,b)):ms)) | |
| n == b = P ms | |
| n > b = P ((M (a,b)):ms) | |
| otherwise = concat_p (M (a,b)) (eliminaMonomio n (P ms)) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment