-- I1M 2009-10: G1_Rel_2.hs
-- 2ª relación de ejercicios (19 de Octubre)
-- Departamento de Ciencias de la Computación e I.A.
-- Universidad de Sevilla
-- =====================================================================

-- ---------------------------------------------------------------------
-- Importación de librerías auxiliares                                --
-- ---------------------------------------------------------------------

import Test.QuickCheck

-- ---------------------------------------------------------------------
-- Ejercicio 1. Escribir los paréntesis correspondientes a las
-- siguientes expresiones:  
--    * 2^3+4
--    * 2*3+4*5
--    * 2+3*4^5
-- ---------------------------------------------------------------------

-- ---------------------------------------------------------------------
-- Ejercicio 2. La siguiente definición contiene 4 errores sintácticos. 
-- Corregir los errores y comprobar que la definición es correcta
-- calculando con Haskell el valor de n. 
--    n = A ´div´ length xs
--          where
--              A = 10
--             xs = [1, 2, 3, 4, 5]
-- --------------------------------------------------------------------- 

-- ---------------------------------------------------------------------
-- Ejercicio 3. Definir la función ultimo tal que (ultimo xs) es el
-- último elemento de la lista no vacía xs. Por ejemplo, 
--    ultimo [2,5,3]  ==>  3
-- Dar dos definiciones usando las funciones introducidas en el tema 2 y
-- comprobar su equivalencia con QuickCheck.
-- 
-- Nota: La función ultimo es la predefinida last.
-- ---------------------------------------------------------------------

-- ---------------------------------------------------------------------
-- Ejercicio 4. Definir la función iniciales tal que (iniciales xs) es
-- la lista obtenida eliminando el último elemento de la lista no vacía
-- xs. Por ejemplo, 
--    iniciales [2,5,3]  ==>  [2,5]
-- Dar dos definiciones usando las funciones introducidas en este tema y
-- comprobar su equivalencia usando QuickCheck.
--- 
-- Nota: La función iniciales es la predefinida init.
-- ---------------------------------------------------------------------

-- ---------------------------------------------------------------------
-- Ejercicio 5. Comprobar con QuickCheck que para toda lista no vacía
-- xs, la lista obtenida al añadirle a los iniciales de xs la lista
-- formada por el último elemento de xs es xs.
-- ---------------------------------------------------------------------

-- ---------------------------------------------------------------------
-- Ejercicio 6 (Transformación entre euros y pesetas)
-- ---------------------------------------------------------------------
-- Ejercicio 6.1. Calcular cuántas pesetas son 49 euros (1 euro son 
-- 166.386 pesetas). 
-- ---------------------------------------------------------------------
 
-- ---------------------------------------------------------------------
-- Ejercicio 6.2, Definir la constante cambioEuro cuyo valor es 166.386 
-- y repetir el cálculo anterior usando la constante definida. 
-- ---------------------------------------------------------------------
 
-- ---------------------------------------------------------------------
-- Ejercicio 6.3. Definir la función pesetas tal que (pesetas x) es la 
-- cantidad de pesetas correspondientes a x euros y repetir el cálculo 
-- anterior usando la función definida. 
-- ---------------------------------------------------------------------
 
-- ---------------------------------------------------------------------
-- Ejercicio 6.4. Definir la función euros tal que (euros x) es la
-- cantidad de euros correspondientes a x pesetas y calcular los euros
-- correspondientes a 8152.914 pesetas. 
-- ---------------------------------------------------------------------
 
-- ---------------------------------------------------------------------
-- Ejercicio 6.5. Definir la propiedad prop_EurosPesetas tal que
-- (prop_EurosPesetas x) se verifique si al transformar x euros en
-- pesetas y las pesetas obtenidas en euros se obtienen x
-- euros. Comprobar la prop_EurosPesetas con 49 euros. 
-- ---------------------------------------------------------------------
 
-- ---------------------------------------------------------------------
-- Ejercicio 6.6. Comprobar la prop_EurosPesetas con QuickCheck.
-- ---------------------------------------------------------------------
 
-- ---------------------------------------------------------------------
-- Ejercicio 6.7. Calcular la diferencia entre euros(pesetas 3.625) y
-- 3.625.    
-- ---------------------------------------------------------------------
 
-- ---------------------------------------------------------------------
-- Ejercicio 6.8. Definir el operador ~= tal que (x ~= y) se verifique
-- si el valor absoluto de la diferencia entre x e y es menor que una
-- milésima. Se dice que x e y son casi iguales. 
-- ---------------------------------------------------------------------
 
-- ---------------------------------------------------------------------
-- Ejercicio 6.9. Definir la propiedad prop_EurosPesetas' tal que
-- (prop_EurosPesetas' x) se verifique si al transformar x euros en
-- pesetas y las pesetas obtenidas en euros se obtiene una cantidad casi
-- igual a x de euros. Comprobar la prop_EurosPesetas' con 49 euros. 
-- ---------------------------------------------------------------------
 
-- ---------------------------------------------------------------------
-- Ejercicio 6.10. Comprobar la prop_EurosPesetas' con QuickCheck.
-- ---------------------------------------------------------------------
 
-- ---------------------------------------------------------------------
-- Ejercicio 7. Definir la función
--    mitades :: [a] -> ([a],[a])
-- tal que, dada una lista de longitud par, la divida en dos mitades,
-- devolviendo las dos listas correspondientes. Por ejemplo,
--    *Main> mitades [1,2,3,4,5,6]
--    ([1,2,3],[4,5,6])
-- Dar dos definiciones de mitades y comprobar con QuickCheck que son
-- equivalentes. 
-- ---------------------------------------------------------------------

-- ---------------------------------------------------------------------
-- Ejercicio 8. Definir la función
--    tailSeguro :: [a] -> [a] 
-- que se comporta como la función tail, excepto que tailSeguro aplica
-- la lista vacía en sí misma y tail devuelve error en ese caso. Dar
-- cuatro definiciones distintas utilizando
--    1. una expresión condicional
--    2. guardas
--    3. ecuaciones
--    4. patrones
-- Comprobar con QuickCheck que las definiciones son equivalentes.
-- 
-- Indicación: Usar la función null.
-- --------------------------------------------------------------------

-- ---------------------------------------------------------------------
-- Ejercicio 9. De manera similar al operador conjunción, demostrar cómo
-- usando emparejamiento de patrones el operador lógico disjunción puede
-- definirse de cuatro formas diferentes (disj_1, disj_2, disj_3 y
-- disj_4). Comprobar con QuickCheck que las definiciones son
-- equivalentes entre si y con el operador (||).
-- ---------------------------------------------------------------------

-- ---------------------------------------------------------------------
-- Ejercicio 10. Redefinir la función
--    mult x y z = x*y*z 
-- usando expresiones lambda y comprobar con QuickCheck que las
-- definiciones son equivalentes.
-- ---------------------------------------------------------------------

-- ---------------------------------------------------------------------
-- Ejercicio 11 (Máximo de enteros)
-- ---------------------------------------------------------------------
-- Ejercicio 11.1. Definir, por casos, la función maxI tal que maxI x y
-- es el máximo de los números enteros x e y. Por ejemplo, 
--    maxI 2 5 => 5 
--    maxI 7 5 => 7 
-- ---------------------------------------------------------------------

-- ---------------------------------------------------------------------
-- Ejercicio 11.2. En este apartado vamos a comprobar propiedades del
-- máximo.  
-- ---------------------------------------------------------------------
-- Ejercicio 11.2.1. Comprobar con QuickCheck que el máximo de x e y es
-- mayor o igual que x y que y.
-- ---------------------------------------------------------------------

-- ---------------------------------------------------------------------
-- Ejercicio 11.2.2. Comprobar con QuickCheck que el máximo de x e y es
-- x ó y. 
-- ---------------------------------------------------------------------

-- ---------------------------------------------------------------------
-- Ejercicio 11.2.3. Comprobar con QuickCheck que si x es mayor o igual
-- que y, entonces el máximo de x e y es x. 
-- ---------------------------------------------------------------------

-- ---------------------------------------------------------------------
-- Ejercicio 11.2.4. Comprobar con QuickCheck que si y es mayor o igual
-- que x, entonces el máximo de x e y es y.
-- ---------------------------------------------------------------------

-- ---------------------------------------------------------------------
-- Ejercicio 12 (Menor múltiplo mayor o igual que)
-- ---------------------------------------------------------------------
-- El objetivo de este ejercicio consiste en definir la función
-- menorMultiplo tal que (menorMultiplo n p) es el menor número mayor o
-- igual que n que es múltiplo de p. Por ejemplo, 
--    menorMultiplo 16 5   ==> 20 
--    menorMultiplo 167 25 ==> 175 
-- Para ello, partiremos de la siguiente propiedad
--    menorMultiplo n p = n + (p - (n resto p))
-- es decir, n más la diferencia entre p y el resto de la división entre
-- n y p. 
-- ---------------------------------------------------------------------
-- Ejercicio 12.1. Definir la función menorMultiplo.
-- ---------------------------------------------------------------------

-- ---------------------------------------------------------------------
-- Ejercicio 12.2. Calcular el resultado de menorMultiplo para los
-- ejemplos anteriores. 
-- ---------------------------------------------------------------------

-- ---------------------------------------------------------------------
-- Ejercicio 12.3. En este apartado vamos a estudiar propiedades de la
-- función menorMultiplo. 
-- ---------------------------------------------------------------------
-- Ejercicio 12.3.1. Comprobar con QuickCheck si (menorMultiplo n p) es
-- mayor o igual que n. 
-- ---------------------------------------------------------------------

-- ---------------------------------------------------------------------
-- Ejercicio 12.3.2. Comprobar con QuickCheck si (menorMultiplo n p) es
-- múltiplo de p. 
-- ---------------------------------------------------------------------

-- ---------------------------------------------------------------------
-- Ejercicio 12.3.3. Comprobar con QuickCheck si (menorMultiplo n n) es
-- igual a n. 
-- ---------------------------------------------------------------------

-- ---------------------------------------------------------------------
-- Ejercicio 12.4. Corregir los errores de la definición de
-- menorMultiplo escribiendo una nueva función menorMultiplo'. Definir
-- las correspondientes propiedades y comprobarlas. 
-- ---------------------------------------------------------------------

-- ---------------------------------------------------------------------
-- Ejercicio 12.5. Obtener una definición recursiva que se denomine
-- menorMultiplo'', definir las correspondientes propiedades y
-- comprobarlas.    
-- ---------------------------------------------------------------------

