-- I1M 2021-22: Rel_4.hs (27 de Octubre de 2021)
-- Definiciones por comprensión (II)
-- Departamento de Ciencias de la Computación e I.A.
-- Universidad de Sevilla
-- =====================================================================
-- ---------------------------------------------------------------------
-- Introducción --
-- ---------------------------------------------------------------------
--
-- En esta relación se presentan ejercicios con definiciones por
-- comprensión correspondientes al tema 5.
--
-- ---------------------------------------------------------------------
-- § Librerías auxiliares --
-- ---------------------------------------------------------------------
import Test.QuickCheck
-- ---------------------------------------------------------------------
-- Ejercicio 1. Definir la función
-- divisoresPrimos :: Int -> [Int]
-- tal que (divisoresPrimos x) es la lista de los divisores primos de x.
-- Por ejemplo,
-- divisoresPrimos 40 == [2,5]
-- divisoresPrimos 70 == [2,5,7]
-- ------------------------------------------------------------------------
divisoresPrimos :: Int -> [Int]
divisoresPrimos x = undefined
-- ---------------------------------------------------------------------
-- Ejercicio 2. Un número es libre de cuadrados si no es divisible por el
-- cuadrado de ningún entero mayor que 1. Por ejemplo, 70 es libre de
-- cuadrado porque sólo es divisible por 1, 2, 5, 7 y 70; en cambio, 40
-- no es libre de cuadrados porque es divisible por 2^2.
--
-- Definir la función
-- libreDeCuadrados :: Int -> Bool
-- tal que (libreDeCuadrados x) se verifica si x es libre de cuadrados.
-- Por ejemplo,
-- libreDeCuadrados 70 == True
-- libreDeCuadrados 40 == False
-- ---------------------------------------------------------------------
libreDeCuadrados :: Int -> Bool
libreDeCuadrados = undefined
-- ---------------------------------------------------------------------
-- Ejercicio 3. [Del problema 21 del Proyecto Euler]. Sea d(n) la suma
-- de los divisores propios de n. Si d(a) = b y d(b) = a, siendo a
-- distinto de b,
-- decimos que a y b son un par de números amigos. Por ejemplo, los
-- divisores propios de 220 son 1, 2, 4, 5, 10, 11, 20, 22, 44, 55 y
-- 110; por tanto, d(220) = 284. Los divisores propios de 284 son 1, 2,
-- 4, 71 y 142; por tanto, d(284) = 220. Luego, 220 y 284 son dos
-- números amigos.
--
-- Definir la función
-- amigos :: Int -> Int -> Bool
-- tal que (amigos a b) se verifica si a y b son números amigos. Por
-- ejemplo,
-- amigos 6 6 == False
-- amigos 220 248 == False
-- amigos 220 284 == True
-- amigos 100 200 == False
-- amigos 1184 1210 == True
-- ---------------------------------------------------------------------
amigos :: Int -> Int -> Bool
amigos a b = undefined
-- ---------------------------------------------------------------------
-- Ejercicio 4. (Problema 211 del proyecto Euler) Dado un entero
-- positivo n, consideremos la suma de los cuadrados de sus divisores,
-- Por ejemplo,
-- f(10) = 1 + 4 + 25 + 100 = 130
-- f(42) = 1 + 4 + 9 + 36 + 49 + 196 + 441 + 1764 = 2500
-- Decimos que n es especial si f(n) es un cuadrado perfecto. En los
-- ejemplos anteriores, 42 es especial y 10 no lo es.
--
-- Definir la función
-- especial:: Int -> Bool
-- tal que (especial x) se verifica si x es un número es especial. Por
-- ejemplo,
-- especial 42 == True
-- especial 10 == False
--
-- Calcular todos los números especiales de tres cifras.
-- El resultado es:
-- λ> calculo
-- [246,287,728]
-- ---------------------------------------------------------------------
especial :: Int -> Bool
especial = undefined
-- ---------------------------------------------------------------------
-- Ejercicio 5. La multiplicidad de x en y es la mayor potencia de x
-- que divide a y. Por ejemplo, la multiplicidad de 2 en 40 es 3 porque
-- 40 es divisible por 2^3 y no lo es por 2^4. Además, la multiplicidad
-- de 1 en cualquier número se supone igual a 1.
--
-- Definir la función
-- multiplicidad :: Integer -> Integer -> Integer
-- tal que (multiplicidad x y) es la
-- multiplicidad de x en y. Por ejemplo,
-- multiplicidad 2 40 == 3
-- multiplicidad 5 40 == 1
-- multiplicidad 3 40 == 0
-- multiplicidad 1 40 == 1
-- ---------------------------------------------------------------------
multiplicidad :: Integer -> Integer -> Integer
multiplicidad = undefined
-- -------------------------------------------------------------
-- Ejercicio 6.1. Sea t una lista de pares de la forma
-- (nombre, [(asig_1, nota_1),...,(asig_k, nota.k)])
-- Por ejemplo,
-- t1 = [("Ana",[("Alg",1),("Cal",3),("Inf",8),("Fis",2)]),
-- ("Juan",[("Alg",5),("Cal",1),("Inf",2),("Fis",9)]),
-- ("Alba",[("Alg",5),("Cal",6),("Inf",6),("Fis",5)]),
-- ("Pedro",[("Alg",9),("Cal",5),("Inf",3),("Fis",1)])]
-- Definir la función
-- calificaciones :: [(String,[(String,Int)])] -> String -> [(String,Int)]
-- tal que (calificaciones t p) es la lista de las calificaciones de la
-- persona p en la lista t. Por ejemplo,
-- ghci> calificaciones t1 "Pedro"
-- [("Alg",9),("Cal",5),("Inf",3),("Fis",1)]
-- ---------------------------------------------------------------------
t1 :: [(String,[(String,Int)])]
t1 = [("Ana",[("Alg",1),("Cal",3),("Inf",8),("Fis",2)]),
("Juan",[("Alg",5),("Cal",1),("Inf",2),("Fis",9)]),
("Alba",[("Alg",5),("Cal",6),("Inf",6),("Fis",5)]),
("Pedro",[("Alg",9),("Cal",5),("Inf",3),("Fis",1)])]
calificaciones :: [(String,[(String,Int)])] -> String -> [(String,Int)]
calificaciones t p = undefined
-- ---------------------------------------------------------------------
-- Ejercicio 6.2. Definir la función
-- todasAprobadas :: [(String,[(String,Int)])] -> String -> Bool
-- tal que (todasAprobadas t p) se cumple si en la lista t, p tiene
-- todas las asignaturas aprobadas. Por ejemplo,
-- todasAprobadas t1 "Alba" == True
-- todasAprobadas t1 "Pedro" == False
-- ---------------------------------------------------------------------
todasAprobadas :: [(String,[(String,Int)])] -> String -> Bool
todasAprobadas t p = undefined
-- ---------------------------------------------------------------------
-- Ejercicio 6.3. Definir la función
-- aprobados :: [(String,[(String,Int)])] -> [String]
-- tal que (aprobados t) es la lista de los alumnos de la lista de notas
-- t que han aprobado todas las asignaturas.Por ejemplo,
-- ghci> aprobados t1 == ["Alba"]
-- ---------------------------------------------------------------------
aprobados :: [(String,[(String,Int)])] -> [String]
aprobados t = undefined
-- ---------------------------------------------------------------------
-- Ejercicio 7. Un número n es de Angelini si n y 2n tienen algún
-- dígito común. Por ejemplo, 2014 es un número de Angelini ya que 2014
-- y su doble (4028) comparten los dígitos 4 y 0.
--
-- Definir la función
-- angelini :: Integer -> Bool
-- tal que (angelini n) se verifica si n es un número de Angelini. Por
-- ejemplo,
-- angelini 2014 == True
-- angelini 2067 == False
-- ---------------------------------------------------------------------
angelini :: Integer -> Bool
angelini n = undefined
-- ---------------------------------------------------------------------
-- Ejercicio 8.1. Definir la función
-- unitarios :: Int -> [Int]
-- tal (unitarios n) es la lista de números [n,nn, nnn, ....]. Por
-- ejemplo.
-- take 7 (unitarios 3) == [3,33,333,3333,33333,333333,3333333]
-- take 3 (unitarios 1) == [1,11,111]
-- ---------------------------------------------------------------------
unitarios :: Int -> [Int]
unitarios x = undefined
-- ---------------------------------------------------------------------
-- Ejercicio 8.2. Definir la función
-- multiplosUnitarios :: Int -> Int -> Int -> [Int]
-- tal que (multiplosUnitarios x y n) es la lista de los n primeros
-- múltiplos de x cuyo único dígito es y. Por ejemplo,
-- multiplosUnitarios 7 1 2 == [111111,111111111111]
-- multiplosUnitarios 11 3 5 == [33,3333,333333,33333333,3333333333]
-- ---------------------------------------------------------------------
multiplosUnitarios :: Int -> Int -> Int -> [Int]
multiplosUnitarios x y n = undefined
-- ---------------------------------------------------------------------
-- Ejercicio 9. Definir la función
-- masOcurrentes :: Eq a => [a] -> [a]
-- tal que (masOcurrentes xs) es la lista de los elementos de xs que
-- ocurren el máximo número de veces. Por ejemplo,
-- masOcurrentes [1,2,3,4,3,2,3,1,4] == [3,3,3]
-- masOcurrentes [1,2,3,4,5,2,3,1,4] == [1,2,3,4,2,3,1,4]
-- masOcurrentes "Salamanca" == "aaaa"
-- ---------------------------------------------------------------------
masOcurrentes :: Eq a => [a] -> [a]
masOcurrentes xs = undefined
-- ---------------------------------------------------------------------
-- Ejercicio 10. La suma de la serie
-- 1/1^2 + 1/2^2 + 1/3^2 + 1/4^2 + ...
-- es pi^2/6. Por tanto, pi se puede aproximar mediante la raíz cuadrada
-- de 6 por la suma de la serie.
--
-- Definir la función aproximaPi tal que (aproximaPi n) es la aproximación
-- de pi obtenida mediante n términos de la serie. Por ejemplo,
-- aproximaPi 4 == 2.9226129861250305
-- aproximaPi 1000 == 3.1406380562059946
-- ---------------------------------------------------------------------
aproximaPi n = undefined
-- ---------------------------------------------------------------------
-- Ejercicio 11. Una representación de 20 en base 2 es [0,0,1,0,1] pues
-- 20 = 1*2^2 + 1*2^4. Y una representación de 46 en base 3 es [1,0,2,1]
-- pues 46 = 1*3^0 + 0*3^1 + 2*3^2 + 1*3^3.
--
-- Definir la función
-- deBaseABase10 :: Int -> [Int] -> Int
-- tal que (deBaseABase10 b xs) es el número n tal que su representación
-- en base b es xs. Por ejemplo,
-- deBaseABase10 2 [0,0,1,0,1] == 20
-- deBaseABase10 2 [1,1,0,1] == 11
-- deBaseABase10 3 [1,0,2,1] == 46
-- deBaseABase10 5 [0,2,1,3,1,4,1] == 2916
-- ---------------------------------------------------------------------
deBaseABase10 :: Int -> [Int] -> Int
deBaseABase10 b xs = undefined
-- ---------------------------------------------------------------------
-- Ejercicio 12.1. Definir la función
-- conPos :: [a] -> [(a,Int)]
-- tal que (conPos xs) es la lista obtenida a partir de xs especificando
-- las posiciones de sus elementos. Por ejemplo,
-- conPos [1,5,0,7] == [(1,0),(5,1),(0,2),(7,3)]
-- ---------------------------------------------------------------------
conPos :: [a] -> [(a,Int)]
conPos xs = undefined
-- ---------------------------------------------------------------------
-- Ejercicio 12.2. Definir la
-- pares :: [a] -> [a]
-- tal que (pares cs) es la cadena formada por los caracteres en
-- posición par de cs. Por ejemplo,
-- pares "el cielo sobre berlin" == "e il or eln"
-- ---------------------------------------------------------------------
pares :: [a] -> [a]
pares cs = undefined
-- ---------------------------------------------------------------------
-- Ejercicio 13. Dos listas xs, ys de la misma longitud son
-- perpendiculares si el producto escalar de ambas es 0, donde el
-- producto escalar de dos listas de enteros xs e ys viene
-- dado por la suma de los productos de los elementos correspondientes.
--
-- Definir la función
-- perpendiculares :: (Num a, Eq a) => [a] -> [[a]] -> [[a]]
-- tal que (perpendiculares xs yss) es la lista de los elementos de yss
-- que son perpendiculares a xs. Por ejemplo,
-- ghci> perpendiculares [1,0,1] [[0,1,0], [2,3,1], [-1,7,1],[3,1,0]]
-- [[0,1,0],[-1,7,1]]
-- ---------------------------------------------------------------------
perpendiculares :: (Num a, Eq a) => [a] -> [[a]] -> [[a]]
perpendiculares xs yss = undefined
-- ---------------------------------------------------------------------
-- Ejercicio 14. Dada una lista de números enteros, definiremos el
-- mayor salto como el mayor valor de las diferencias (en valor
-- absoluto) entre números consecutivos de la lista. Por ejemplo, dada
-- la lista [2,5,-3] las distancias son
-- 3 (valor absoluto de la resta 2 - 5) y
-- 8 (valor absoluto de la resta de 5 y (-3))
-- Por tanto, su mayor salto es 8. No está definido el mayor salto para
-- listas con menos de 2 elementos
--
-- Definir la función
-- mayorSalto :: [Integer] -> Integer
-- tal que (mayorSalto xs) es el mayor salto de la lista xs. Por
-- ejemplo,
-- mayorSalto [1,5] == 4
-- mayorSalto [10,-10,1,4,20,-2] == 22
-- ---------------------------------------------------------------------
mayorSalto :: [Integer] -> Integer
mayorSalto xs = undefined
-- ---------------------------------------------------------------------
-- Ejercicio 15. Definir la función
-- longCamino :: [(Float,Float)] -> Float
-- tal que (longCamino xs) es la longitud del camino determinado por los
-- puntos del plano listados en xs. Por ejemplo,
-- longCamino [(0,0),(1,0),(2,1),(2,0)] == 3.4142137
-- ---------------------------------------------------------------------
longCamino :: [(Float,Float)] -> Float
longCamino xs = undefined
-- ---------------------------------------------------------------------
-- Ejercicio 16. Definir la función
-- numeroConsecutivos :: (Num a, Eq a) => [a] -> Int
-- tal que (numeroConsecutivosC xs) es la cantidad de números
-- consecutivos que aparecen al comienzo de la lista xs. Por ejemplo,
-- numeroConsecutivosC [1,3,5,7,9] == 1
-- numeroConsecutivosC [1,2,3,4,5,7,9] == 5
-- numeroConsecutivosC [] == 0
-- ---------------------------------------------------------------------
numeroConsecutivos :: (Num a, Eq a) => [a] -> Int
numeroConsecutivos = undefined
-- ---------------------------------------------------------------------
-- Ejercicio 17. Definir la función
-- sumaEquidistantes :: Num a => [a] -> [a]
-- tal que (sumaEquidistantes xs) es la lista sumando el primer elemento
-- de xs con el último, el segundo con el penúltimo y así
-- sucesivamente. Por ejemplo,
-- sumaEquidistantes [6,5,3,1] == [7,8]
-- sumaEquidistantes [6,5,3] == [9,10]
-- sumaEquidistantes [3,2,3,2] == [5,5]
-- sumaEquidistantes [6,5,3,1,2,0,4,7,8,9] == [15,13,10,5,2]
-- ---------------------------------------------------------------------
sumaEquidistantes :: Num a => [a] -> [a]
sumaEquidistantes xs = undefined
-- ---------------------------------------------------------------------
-- Ejercicio 18. La distancia entre dos números es el valor absoluto de
-- su diferencia. Por ejemplo, la distancia entre 2 y 5 es 3.
--
-- Definir la función
-- cercanos :: [Int] -> [Int] -> [(Int,Int)]
-- tal que (cercanos xs ys) es la lista de pares de elementos de xs e ys
-- cuya distancia es mínima. Por ejemplo,
-- cercanos [3,7,2,1] [5,11,9] == [(3,5),(7,5),(7,9)]
-- ---------------------------------------------------------------------
cercanos :: [Int] -> [Int] -> [(Int,Int)]
cercanos xs ys = undefined
-- ---------------------------------------------------------------------
-- Ejercicio 19. [De la IMO 1996]. Una sucesión [a(0),a(1),...,a(n)]
-- se denomina cuadrática si para cada i {1, 2,..., n} se cumple que
-- |a(i)- a(i-1)| = i^2 .
--
-- Definir la función
-- esCuadratica :: [Int] -> Bool
-- tal que (esCuadratica xs) se verifica si xs cuadrática. Por ejemplo,
-- esCuadratica [2,1,-3,6] == True
-- esCuadratica [2,1,3,5] == False
-- esCuadratica [3,4,8,17,33,58,94,45,-19,-100] == True
-- ---------------------------------------------------------------------
esCuadratica :: [Int] -> Bool
esCuadratica xs = undefined
-- ---------------------------------------------------------------------
-- Ejercicio 20.1. Definir las funciones
-- ultima, primera :: Int -> Int
-- tales que
-- * (ultima n) es la última cifra del número natural n y
-- * (primera n) es la primera cifra del número natural n.
-- Por ejemplo,
-- ultima 711 = 1
-- primera 711 = 7
-- ---------------------------------------------------------------------
ultima, primera :: Int -> Int
ultima n = undefined
primera n = undefined
-- ---------------------------------------------------------------------
-- Ejercicio 20.2. Definir la función
-- encadenadoC :: [Int] -> Bool
-- tal que (encadenadoC xs) se verifica si xs es una lista de enteros
-- positivos encadenados (es decir, la última cifra de cada número
-- coincide con la primera del siguiente en la lista). Por ejemplo,
-- encadenadoC [711,1024,413,367] == True
-- encadenadoC [711,1024,213,367] == False
-- ---------------------------------------------------------------------
encadenadoC :: [Int] -> Bool
encadenadoC xs = undefined