-- I1M 2009-10: G1_Rel_8_sol.hs
-- 8ª relación de ejercicios (20 de Noviembre)
-- Departamento de Ciencias de la Computación e I.A.
-- Universidad de Sevilla
-- =====================================================================

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

import Data.Char
import Data.List
import Test.QuickCheck

-- ---------------------------------------------------------------------
-- Ejercicio 1. Definir, por comprensión, la función
--    cuadradosC :: [Integer] -> [Integer]
-- tal que (cuadradosC xs) es la lista de los cuadrados de xs. Por
-- ejemplo, 
--    cuadradosC [1,2,3]  ==>  [1,4,9]
-- ---------------------------------------------------------------------

cuadradosC :: [Integer] -> [Integer]
cuadradosC xs = undefined

-- ---------------------------------------------------------------------
-- Ejercicio 2. Definir, por recursión, la función
--    cuadradosR :: [Integer] -> [Integer]
-- tal que (cuadradosR xs) es la lista de los cuadrados de xs. Por
-- ejemplo, 
--    cuadradosR [1,2,3]  ==>  [1,4,9]
-- ---------------------------------------------------------------------

cuadradosR :: [Integer] -> [Integer]
cuadradosR = undefined

-- ---------------------------------------------------------------------
-- Ejercicio 3. Escribir el cálculo de (cuadradosR [1,3,3]).
-- ---------------------------------------------------------------------

-- El cálculo es:

-- ---------------------------------------------------------------------
-- Ejercicio 4. Definir, por comprensión, la función
--    imparesC :: [Integer] -> [Integer]
-- tal que (imparesC xs) es la lista de los números impares de xs. Por
-- ejemplo, 
--    imparesC [1,2,3]  ==>  [1,3]
-- ---------------------------------------------------------------------

imparesC :: [Integer] -> [Integer]
imparesC xs = undefined

-- ---------------------------------------------------------------------
-- Ejercicio 5. Definir, por recursión, la función
--    imparesR :: [Integer] -> [Integer]
-- tal que (imparesR xs) es la lista de los números impares de xs. Por
-- ejemplo, 
--    imparesR [1,2,3]  ==>  [1,3]
-- ---------------------------------------------------------------------

imparesR :: [Integer] -> [Integer]
imparesR = undefined

-- ---------------------------------------------------------------------
-- Ejercicio 6. Escribir el cálculo de (imparesR [1,3,3]).
-- ---------------------------------------------------------------------

-- El cálculo es

-- ---------------------------------------------------------------------
-- Ejercicio 7. Definir, por comprensión, la función
--    imparesCuadradosC :: [Integer] -> [Integer]
-- tal que (imparesCuadradosC xs) es la lista de los cuadrados de los
-- números impares de xs. Por ejemplo, 
--    imparesCudradosC [1,2,3]  ==>  [1,9]
-- ---------------------------------------------------------------------

imparesCuadradosC :: [Integer] -> [Integer]
imparesCuadradosC xs = undefined

-- ---------------------------------------------------------------------
-- Ejercicio 8. Definir, por recursión, la función
--    imparesCuadradosR :: [Integer] -> [Integer]
-- tal que (imparesCuadradosR xs) es la lista de los cuadrados de los
-- números impares de xs. Por ejemplo, 
--    imparesCudradosR [1,2,3]  ==>  [1,9]
-- ---------------------------------------------------------------------

imparesCuadradosR :: [Integer] -> [Integer]
imparesCuadradosR = undefined

-- ---------------------------------------------------------------------
-- Ejercicio 9. Escribir el cálculo de (imparesCuadradosR [1,3,3]).
-- ---------------------------------------------------------------------

-- El cálculo es

-- ---------------------------------------------------------------------
-- Ejercicio 10. Definir, por comprensión, la función
--    sumaCuadradosImparesC :: [Integer] -> Integer
-- tal que (sumaCuadradosImparesC xs) es la suma de los cuadrados de los
-- números impares de la lista xs. Por ejemplo,
--    sumaCuadradosImparesC [1,2,3]  ==>  10
-- ---------------------------------------------------------------------

sumaCuadradosImparesC :: [Integer] -> Integer
sumaCuadradosImparesC xs = undefined

-- ---------------------------------------------------------------------
-- Ejercicio 11. Definir, por recursión, la función
--    sumaCuadradosImparesR :: [Integer] -> Integer
-- tal que (sumaCuadradosImparesR xs) es la suma de los cuadrados de los
-- números impares de la lista xs. Por ejemplo,
--    sumaCuadradosImparesR [1,2,3]  ==>  10
-- ---------------------------------------------------------------------

sumaCuadradosImparesR :: [Integer] -> Integer
sumaCuadradosImparesR = undefined

-- ---------------------------------------------------------------------
-- Ejercicio 12. Definir, usando funciones predefinidas, la función
--    entreL :: Integer -> Integer -> [Integer]
-- tal que (entreL m n) es la lista de los números entre m y n. Por
-- ejemplo, 
--    entreL 2 5  ==>  [2,3,4,5]
-- ---------------------------------------------------------------------

entreL :: Integer -> Integer -> [Integer]
entreL m n = undefined

-- ---------------------------------------------------------------------
-- Ejercicio 13. Definir, por recursión, la función
--    entreR :: Integer -> Integer -> [Integer]
-- tal que (entreR m n) es la lista de los números entre m y n. Por
-- ejemplo, 
--    entreR 2 5  ==>  [2,3,4,5]
-- ---------------------------------------------------------------------

entreR :: Integer -> Integer -> [Integer]
entreR m n = undefined

-- ---------------------------------------------------------------------
-- Ejercicio 14. Definir, por comprensión, la función
--    mitadPares :: [Int] -> [Int]
-- tal que (mitadPares xs) es la lista de las mitades de los elementos
-- de xs que son pares. Por ejemplo,
--    mitadPares [0,2,1,7,8,56,17,18]  ==>  [0,1,4,28,9]
-- ---------------------------------------------------------------------

mitadPares :: [Int] -> [Int]
mitadPares xs = undefined

-- ---------------------------------------------------------------------
-- Ejercicio 15. Definir, por recursión, la función
--    mitadParesRec :: [Int] -> [Int]
-- tal que (mitadParesRec []) es la lista de las mitades de los elementos
-- de xs que son pares. Por ejemplo,
--    mitadParesRec [0,2,1,7,8,56,17,18]  ==>  [0,1,4,28,9]
-- ---------------------------------------------------------------------

mitadParesRec :: [Int] -> [Int]
mitadParesRec = undefined

-- ---------------------------------------------------------------------
-- Ejercicio 16. Comprobar con QuickCheck que ambas definiciones son
-- equivalentes. 
-- ---------------------------------------------------------------------

-- La propiedad es
prop_mitadPares :: [Int] -> Bool
prop_mitadPares xs = undefined

-- La comprobación es

-- ---------------------------------------------------------------------
-- Ejercicio 17. Definir, por comprensión, la función
--    enRango :: Int -> Int -> [Int] -> [Int]
-- tal que (enRango a b xs) es la lista de los elementos de xs menores o
-- iguales que a y menores o iguales que b. Por ejemplo,
--    enRango 5 10 [1..15]  ==>  [5,6,7,8,9,10]
-- ---------------------------------------------------------------------

enRango :: Int -> Int -> [Int] -> [Int]
enRango a b xs = undefined

-- ---------------------------------------------------------------------
-- Ejercicio 18. Definir, por recursión, la función
--    enRangoRec :: Int -> Int -> [Int] -> [Int]
-- tal que (enRangoRec a b []) es la lista de los elementos de xs menores o
-- iguales que a y menores o iguales que b. Por ejemplo,
--    enRangoRec 5 10 [1..15]  ==>  [5,6,7,8,9,10]
-- ---------------------------------------------------------------------

enRangoRec :: Int -> Int -> [Int] -> [Int]
enRangoRec = undefined

-- ---------------------------------------------------------------------
-- Ejercicio 19. Comprobar con QuickCheck que ambas definiciones son
-- equivalentes. 
-- ---------------------------------------------------------------------

-- La propiedad es
prop_enRango :: Int -> Int -> [Int] -> Bool
prop_enRango a b xs = undefined

-- La comprobación es

-- ---------------------------------------------------------------------
-- Ejercicio 20. Definir, por comprensión, la función
--    sumaPositivos :: [Int] -> Int
-- tal que (sumaPositivos xs) es la suma de los números positivos de
-- xs. Por ejemplo, 
--    sumaPositivos [0,1,-3,-2,8,-1,6]  ==>  15
-- ---------------------------------------------------------------------

sumaPositivos :: [Int] -> Int
sumaPositivos xs = undefined

-- ---------------------------------------------------------------------
-- Ejercicio 21. Definir, por recursión, la función
--    sumaPositivosRec :: [Int] -> Int
-- tal que (sumaPositivosRec xs) es la suma de los números positivos de
-- xs. Por ejemplo, 
--    sumaPositivosRec [0,1,-3,-2,8,-1,6]  ==>  15
-- ---------------------------------------------------------------------

sumaPositivosRec :: [Int] -> Int
sumaPositivosRec = undefined

-- ---------------------------------------------------------------------
-- Ejercicio 22. Comprobar con QuickCheck que ambas definiciones son
-- equivalentes. 
-- ---------------------------------------------------------------------

-- La propiedad es
prop_sumaPositivos :: [Int] -> Bool
prop_sumaPositivos xs = undefined

-- La comprobación es

-- ---------------------------------------------------------------------
-- Ejercicio 23. Una persona es tan agarrada que sólo compra cuando le
-- hacen un descuento del 10% y el precio (con el descuento) es menor o
-- igual que 199. Definir, usando comprensión, la función
--    agarrado :: [Float] -> Float
-- tal que (agarrado ps) es el precio que tiene que pagar por una compra
-- cuya lista de precios es ps. Por ejemplo,
--    agarrado  [45.00, 199.00, 220.00, 399.00]  ==>  417.59998
-- ---------------------------------------------------------------------

agarrado :: [Float] -> Float
agarrado ps = undefined

-- ---------------------------------------------------------------------
-- Ejercicio 24. Una persona es tan agarrada que sólo compra cuando le
-- hacen un descuento del 10% y el precio (con el descuento) es menor o
-- igual que 199. Definir, por recursión, la función
--    agarradoRec :: [Float] -> Float
-- tal que (agarradoRec ps) es el precio que tiene que pagar por una compra
-- cuya lista de precios es ps. Por ejemplo,
--    agarradoRec  [45.00, 199.00, 220.00, 399.00]  ==>  417.59998
-- ---------------------------------------------------------------------

agarradoRec :: [Float] -> Float
agarradoRec = undefined

-- ---------------------------------------------------------------------
-- Ejercicio 25. Comprobar con QuickCheck que ambas definiciones son
-- similares; es decir, el valor absoluto de su diferencia es menor que
-- una diezmilésima. 
-- ---------------------------------------------------------------------

-- La propiedad es
prop_agarrado :: [Integer] -> Bool
prop_agarrado xs = undefined

-- La comprobación es

-- ---------------------------------------------------------------------
-- Ejercicio 26. Definir, por comprensión, la función
--    sumaDigitos :: String -> Int
-- tal que (sumaDigitos xs) es la suma de los dígitos de la cadena
-- xs. Por ejemplo, 
--    sumaDigitos "SE 2431 X"  ==>  10
-- Nota: Usar la función isDigit.
-- ---------------------------------------------------------------------

sumaDigitos :: String -> Int
sumaDigitos xs = undefined

-- ---------------------------------------------------------------------
-- Ejercicio 27. Definir, por recursión, la función
--    sumaDigitosRec :: String -> Int
-- tal que (sumaDigitosRec xs) es la suma de los dígitos de la cadena
-- xs. Por ejemplo, 
--    sumaDigitosRec "SE 2431 X"  ==>  10
-- ---------------------------------------------------------------------

sumaDigitosRec :: String -> Int
sumaDigitosRec = undefined

-- ---------------------------------------------------------------------
-- Ejercicio 28. Comprobar con QuickCheck que ambas definiciones son
-- equivalentes. 
-- ---------------------------------------------------------------------

-- La propiedad es
prop_sumaDigitos :: String -> Bool
prop_sumaDigitos xs = undefined

-- La comprobación es

-- ---------------------------------------------------------------------
-- Ejercicio 29. Definir, por comprensión, la función
--    mayusculaInicial :: String -> String
-- tal que (mayusculaInicial xs) es la palabra xs con la letra inicial
-- en mayúscula y las restantes en minúsculas. Por ejemplo, 
--    mayusculaInicial "sEviLLa"  ==>  "Sevilla"
-- Nota: Usar las funciones toLower y toUpper.
-- ---------------------------------------------------------------------

mayusculaInicial :: String -> String
mayusculaInicial = undefined

-- ---------------------------------------------------------------------
-- Ejercicio 30. Definir, por recursión, la función
--    mayusculaInicialRec :: String -> String
-- tal que (mayusculaInicialRec xs) es la palabra xs con la letra
-- inicial en mayúscula y las restantes en minúsculas. Por ejemplo,
--    mayusculaInicialRec "sEviLLa"  ==>  "Sevilla"
-- ---------------------------------------------------------------------

mayusculaInicialRec :: String -> String
mayusculaInicialRec = undefined

-- ---------------------------------------------------------------------
-- Ejercicio 31. Comprobar con QuickCheck que ambas definiciones son
-- equivalentes. 
-- ---------------------------------------------------------------------

-- La propiedad es
prop_mayusculaInicial :: String -> Bool
prop_mayusculaInicial xs = undefined

-- La comprobación es

-- ---------------------------------------------------------------------
-- Ejercicio 32. Se consideran las siguientes reglas de mayúsculas
-- iniciales para los títulos: 
--    * la primera palabra comienza en mayúscula y
--    * todas las palabras que tienen 4 letras como mínimo empiezan
--      con mayúsculas
-- Definir, por comprensión, la función
--    titulo :: [String] -> [String]
-- tal que (titulo ps) es la lista de las palabras de ps con
-- las reglas de mayúsculas iniciales de los títulos. Por ejemplo,
--    *Main> titulo ["eL","arTE","DE","La","proGraMacion"]
--    ["El","Arte","de","la","Programacion"]
-- ---------------------------------------------------------------------

titulo :: [String] -> [String]
titulo = undefined

-- (transforma p) es la palabra p con mayúscula inicial si su longitud
-- es mayor o igual que 4 y es p en minúscula en caso contrario
transforma :: String -> String
transforma = undefined

-- (minuscula xs) es la palabra xs en minúscula.
minuscula :: String -> String
minuscula xs = undefined

-- ---------------------------------------------------------------------
-- Ejercicio 33. Definir, por recursión, la función
--    tituloRec :: [String] -> [String]
-- tal que (tituloRec ps) es la lista de las palabras de ps con
-- las reglas de mayúsculas iniciales de los títulos. Por ejemplo,
--    *Main> tituloRec ["eL","arTE","DE","La","proGraMacion"]
--    ["El","Arte","de","la","Programacion"]
-- ---------------------------------------------------------------------

tituloRec :: [String] -> [String]
tituloRec = undefined

-- ---------------------------------------------------------------------
-- Ejercicio 34. Comprobar con QuickCheck que ambas definiciones son
-- equivalentes. 
-- ---------------------------------------------------------------------

-- La propiedad es
prop_titulo :: [String] -> Bool
prop_titulo xs = undefined

-- La comprobación es

-- ---------------------------------------------------------------------
-- Ejercicio 35. Definir, por comprensión, la función
--    buscaCrucigrama :: Char -> Int -> Int -> [String] -> [String]
-- tal que (buscaCrucigrama l pos lon ps) es la lista de las palabras de
-- la lista de palabras ps que tienen longitud lon y poseen la letra l
-- en la posición pos (comenzando en 0). Por ejemplo,
--    *Main> buscaCrucigrama 'c' 1 7 ["ocaso", "casa", "ocupado"]
--    ["ocupado"]
-- ---------------------------------------------------------------------

buscaCrucigrama :: Char -> Int -> Int -> [String] -> [String]
buscaCrucigrama l pos lon ps = undefined

-- ---------------------------------------------------------------------
-- Ejercicio 36. Definir, por comprensión, la función
--    buscaCrucigramaRec :: Char -> Int -> Int -> [String] -> [String]
-- tal que (buscaCrucigramaRec l pos lon ps) es la lista de las palabras
-- de la lista de palabras ps que tienn longitud lon y posen la letra l
-- en la posición pos (comenzando en 0). Por ejemplo,
--    *Main> buscaCrucigramaRec 'c' 1 7 ["ocaso", "casa", "ocupado"]
--    ["ocupado"]
-- ---------------------------------------------------------------------

buscaCrucigramaRec :: Char -> Int -> Int -> [String] -> [String]
buscaCrucigramaRec = undefined

-- ---------------------------------------------------------------------
-- Ejercicio 37. Comprobar con QuickCheck que ambas definiciones son
-- equivalentes. 
-- ---------------------------------------------------------------------

-- La propiedad es
prop_buscaCrucigrama :: Char -> Int -> Int -> [String] -> Bool
prop_buscaCrucigrama letra pos lon ps = undefined

-- La comprobación es

-- ---------------------------------------------------------------------
-- Ejercicio 38. Definir, por comprensión, la función
--    posiciones :: String -> Char -> [Int]
-- tal que (posiciones xs y) es la lista de la posiciones del carácter y
-- en la cadena xs. Por ejemplo,
--    posiciones "Salamamca" 'a'  ==>  [1,3,5,8]
-- ---------------------------------------------------------------------

posiciones :: String -> Char -> [Int]
posiciones xs y = undefined

-- ---------------------------------------------------------------------
-- Ejercicio 39. Definir, por recursión, la función
--    posicionesRec :: String -> Char -> [Int]
-- tal que (posicionesRec xs y) es la lista de la posiciones del
-- carácter y en la cadena xs. Por ejemplo,
--    posicionesRec "Salamamca" 'a'  ==>  [1,3,5,8]
-- ---------------------------------------------------------------------

posicionesRec :: String -> Char -> [Int]
posicionesRec xs y = undefined

-- ---------------------------------------------------------------------
-- Ejercicio 40. Comprobar con QuickCheck que ambas definiciones son
-- equivalentes. 
-- ---------------------------------------------------------------------

-- La propiedad es
prop_posiciones :: String -> Char -> Bool
prop_posiciones xs y = undefined

-- La comprobación es

-- ---------------------------------------------------------------------
-- Ejercicio 41. Definir, por recursión, la función
--    contieneRec :: String -> String -> Bool
-- tal que (contieneRec xs ys) se verifica si ys es una subcadena de
-- xs. Por ejemplo, 
--    contieneRec "escasamente" "casa"   ==>  True
--    contieneRec "escasamente" "cante"  ==>  False
--    contieneRec "" ""                  ==>  True
-- Nota: Se puede usar la predefinida (isPrefixOf ys xs) que se verifica
-- si ys es un prefijo de xs.
-- ---------------------------------------------------------------------

contieneRec :: String -> String -> Bool
contieneRec = undefined

-- ---------------------------------------------------------------------
-- Ejercicio 42. Definir, por comprensión, la función
--    contiene :: String -> String -> Bool
-- tal que (contiene xs ys) se verifica si ys es una subcadena de
-- xs. Por ejemplo, 
--    contiene "escasamente" "casa"   ==>  True
--    contiene "escasamente" "cante"  ==>  False
--    contiene "" ""                  ==>  True
-- Nota: Se puede usar la predefinida (isPrefixOf ys xs) que se verifica
-- si ys es un prefijo de xs.
-- ---------------------------------------------------------------------

contiene :: String -> String -> Bool
contiene xs ys = undefined

-- (sufijosComenzandoCon xs ys) es la lista de los sufijos de xs que
-- comienzan con ys. Por ejemplo,
--    sufijosComenzandoCon "abacbad" "ba"  ==>  ["bacbad","bad"]
sufijosComenzandoCon :: String -> String -> [String]
sufijosComenzandoCon xs ys = undefined

-- (sufijos xs) es la lista de sufijos de xs. Por ejemplo,
--    sufijos "abc"  ==>  ["abc","bc","c",""]
sufijos :: String -> [String]
sufijos xs = undefined

-- ---------------------------------------------------------------------
-- Ejercicio 43. Comprobar con QuickCheck que ambas definiciones son
-- equivalentes. 
-- ---------------------------------------------------------------------

-- La propiedad es
prop_contiene :: String -> String -> Bool
prop_contiene xs ys = undefined

-- La comprobación es
