Está en la página 1de 49

Ejercicios

de Examen. Informática. Haskell. Versión curso 2020/2021




INFORMÁTICA
GRADO DE MATEMÁTICAS
Ejercicios de examen de Haskell

Cada ejercicio se ha enmarcado en el tema más avanzado que hay que haber estudiado para
resolverlo completo. Para resolución hacen falta conocimientos de ese tema y de todos, o parte,
de los temas anteriores.

INDICE




1. Febrero 2013. Fun. Tema 2 ................................................................................................................................... 3
2. Febrero 2013. Cubo. Tema 4 (aleatorios) ....................................................................................................... 3
3. Febrero 2013. menorNatural. Temas 3 y 4 ................................................................................................... 4
4. Febrero 2013. colaPrioridad. Tema 6 ............................................................................................................... 4
5. Julio 2013. Serpientes. Tema 3 ............................................................................................................................ 4
6. Septiembre 2013. Secuencia Cíclica. Tema: 3. ............................................................................................. 5
7. Septiembre 2013. 2. INTERSECCION. Temas: 3. .......................................................................................... 5
8. Septiembre 2013. esSubExpr. Tema 5. ........................................................................................................... 5
9. Septiembre 2013. Distancia. Tema: 6 ............................................................................................................... 5
10. Febrero 2014. Es-suave y Suaves. Tema 4 ................................................................................................... 6
11. Febrero 2014. Maya, Willy y Casandra. Tema 5 aleatorios .................................................................. 6
12. Febrero 2014. Expr. Tema 5 .............................................................................................................................. 7
13. Julio 2014. PreMax. Tema 3 ................................................................................................................................ 7
14. Julio 2014. partir. Tema 3 ................................................................................................................................... 7
15. Julio 2014. Distribuye. Tema 2, 4 ..................................................................................................................... 7
16. Julio 2014. La tortuga. Tema: 5 ......................................................................................................................... 8
17. Septiembre 2014. UnosYCeros. Tema 3 ........................................................................................................ 8
18. Septiembre 2014. Supercreciente. Tema: 3 ................................................................................................ 8
19. Febrero 2015. Parte. Tema 3 ............................................................................................................................. 9
20. Febrero 2015. algDiv. Tema 4. .......................................................................................................................... 9
21. Febrero 2015. Bolas blancas y negras. Tema 4 .......................................................................................... 9
22. Febrero 2015. Cola con dos pilas. Tema 6 ................................................................................................... 9
23. Julio 2015. Particion. Tema 4. ......................................................................................................................... 10
24. Julio 2015. K-esimo. Tema 3 ........................................................................................................................... 10
25. Julio 2015. Cerillas de Banach. Tema 4 ...................................................................................................... 10
26. Julio 2015. Arbol recursivo. Tema 6 ........................................................................................................... 10
27. Septiembre 2015. Romanos. Tema 3. .......................................................................................................... 11
28. Septiembre 2015. Suaves. Tema 4 ................................................................................................................ 11
29. Septiembre 2015. Chuck a Luck. Tema 4 ................................................................................................... 11
30. Febrero 2016. Números de Luhn. Tema 2 y 3. ........................................................................................ 12
31. Febrero 2016. CalculoMul. Tema 3 .............................................................................................................. 12
32. Febrero 2016. Expresiones Sum y Prod. Tema 5 ................................................................................... 13
33. Julio 2016. Binarios 10. Tema 3 ..................................................................................................................... 14


1
Ejercicios de Examen. Informática. Haskell. Versión curso 2020/2021


34. Julio 2016. Lap. Temas 3 y 4 ........................................................................................................................... 15
35. Julio 2016. La red social. Tema 5 .................................................................................................................. 16
36. Septiembre 2016. Look-and-say. Tema 3 .................................................................................................. 17
37. Septiembre 2016. Matrices. Tema 2. ........................................................................................................... 18
38. Septiembre 2016. Binarios CeroUno. Temas: 5 y 3. .............................................................................. 19
39. Febrero 2017. Nicomano. Tema 3. ............................................................................................................... 21
40. Febrero 2017. Valida. Temas 6, 3 y 2 .......................................................................................................... 21
41. Febrero 2017. Fechas. Tema 5. ...................................................................................................................... 22
42. Julio 2017. Raiz Cuadrada. Tema 2,3 ........................................................................................................... 23
43. Julio2017. Collatz. Tema 3 y 4 ........................................................................................................................ 25
44. Julio2017. Cubos. Tema 3 ................................................................................................................................. 25
45. Julio 2017. Infija Prefija. Tema 6 ................................................................................................................... 25
46. Septiembre 2017. Juego de la cuerda. Tema 4 ........................................................................................ 26
47. Septiembre 2017. La ley d'Hondt. Tema 3. ............................................................................................... 27
48. Septiembre 2017. Palíndromo. Temas 3. .................................................................................................. 28
49. Febrero 2018. El número PI. Temas 4 ........................................................................................................ 28
50. Febrero 2018, Codificar. Temas 2 y 3 ......................................................................................................... 29
51. Febrero 2018. El tren. Tema 5 ....................................................................................................................... 30
52. Julio 2018. Sustituir elementos lista. Tema 3. ........................................................................................ 31
53. Julio 2018. Anagramas. Temas 3 y 4. ........................................................................................................... 31
54. Julio 2018. Hamming. Tema 6. ....................................................................................................................... 32
55. Julio 2018. Grafo bidireccional etiquetado. Temas 5 y 6 ................................................................... 32
56. Septiembre 2018. Números de kaprekar. Tema 3 ................................................................................. 33
57. Septiembre 2018. Lista Cuadrados. Temas 2 y 4 .................................................................................. 33
58. Septiembre 2018. Grafo bidireccional 1. Temas 5 y 6 ........................................................................ 34
59. Febrero 2019. Alternada. Tema 2 y 3 ....................................................................................................... 34
60. Febrero 2019. El tipo Polinomios. Tema 5 .............................................................................................. 35
61. Febrero 2019. Un juego de números. Temas 3 y 5 ............................................................................... 35
62. Julio 2019. Fracciones continuas . Tema 3, 4 y 5 ................................................................................. 36
63. Julio 2019. Ampliando las funcionalidades de las Pilas . Tema 6 ................................................. 37
64. Julio 2019. El 46 . Tema 3,4 ........................................................................................................................... 37
65. Septiembre 2019. Numeros desnudos y de Dudeney. Tema 2 y 3 ................................................. 38
66. Septiembre 2019. Multiplicacion Rusa. Tema 3 y 4 .............................................................................. 38
67. Septiembre 2019. Multiplicacion Egipcia . Tema 3 y 4 ........................................................................ 39
68. Septiembre 2019. Arboles de Calkin-Wilf. Tema 5 ............................................................................... 39
69. Febrero 2020. Una sucesión (Tema 3) ....................................................................................................... 40
70. Febrero 2020. Donde Está (Temas 2 y 3) .................................................................................................. 40
71. Febrero 2020. Polinomios (Temas 5) ......................................................................................................... 41
72. Febrero 2020. Arbol de Factorización (Tema 6) .................................................................................... 42
73. Julio 2020. Pirámide de números ................................................................................................................. 43
74. Julio 2020. Un juego con la baraja española ............................................................................................. 44
75. Septiembre 2020. Fichas de dominó ........................................................................................................... 46



2
Ejercicios de Examen. Informática. Haskell. Versión curso 2020/2021



1. Febrero 2013. Fun. Tema 2

Sea h una función que toma dos enteros y devuelve un entero (h :: Int -> Int -> Int) que suponemos ya definida,
y sea fun la siguiente función:
fun xs = sum [ h 5 x | x <- xs ]
a) Da una nueva definición de la función fun, llamándola fun2, de modo que calcule lo mismo que la anterior
pero que use la función map en lugar de una lista por comprensión.
a) Sea la siguiente función:

fun' :: (Integral a) => a -> Bool
fun' x = not (even (abs x))

Da una nueva definición de esta función, pero defínela usando el operador de composición de funciones.

2. Febrero 2013. Cubo. Tema 4 (aleatorios)

Consideremos un cubo con sus aristas numeradas tal como se indica en la figura. 8 7

Supongamos definida la función aleatoriosDe :: [a] -> Semilla -> [a] que
devuelve una lista infinita pseudo-aleatoria con los elementos de la lista 5 6
primerargumento. Usando semillas distintas podemos modelar distintos
experimentos. 4 3

Consideremos el siguiente experimento: Los vértices 7 y 8 del cubo están
envenenados. Una hormiga parte del vértice número 1 y se mueve 1 2
aleatoriamente por las aristas del cubo hasta que en algún momento llega a uno de los
vértices envenenados y muere. Para realizar un movimiento, la hormiga selecciona aleatoriamente (con
probabilidad uniforme) uno de los tres vértices que se encuentran conectados (mediante una arista) con el
vértice en el que se encuentra y se desplaza a dicho vértice.

Por ejemplo, el resultado de un experimento podría ser 1 → 2 → 6 → 7, que indica que la hormiga realizó 3
movimientos antes de morir (partió del vértice 1; en dicho momento podía moverse a uno de los siguientes
vértices: 2, 4 o 5; desde el 1 decidió ir al 2; a partir de aquí decidió ir al 6 y por último fue al 7, donde murió).

a) Define una función experimento que tome como parámetro una semilla y devuelva una lista con todos los
vértices por los que pasa la hormiga al simular un experimento como el descrito, usando para generar los
números aleatorios que correspondan a las decisiones tomadas por la hormiga la semilla pasada como
parámetro. La lista resultado debe incluir, además de los vértices intermedios del recorrido, el inicial (vértice
1) y el final donde muere la hormiga (vértice 7 u 8). Además, los vértices de la lista deben estar en el orden en
que fueron recorridos por la hormiga.

b) Escribe una función promedioMovimientos que realice 1000 experimentos (con semillas distintas) y
calcule el promedio del número de movimientos que realiza la hormiga antes de morir. Para ello, realiza los
1000 experimentos, determina el número de movimientos realizados en cada experimento y calcula la media
aritmética de dichos valores.

c) Escribe una función probRepe que determine la probabilidad de que la hormiga pase más de una vez por el
mismo vértice antes de morir al realizar un recorrido. Para ello, realiza 1000 experimentos y cuenta como
casos favorables aquellos en los que el camino correspondiente contenga vértices repetidos. Tu función debe
devolver como resultado el cociente entre los casos favorables y el número de experimentos realizados.








3
Ejercicios de Examen. Informática. Haskell. Versión curso 2020/2021


3. Febrero 2013. menorNatural. Temas 3 y 4

Define una función menorNatural que calcule el menor número natural n tal que n! (factorial de n) termina
exactamente en 1987 ceros. Para resolver este problema, puedes usar cualquier función predefinida que
consideres útil y definir otras que sean útiles (cálculo del factorial, obtener cifras de un número, etc.)

4. Febrero 2013. colaPrioridad. Tema 6

Una cola con prioridad es una cola en la que cada uno de los valores almacenados tiene asociada una prioridad
(que supondremos un valor entero). Cuando se introduce un nuevo valor en la cola, éste se sitúa delante de todos
aquellos que tienen una prioridad inferior. Si hay valores en la cola con la misma prioridad, el nuevo valor se sitúa
detrás de ellos. Es decir, el orden de los elementos en la cola viene dado por sus prioridades, y a igualdad de
prioridades, los que entraron antes están delante. Al sacar un elemento de la cola, siempre saldrá el primero según
el orden anterior, es decir, de los de mayor prioridad, aquél que entró primero.

Sea el siguiente tipo recursivo para representar colas con prioridad:
type Prioridad = Int
data ColaPrioridad a = Vacía | Nodo Prioridad a (ColaPrioridad a) deriving Show

Con el que, por ejemplo, podemos definir la siguiente cola con prioridad de cadenas de caracteres:

Nodo 10 "Pepe" (Nodo 6 "Juan" (Nodo 3 "Luis" Vacía))



a) Define una función mete que tome como argumentos un elemento, su prioridad y una cola con prioridad y
devuelva la nueva cola que se obtiene tras insertar dicho elemento en su posición correcta (de acuerdo a su
prioridad).
b) Define las siguientes funciones:
• vacia, que devuelva una nueva cola con prioridad vacía,
• estaVacía, que tome una cola con prioridad y devuelva True si ésta almacena cero elementos,
• saca, que dada una cola con prioridad devuelva una tupla con el primer elemento y la cola con prioridad
que resulta tras sacar dicho elemento.

5. Julio 2013. Serpientes. Tema 3

a) Una serpiente de palabras es una secuencia de palabras donde cada palabra comienza con la letra con la
que acaba la palabra previa. Define una función esSerpiente que tome una lista de palabras y compruebe si
es una serpiente. Por ejemplo:
esSerpiente [“hola”, “amigo”, “oscura” ] => True
esSerpiente [“hola”, “amigo”, “rojo”, “oscuro” ] => False

NOTA: tu solución no debe producir un error en ningún caso y siempre debe devolver True o False.

b) Define una función serpiente que tome una lista de palabras y devuelva una de las serpientes más
largas (con más palabras) que se puede construir usando dichas palabras. La serpiente resultado podrá
no incluir alguna de las palabras dadas pero no debe incluir palabras duplicadas. Para resolver este
ejercicio, puedes asumir que en la lista de palabras proporcionadas no hay repeticiones de palabras y que
ninguna palabra es vacía. Por ejemplo:

serpiente ["amor","hola","osar","roto","otro","haskell"] =>


["hola","amor","roto","otro","osar"]

AYUDA: La idea es construir todas las serpientes posibles y seleccionar la más larga. Puede ser útil definir
primero una función que tome un carácter y una lista de palabras y devuelva una de las serpientes más
largas que se pueden construir con dichas palabras y tal que la primera palabra de la serpiente comience
por el carácter dado.



4
Ejercicios de Examen. Informática. Haskell. Versión curso 2020/2021

6. Septiembre 2013. Secuencia Cíclica. Tema: 3.


Sea una secuencia cíclica de longitud n una secuencia finita de n valores donde
cada elemento tiene un siguiente. Por ejemplo, la figura representa una secuencia
1
cíclica con 5 elementos, de modo que el siguiente a 1 es 3, el siguiente a 3 es 4, el
siguiente a 4 es 7, el siguiente a 7 es 9 y el siguiente a 9 es 1. 9 3
Supongamos que representamos una secuencia cíclica mediante una lista de
Haskell, de modo que consideramos que el siguiente al elemento de la lista en
posición k es el que está en la posición k+1, salvo para el último elemento de la 7 4
lista, cuyo siguiente es el primero.

Así, la secuencia cíclica de la figura puede ser representada con la lista [1,3,4,7,9], pero también, por ejemplo,
con la lista [4,7,9,1,3].

Define una función mismoCiclo que tome dos listas y devuelva True si ambas representan la misma
secuencia cíclica. Por ejemplo:
mismoCiclo [1,3,4,7,9] [9,1,3,4,7] => True
mismoCiclo [1,3,4,7,9] [1,2,4,7,9] => False

7.Septiembre 2013. 2. INTERSECCION. Temas: 3.


Define una función intersección que tome dos listas de enteros ordenadas ascendentemente (esto es una
precondición) y devuelva una lista con la intersección de sus elementos. Por ejemplo:
intersección [1,3,4,7] [2,3,4,5] => [3,4]
intersección [1,3,3,3,4,4,4,7] [2,3,3,4,4,4,4,5,5] => [3,3,4,4,4]
Observa que los elementos en las listas pueden estar repetidos y esto ha de tenerse en cuanta al calcular el
número de veces que aparece dicho elemento en el resultado. En este ejercicio se valorará que tu solución
utilice la precondición para simplificar y hacer eficiente la implementación de la función.

8. Septiembre 2013. esSubExpr. Tema 5.


Sea el siguiente tipo recursivo que permite representar expresiones aritméticas sobre enteros con una única
variable (denotada por X):
data Expr = Num Int -- valor entero
| Suma Expr Expr -- suma
| Prod Expr Expr -- producto
| X -- variable
deriving Eq

Por ejemplo, la expresión "X*(13+X)" se representa con Prod X (Suma (Num 13) X).
Define la función esSubExpr que, dadas dos expresiones devuelva True si la primera es una subexpresión
de la segunda, es decir, si la primera expresión aparece dentro de la segunda. Por ejemplo:
esSubExpr (Suma (Num 13) X) (Prod X (Suma (Num 13) X)) => True
esSubExpr (Suma (Num 13) X) (Suma (Num 13) X) => True
esSubExpr (Suma X (Num 13)) (Prod X (Suma (Num 13) X)) => False

Observa que consideramos que una expresión es subexpresión de sí misma.

9. Septiembre 2013. Distancia. Tema: 6


Dado un grafo se denomina distancia entre dos vértices distintos a la longitud del camino mínimo (más corto)
que va del primero al segundo. La excentricidad de un vértice se define como la máxima distancia medida


5
Ejercicios de Examen. Informática. Haskell. Versión curso 2020/2021


desde ese vértice, es decir, como la longitud del camino mínimo más largo que parte desde ese vértice a
cualquier nodo del grafo. Finalmente, el diámetro de un grafo se define como la distancia que separa a sus
dos vértices más alejados, es decir, como la máxima excentricidad de sus vértices, o la longitud del camino
mínimo entre dos vértices más largo que hay en el grafo.

Define una función en Haskell que calcule la excentricidad de un grafo

Nota: puedes usar las funciones de recorrido estudiadas en el tema 6:


type Camino a = [a]
caminosProfundidad :: (Eq a) => Grafo a -> a -> [Camino a]
caminosAnchura :: (Eq a) => Grafo a -> a -> [Camino a]

10. Febrero 2014. Es-suave y Suaves. Tema 4


Una sucesión de enteros es suave si para cualquier término de ésta el valor absoluto de la diferencia entre
dicho término y su siguiente es 1. Supongamos que representamos una sucesión de enteros mediante una
lista. Entonces, por ejemplo, las sucesiones [2,1,0,1] y [1,0,1] son suaves, mientras que la sucesión [2,5] no
lo es.
a) Usando recursividad, define una función esSuave que tome una lista de enteros y compruebe si es una
sucesión suave.
b) La función zipWith se encuentra predefinida del siguiente modo:
zipWith :: (a -> b -> b) -> [a] -> [b] -> [c]
zipWith f (x:xs) (y:ys) = f x y : zipWith f xs ys
zipWith _ _ _ = []
Da una definición no recursiva de la función esSuave usando, entre otras, la función zipWith.
c) Define la función suaves tal que suaves n (siendo n un entero mayor que 0) devuelva todas las
sucesiones suaves de longitud n con último término 0. Por ejemplo,
suaves 2 => [[1,0],[-1,0]]
suaves 3 => [[2,1,0],[0,1,0],[0,-1,0],[-2,-1,0]]

d) Define una propiedad para comprobar con QuickCheck que el resultado de la función suaves es
correcto.

11. Febrero 2014. Maya, Willy y Casandra. Tema 5 aleatorios

El problema de las tres abejas es el siguiente: en una estancia hay inicialmente tres abejas (Maya, Willy y
Casandra) y en otra estancia contigua ninguna. Cada segundo hay una abeja de las tres (al azar con probabilidad
1/3) que cambia de estancia. En promedio, ¿cuántos segundos harán falta para que pasen todas las abejas de la
primera a la segunda estancia?

Situación inicial Posible situación intermedia Situación final

Sean las siguientes definiciones en Haskell para modelar el problema anterior:


import Mates.Aleatorios
data Abeja = Maya | Willy | Casandra deriving (Eq,Show)
movimientos :: Semilla -> [Abeja]
movimientos s = aleatoriosDe [Maya,Willy,Casandra] s
De modo que el i-ésimo elemento de la lista devuelta por la función movimientos (para cierta semilla s) indica
la abeja que cambiaría de estancia en el segundo i-ésimo de dicha simulación.



6
Ejercicios de Examen. Informática. Haskell. Versión curso 2020/2021


Escribe un programa en Haskell para simular el problema de las tres abejas y para estimar el promedio de
segundos necesarios para alcanzar la situación final.

12. Febrero 2014. Expr. Tema 5


Sea el siguiente tipo recursivo para definir expresiones aritméticas sobre enteros dependientes de una variable (x):
data Expr = N Integer -- un entero
| X -- variable X
| Expr :+ Expr -- suma de dos expresiones
| Expr :- Expr -- diferencia de dos expresiones
| Expr :* Expr -- producto de dos expresiones
| Expr :^ Int -- expresión elevada a un entero
deriving (Eq, Show)
7
Por ejemplo, la expresión 3x - (x+2) quedaría representada en Haskell como:
e :: Expr
e = (N 3 :* X) :- ((X :+ N 2) :^ 7)

Define la función máximo :: Expr -> [Integer] -> (Integer,[Integer]) tal que máximo e xs devuelva la
tupla formada por el máximo valor de la expresión e para los puntos en xs y la lista con los puntos de xs en los que
e alcanza dicho máximo. Por ejemplo:

máximo ((N 10 :+ ((N 1 :- X) :* X)) :^ 2) [-3..3] => (100,[0,1])

2
ya que el máximo de la expresión (10 + ((1 – x) x)) en el intervalo [-3..3] es 100 y dicho
máximo se alcanza cuando x vale 0 o 1.

AYUDA: define primero una función que evalúe una expresión dado el valor de la variable x.

13. Julio 2014. PreMax. Tema 3


Define una función recursiva
preMax :: [Integer] -> Integer -> ([Integer],[Integer])

de modo que preMax xs n parte la lista xs en dos trozos. El primero contiene el mayor segmento inicial de xs tal
que la suma de sus elementos sea menor o igual que n, y el segundo contiene el resto de la lista xs. Por ejemplo

preMax [1,2,3,1,3,2,6,1] 9 => ( [1,2,3,1], [3,2,6,1] )

14. Julio 2014. partir. Tema 3

Una función partir :: [Integer] -> Integer -> [[Integer]] de modo que partir xs n parte la lista xs
en segmentos de máxima longitud cuyas sumas son menores o iguales que n. Por ejemplo:
partir [1,2,3,1,3,2,6,1] 9 => [ [1,2,3,1], [3,2], [6,1] ]

15. Julio 2014. Distribuye. Tema 2, 4

Define, usando listas por comprensión, la función distribuye que compruebe si una función distribuye sobre un
operador para todos los elementos de un conjunto. Por ejemplo, si
doble x = 2*x,
entonces
distribuye doble (+) [1..10] => True
ya que la función doble distribuye con la suma para el conjunto [1..10]:
∀x, y ∈[1..10] . doble x + doble y = doble( x + y)
La función, el operador y el conjunto se pasarán como parámetros. Indica además el tipo polimórfico de
dicha función.



7
Ejercicios de Examen. Informática. Haskell. Versión curso 2020/2021


16. Julio 2014. La tortuga. Tema: 5
Para describir el movimiento de una tortuga digital sobre una cuadricula, usamos el siguiente tipo:
data MovTortuga = Av | Dr | Rp Int [MovTortuga] deriving Show
De manera que:
Av significa que la tortuga avance una unidad,
Dr que gire 90 grados a la derecha, y
Rp n ms que repita n veces los movimientos que se encuentran en la lista ms.
Definimos también el tipo que registra toda una serie de movimientos
type CaminoTortuga = [MovTortuga]
Por ejemplo, un camino posible es
camino1 = [Av,Dr,Av,Dr,Dr,Dr,Rp 4 [Av,Dr,Dr,Dr],Dr]

a) Sea la longitud el número de segmentos unitarios que tiene un camino. Define una función para
determinar la longitud de un camino.
longitud :: CaminoTortuga -> Int
Por ejemplo:
longitud camino1 => 6
b) Sea el siguiente tipo para representar la orientación de la tortuga
data Orientación = N | S | E | O deriving Show
de modo que la orientación puede ser N (Norte), S (Sur), E (Este) u O (Oeste).
Define una función que tome la orientación inicial de la tortuga y un camino y devuelva la orientación final
tras seguir el camino dado.
orientación :: Orientación -> CaminoTortuga -> Orientación
Por ejemplo:

orientación E camino1 => S



17. Septiembre 2014. UnosYCeros. Tema 3

a) Define una función unosYCeros que devuelva una lista infinita con todos los números naturales cuyas cifras son
todas unos y ceros. Por ejemplo:
take 15 unosYCeros =>
[1,10,11,100,101,110,111,1000,1001,1010,1011,1100,1101,1110,1111]

b) Define una función multUnosYCeros que devuelva una lista con los múltiplos de un número formados por cifras
que son unos y ceros. Por ejemplo:
take 4 (multUnosYCeros 3) => [111,1011,1101,1110]

c) Define una propiedad para comprobar con QuickCheck que todo número natural mayor que cero tiene al
menos un múltiplo cuyos dígitos son todos unos y ceros

18. Septiembre 2014. Supercreciente. Tema: 3



Una sucesión creciente es aquella en cada elemento es estrictamente mayor que el anterior. Una sucesión
supercreciente es una sucesión creciente en la que la diferencia entre un elemento y el siguiente es estrictamente
mayor que la diferencia entre el elemento anterior y dicho elemento. Por ejemplo, [1,2,4,7] es supercreciente, pero
[1,4,8,12] no lo es. Define, usando recursividad, una función que tome una secuencia (como una lista) y compruebe
si es o no supercreciente.
supercreciente [1, 2, 4, 7] à True
supercreciente[2, 4, 8, 12] à False



8
Ejercicios de Examen. Informática. Haskell. Versión curso 2020/2021


19. Febrero 2015. Parte. Tema 3
Define una función recursiva parte que tome una lista de enteros y devuelva dos listas: una con los
elementos pares y otra con los impares. Para resolver este problema debes definir una única función recursiva
que genere la solución recorriendo una única vez los elementos de la lista parámetro. Por ejemplo:
parte [2,9,3,7,1,9,4] => ([2,4],[9,3,7,1,9])

20. Febrero 2015. algDiv. Tema 4.

Usando algunas de las siguientes funciones predefinidas:


all :: (a -> Bool) -> [a] -> Bool -- comprueba si todos los elementos cumplen
una condición
any :: (a -> Bool) -> [a] -> Bool -- comprueba si algún elemento cumple una
condición
filter :: (a -> Bool) -> [a] -> [a] -- selecciona los elementos que cumplen una
condición

define, sin usar recursividad, una función algDiv que tome dos listas de enteros y devuelva todos los
elementos de la primera que lista que son divisores de algún elemento de la segunda. Por ejemplo:
algDiv [4,5,7,3] [10,9,27,13] => [5,3]
algDiv [2,3,5] [7,11,13] => []

21. Febrero 2015. Bolas blancas y negras. Tema 4

Tenemos dos casilleros con un número par de casillas (n) cada uno. Inicialmente, todas las casillas del primer
casillero contienen bolas blancas y las del segundo bolas negras. A continuación, se toma al azar (con
probabilidad uniforme) una bola de cada uno de los casilleros y se intercambian (la bola seleccionada del
primer casillero se coloca en la casilla de la bola seleccionada del segundo casillero y la bola seleccionada
del segundo casillero se coloca en la casilla de la bola seleccionada del primero). El proceso se repite hasta
que cada casillero contenga n/2 bolas blancas y n/2 bolas negras. Escribe una función en Haskell que tome
como parámetros el nº de bolas (n) y una semilla (s), realice una simulación con dicha semilla y devuelva el
nº de intercambios de bolas realizados para llegar a la situación final. Escribe también una función que calcule
la esperanza (nº promedio de intercambios realizados) al realizar el experimento anterior.

1 2 3 4 1 2 3 4 1 2 3 4 1 2 3 4 1 2 3 4 1 2 3 4
Situación inicial (n=4) En el primer intercambio, se cambió la bola 2 Situación final (tras varios
del casillero 1º con la bola 3 del casillero 2º intercambios)


22. Febrero 2015. Cola con dos pilas. Tema 6

La estructura de datos cola puede ser implementada de un modo eficiente usando dos pilas. Los elementos
de la cola se encuentran distribuidos en las dos pilas según se explica a continuación. Los elementos de la
primera pila se corresponden con los primeros elementos de la cola representada (el tope de esta pila es el
primero de la cola, el que se encuentra debajo del tope es el segundo de la cola, etc). Los elementos de la
segunda pila van en la cola tras los de la primera pila, pero en este caso, el orden es inverso: el tope de la
segunda pila es el último elemento de la cola, el que se encuentra bajo el tope es el penúltimo de la cola, etc.
Para introducir un elemento en la cola, solo hay que introducirlo en la segunda pila, con lo que queda situado
tras el último de la cola. Para sacar un elemento de la cola, se saca el tope de la primera pila, siempre que
dicha pila no esté vacía; si ésta estuviese vacía, habría que pasar previamente todos los elementos de la
segunda pila a la primera y luego realizar la extracción.

Escribe un módulo de biblioteca donde se defina el tipo Cola según se ha descrito, de modo que se exporte
el tipo Cola que has definido y todas las operaciones propias de esta estructura. Para resolver este problema,
puedes suponer definido e importar el módulo Pila que hemos estudiado en el tema 6.



9
Ejercicios de Examen. Informática. Haskell. Versión curso 2020/2021

23. Julio 2015. Particion. Tema 4.

Usando recursividad y sin usar funciones predefinidas, define una función polimórfica de orden
superior particion que tome una propiedad (o predicado) y una lista, y devuelva dos listas: una
con los elementos que cumplen la propiedad y otra con los que no la cumplen.


24. Julio 2015. K-esimo. Tema 3

Consideremos una lista cuyos elementos se encuentran desordenados. El objetivo es definir una
función sobrecargada que devuelva el k-ésimo menor elemento de la lista sin ordenar ésta
(consideraremos que el 0-ésimo menor es el elemento mínimo de la lista). Por ejemplo:

k_ésimoMenor 0 [9,4,3,2,4,8,6] => 2 k_ésimoMenor 1 [9,4,3,2,4,8,6] => 3


k_ésimoMenor 2 [9,4,3,2,4,8,6] => 4 k_ésimoMenor 3 [9,4,3,2,4,8,6] => 4

k_ésimoMenor 4 [9,4,3,2,4,8,6] => 6

El algoritmo que debes utilizar para resolver este problema es de tipo divide y vencerás. En cada
paso, se considera el primer elemento de la lista (el pivot) y los demás, y se dividen los demás
en dos sublistas: la que contiene los elementos menores o iguales al pivot y la que contiene los
mayores. Si la primera sublista contiene k elementos, entonces ya hemos encontrado el k-ésimo
menor (es el pivot). En otro caso, hay que seguir buscando en una de las dos mitades (la que
corresponda).
Define la función k_ésimoMenor que se corresponda con este algoritmo.


25. Julio 2015. Cerillas de Banach. Tema 4

El problema de las cajas de cerillas de Banach es el siguiente: un matemático lleva dos cajas de
cerillas, una en su bolsillo izquierdo y otra en el derecho, que contienen inicialmente n1 y n2
cerillas respectivamente. Cada vez que necesita una cerilla, saca una aleatoriamente de uno de
sus bolsillos (la probabilidad de elegir cada bolsillo es la misma). Tras repetir este proceso
varias veces, llegará un momento en el cual la caja del bolsillo elegido se quedará vacía y la otra
caja tendrá un número de cerillas restantes. Define una función en Haskell para simular este
experimento con una semilla aleatoria dada. La función debe devolver una tupla con el nº de
cerillas que quedan en la caja no vacía y el nº total de cerillas extraídas.

26. Julio 2015. Arbol recursivo. Tema 6

Sea el siguiente tipo recursivo para representar árboles en Haskell y un árbol ejemplo, tal como
se han definido en clase:


data Arbol a = Vacio | Nodo a [Arbol a] deriving Show
arbol1 :: Arbol Int
arbol1 = Nodo 1 [ Nodo 2 [ Nodo 4 []
, Nodo 5 []
, Nodo 6 []
]
, Nodo 3 [ Nodo 7 [] ]
]



10
Ejercicios de Examen. Informática. Haskell. Versión curso 2020/2021


a) Una rama de un árbol es un camino que va desde el nodo raíz a una hoja. Define una función
ramas que devuelva todas las ramas de un árbol. Por ejemplo:
ramas arbol1 => [[1,2,4],[1,2,5],[1,2,6],[1,3,7]]

b) Define una función polimórfica de orden superior algunoCadaRama que tome un predicado y
un árbol, y que devuelva verdadero si en cada rama del árbol hay al menos un elemento que
verifica dicho predicado. Por ejemplo:
algunoCadaRama even arbol1 => False
algunoCadaRama odd arbol1 => True



27. Septiembre 2015. Romanos. Tema 3.
En la notación romana para expresar números, los valores de cada una de las letras utilizadas son los siguientes:
M vale 1000, D vale 500, C vale 100, L vale 50, X vale 10, V vale 5 e I vale 1.
Un número romano es una secuencia de letras. Para pasar un número romano a decimal, se recorren sus letras
desde la última a la primera (de derecha a izquierda) y se suman o restan los valores de cada una de ellas. El
valor de la última cifra siempre suma y, para las demás cifras, su valor restará si la cifra que le sigue (cifra a su
derecha) es mayor, o sumará en caso contrario.

Por ejemplo, el número romano MCMXCIX vale 1000 - 100 + 1000 – 10 + 100 - 1 + 10 = 1999.

Define una función romanoADecimal que tome una cadena de caracteres (correspondiente a un número romano)
y devuelva su valor.

28. Septiembre 2015. Suaves. Tema 4

La función zipWith se encuentra predefinida del siguiente modo:
zipWith :: (a -> b -> b) -> [a] -> [b] -> [c]
zipWith f (x:xs) (y:ys) = f x y : zipWith f xs ys
zipWith _ _ _ = []
Da una definición no recursiva de la función esSuave usando, entre otras, la función zipWith.

Define la función suaves tal que suaves n (siendo n un entero mayor que 0) devuelva todas las sucesiones
suaves de longitud n con último término 0. Por ejemplo,
suaves 2 => [[1,0],[-1,0]]
suaves 3 => [[2,1,0],[0,1,0],[0,-1,0],[-2,-1,0]]

29. Septiembre 2015. Chuck a Luck. Tema 4

Sea la siguiente función que devuelve una lista infinita con los resultados de tirar un dado:
import Mates.Aleatorios
dado :: Semilla -> [Dardo]
dado s = aleatoriosDe [1..6] s
Usando dicha función, podemos modelar distintos experimentos aleatorios proporcionando distintas semilla. En
una jugada del juego Chuck a Luck, un jugador tira un dado tres veces. Si obtiene un seis gana 1 euro, si obtiene
dos seises gana 2 euros y si obtiene tres seises gana 3 euros; si no obtiene ningún seis pierde un euro.
a) Supongamos que un jugador tiene siempre suficiente dinero para seguir jugando mientras lo desee. Escribe
una función que, dada una semilla, use la función dado con dicha semilla para simular 1000 jugadas del juego
Chuck a Luck (debes procesar 3000 elementos de la lista devuelta por dado, ya que cada jugada son tres tiradas)
y que devuelva una lista con 1000 enteros, correspondientes a los euros que gana o pierde (número positivo o
negativo) el jugador en cada jugada.


11
Ejercicios de Examen. Informática. Haskell. Versión curso 2020/2021


b) Sea el saldo correspondiente a un experimento como el anterior la cantidad que acaba ganando (positiva) o
perdiendo (negativa) el jugador tras realizar las 1000 jugadas. Escribe una función que realice 1 millón de
experimentos con distintas semillas (cada uno de 1000 jugadas) y devuelva la media de los saldos obtenidos por
el jugador en cada experimento.

30. Febrero 2016. Números de Luhn. Tema 2 y 3.


Los números de las tarjetas de crédito cumplen las restricciones que establece un algoritmo llamado Luhn.
Su creador fue Hans Peter Luhn, un científico de IBM, y su uso ha sido tan extendido que, desde que
fuera creado, hoy controla la creación y validación de todas las tarjetas de crédito del mundo.

Dado un número entero positivo de n cifas (por ejemplo 49927398716) para verificar si cumple el algoritmo
de Luhn.

i. Multiplicamos por 2 los dígitos que ocupan las posiciones pares empezando por el final (sombreado
en la tabla inferior):
(1×2) = 2, (8×2) = 16, (3×2) = 6, (2×2) = 4, (9×2) = 18
ii. Sumamos los dígitos que ocupaban las posiciones impares con los dígitos de los productos obtenidos:
6 + (2) + 7 + (1+6) + 9 + (6) + 7 + (4) + 9 + (1+8) + 4 = 70
iii. Si el resto de dividir el total entre 10 es igual a cero, el número es correcto.


Se pide
1) Implementar la función luhn tal que dado un número diga si cumple las restricciones de Luhn.
Utilizar listas por comprensión (1 punto)
luhn 49927398716 -> True
luhn 49927398717 -> False

2) Implementar la luhn función tal que, dado un número, diga si cumple la suma de verificación de
Luhn. Utilizar recursividad. También se pueden utilizar las funciones auxiliares del apartado anterior.
(0,5 puntos)

3) Definir la sigLuhn tal que, dado un número, si éste cumple la suma de verificación de Luhn
devuelva el dígito (o dígitos) que se podría añadir al final (a la derecha) para que el número resultante
también cumpliese el algoritmo de Lunh. Si el número no cumple la suma de verificación de Luhn se
sacará un menaje de error (0,5 puntos)

sigLuhn 49927398716 à [8]




31. Febrero 2016. CalculoMul. Tema 3

Dados un conjunto de números y operadores, y dado un resultado, pretendemos encontrar una
expresión formada con los números y operadores cuyo valor sea dicho resultado.

1) Suponiendo que sólo se puede usar el producto, definir la función calculoMul tal que dada una
lista de números, lista, y un número, num, devuelva una posible solución al cálculo de num. La solución
será representada con una lista de números que forman parte de la expresión. Si no es posible, se
devolverá la lista vacia.


12
Ejercicios de Examen. Informática. Haskell. Versión curso 2020/2021



calculoMul [3, 4, 5] 75 à [3,5,5] -- ya que 3*5*5 = 75
calculoMul [3, 4, 5] 76 à []
calculoMul [3, 4, 5] 180 à [3,3,4,5] -- 3*3*4*5 = 180
calculoMul [] 180 à []
calculoMul [3, 4, 5] 0 à []

1.1. Indicar el algoritmo/método seguido para obtener la solución a la función calculoMul, en
castellano (no usar haskell) (0,5 puntos)
1.2. Implementar la función calculoMul utilizando recursividad, codificando en haskell el
método explicado en el apartado 1.1 (0,5 puntos)
1.3. Implementar la función calculoMul utilizando acumuladores, con el mismo método
explicado en el apartado 1.1 (0,5 puntos)


2) Ahora vamos a suponer que vamos a calcular el número num utilizando sumas y productos de
los números de la lista, lista. También suponemos que num es menor que 1000. El método seguido será
calcular el número como un sumatorio de productos.
calculoSumasMul [3, 4, 5, 2] 235 à [[2,2,2,5,5],[2,3,5],[5]]
-- ( (2*2* 2* 5*5) + (2 *3*5) + (5)) = 200+30+5=235
calculoSumasMul [3, 4, 5, 2] 231 à [] -- no es posible
calculoSumasMul [3, 4, 5, 2] 220 à [[2,2,2,5,5],[2,2,5]]
calculoSumasMul [3, 4, 5, 2] 60 à [[2,2,3,5]]
calculoSumasMul [3, 4, 5, 2] 6 à[[2,3]]
calculoSumasMul [3, 4, 5, 2] 200 à [[2,2,2,5,5]]

2.1. Indicar el algoritmo/método seguido para obtener la solución a la función
calculoSumasMul, en castellano (no usar haskell). Identificar claramente la lista de funciones
auxiliares que se van a necesitar (0,5 puntos)
2.2. Implementar la función calculoSumasMul, codificando en haskell el método explicado en
el apartado 2.1 (1 punto)

32. Febrero 2016. Expresiones Sum y Prod. Tema 5


Se ha definido el siguiente tipo de datos que permite definir expresiones de sumas y productos
de números enteros

data Expr a = Null | Sum [Expr a] | Prod [a] deriving Show
Así [[2,2,2,5,5],[2,3,5],[5]] se representa como
Sum [Prod [2,2,2,5,5],Prod [2,3,5],Prod [5]]

La evaluación de dicha expresión tendría como resultado 235

1) Definir una función expresionDe que dada una lista de listas de números devuelva la expresión
correspondiente según el tipo de datos Expr, que es la suma de los productos de cada sublista.
expresionDe [[2,2,2,5,5],[2,3,5],[5]] à
Sum [Prod [2,2,2,5,5],Prod [2,3,5],Prod [5]]
expresionDe [[4, 5, 6, 7]] à
Sum [Prod [4,5,6,7]]

2) Define la función expresionToString tal que dada un elemento del tipo expresión devuelva una
cadena de caracteres con su representación algebraica, tal y como muestran los siguientes
ejemplos.. Suponed implementada una función numToStringChar tal que dado un numero devuelve
el carácter de ese número.

numToStringString 4 à “4”


13
Ejercicios de Examen. Informática. Haskell. Versión curso 2020/2021


expresionToString (Sum [Prod [2,2,2,5,5],Prod [2,3,5],Prod [5]]) à
"(2 * 2 * 2 * 5 * 5) + (2 * 3 * 5) + (5)"

3) Ahora se quiere definir una funcion evaluaExpr que evalue una expresión dando como resultado el
valor numérico de hacer el sumatorio de los productos

evaluaExpr (Sum [Prod [2,2,2,5,5],Prod [2,3,5],Prod [5]]) à 235

33. Julio 2016. Binarios 10. Tema 3


Vamos a trabajar con números binarios. Un número binario representa con ceros y unos una cantidad
numérica. Así el 1001 es el número 9

1 0 0 1 Numero binario
3 2 1 0 posicion
23 22 21 20 2 posicion
8 0 0 1 Multiplico el numero binario (fila 1) * 2posicion (fila 3)
8 + 1 = 9 Sumo los valores

1) Para pasar un número en formato decimal a binario, se divide el número del sistema decimal
entre 2, cuyo resultado entero se vuelve a dividir entre 2, y así sucesivamente hasta que el
dividendo sea menor que el divisor, 2. Es decir, cuando el número a dividir sea 1 finaliza la
división. A continuación se ordenan los restos empezando desde el último al primero,
simplemente se colocan en orden inverso a como aparecen en la división. Este será el número
binario que buscamos. Asi se obtendría el binario del número 100



Definir la función aBinarioL que dado un número en formato decimal convierta un número de
formato decimal a binario y como una lista de ceros y unos, en una lista.
aBinarioL 2 à[1,0]
aBinarioL 5 à[1,0,1]
aBinarioL 100 à[1,1,0,0,1,0,0]

La suma de números binarios se realiza de derecha a izquierda, es decir, de los bits de menos
peso a los de más, igual que se hace en la suma de números decimales. Cada par de dígitos se
suma entre ellos, dándose los casos de la tabla adjunta. De esta forma al sumar de derecha a
izquierda el acarreo dígito a dígito, se dan los casos de la tabla adjunta, según los valores de los
dígitos que se suman, y se generan dos valores: el dígito resultante y el correspondiente
acarreo.

Argumentos de entrada Resultado
Digito 1 Digito2 Acarreo [digito-resultante, acarreo-salida]
0 0 0 [0,0]
0 0 1 [1,0]
0 1
0 [1,0]
1 0
0 1
1 [0, 1]
1 0
1 1 0 [0, 1]
1 1 1 [1, 1]



14
Ejercicios de Examen. Informática. Haskell. Versión curso 2020/2021



2) Definir la función sumDigBinaria que calcule en binario la suma de dos dígitos teniendo
en cuenta el acarreo (sin convertir los números a decimal en ningún momento ni usando el
operador suma de Haskell). El primer argumento es el digito 1, el segundo el digito2 y el tercero
es el acarreo. El resultado será una lista con dos valores, el primero el resultado y el segundo el
acarreo según la tabla anterior. Utilizar guardas para implementar la función.

sumDigBinaria 1 0 0 à [1, 0]
sumDigBinaria 1 1 0 à [0, 1]
sumDigBinaria 0 0 0 à [0, 0]
sumDigBinaria 1 1 1 à [1, 1]

3) Utilizando la función sumDigBinaria,, llamada SumDigBinariaNum tal que dados dos
dígitos, devuelva el número binario resultante en una lista. (No se considerará válida si no se
usa la función sumDigBinaria):
sumDigBinariaNum 0 0 à [0]
sumDigBinariaNum 0 1 à [1]
sumDigBinariaNum 1 1 à [1,0]

4) Definir una función que utilice las funciones anteriores que sean necesarias, llamada sumaB
que tenga como entrada dos números en formato decimal, los convierta en números binarios y
luego realice la suma en binario



sumaB 1 3 à [1,0,0]
sumaB 3 1 à [1,0,0]
sumaB 4 2 à [1,1,0]
sumaB 1 0 à [1]
sumaB 7 3 à [1,0,1,0]


Importante. No se puede utilizar en ningún momento el operador suma de haskell, ni hacer la
suma de los números en formado decimal en cualquiera otra forma y convertirlos luego en
binario. SE de be implementar la función utilizando las funciones de los apartados anteriores
que se consideren necesarias




34. Julio 2016. Lap. Temas 3 y 4

1) Escribe una función llamada lap, de lista anterior posterior, que genere la siguiente lista
infinita (1,5 puntos)
[[1],[0,2], [-1, 1, 1, 3] , [-2, 0, 0, 2, 0, 2,2,4]....]



15
Ejercicios de Examen. Informática. Haskell. Versión curso 2020/2021


donde una lista empieza por 1 y los sucesivos elementos resultan del anterior sustituyendo
cada elemento por su antecesor y su sucesor (sumando y restando 1), es decir, el 1 por el 0
y el 2, el 0 por el -1 y el 1, el 2 por el 1 y el 3, etc. La lista empieza por el 1.

take 4 lap à [[1],[0,2],[-1,1,1,3],[-2,0,0,2,0,2,2,4]]

2) Definir la función lapRandom con un parámetro de entrada que es una semilla y que genera
una lista infinita según se indica a continuación. Con la semilla de entrada se generarán dos
números aleatorios, el primero para indicar por qué número empieza el primer elemento de la
lista, y el segundo para indicar el valor que se suma y resta para calcular el antecesor y posterior
de cada elemento, como se hacia en la función anterior. Suponed que está importada la librería
Mates.aleatorios(1 punto)

Por ejemplo, si la semilla es 5, y a partir de esa semilla se generan los números aleatorios 9 y 2,
[9] será el primer elemento, y el siguiente es 9-2 y 9+2, luego será aplicado en +2 y -2 a cada
elemento anterior para calcular el siguiente:

take 4 (lapRandom 5) à
[[9],[7,11],[5,9,9,13],[3,7,7,11,7,11,11,15]]

35. Julio 2016. La red social. Tema 5
Tenemos una red social que permite a los usuarios enviar mensajes 140 caracteres. Además
permite seguir a otros usuarios, citarlos o ser seguido. Para cada usuario se los siguientes datos
1. El identificador del usuario, que es una cadena que empieza por @. Por ejemplo “@adria”
2. Lista de mensajes creados por el usuario ordenados cronológicamente. Cada mensaje es una
cadena de caracteres con la siguiente estructura: una serie de datos numéricos,
correspondientes al año, mes, dia, hora , minuto y segundo y el texto.
3. Lista de seguidores: es una lista de identificadores de usuarios ordenados alfabéticamente
4. Lista de usuarios que esta siguiendo, como una lista de identificadores ordenados
alfabéticamente.

Asi, para el cocinero adria, tenemos los siguientes valores de ejemplo, donde tiene dos menajes,
cuatro seguidores y está siguiendo a cinco usuarios.

Nombre Nombre Valor de cada campo
variable campo
adria Persona “@adria”
Mensajes "2016 3 12 9 23 Siempre he cocinado con el objetivo de aportar algo
técnico y conceptual a la cocina y de emocionar a los clientes, como mis
amigos @berasategui @sandavoal y @luisjanez"

"2015 3 10 23 10 La cocina de @osuna es de alta calidad y creativa, sin


fronteras, como la de @berasategui"

Seguidores "@berasategui", "@dacosta", "@danigarica", "@ramonluis"


Siguiendo "@berasategui", "@davidmunoz", "@joseandres", "@luisjanez", "@sandoval"

Para almacenar los datos de un usuario definimos los siguientes tipos de datos, done Cuenta
almádena todo lo reverente a un usuario

type Persona = String
type Mensajes = [String]
type Seguidores = [Persona]
type Siguiendo = [Persona]
data Cuenta = Usuario Persona Mensajes Seguidores Siguiendo



16
Ejercicios de Examen. Informática. Haskell. Versión curso 2020/2021


deriving Show

Se pide
1) Suponiendo declarado el tipo de datos Cuenta y las siguientes variables m,se, y si

m = ["2016 3 12 9 23 Siempre he cocinado con el objetivo de aportar algo técnico y conceptual a la
cocina y de emocionar a los clientes, como mis amigos @berasategui @sandavoal y @luisjanez",

"2015 3 10 23 10 La cocina de @osuna es de alta calidad y creativa, sin fronteras, como la de


@berasategui"]

se = ["@berasategui", "@dacosta", "@danigarica", "@ramonluis"]


si = ["@berasategui", "@davidmunoz", "@joseandres", "@luisjanez", "@sandoval"]

Escribir código haskell que permita declarar y asignar a una variable tipo Cuenta los datos del
cocinero adria de la tabla (0,3 puntos)

2) Definir una declaración (cabecera) y la función crearUsuarioVacio que permita crear un
usuario, inicialmente sin mensajes ni seguidores (0,2 puntos).

crearUsuarioVacio "adria" à Usuario "@adria" [] [] []

3) Definir la declaración y la función getCitando que permita obtener las personas a las que está
citando un usuario en sus mensajes, ordenadas alfabéticamente (1 punto). Se puede utilizar la
función words que dado un string devuelve la lista de palabras que éste tiene.

words "la casa es azul” à["la”, “casa”, “es”, “azul”]

getCitando adria à ["@berasategui","@luisjanez","@osuna","@sandavoal"]

4) Suponiendo que el mensaje está bien escrito según la estructura definida anteriormente, definir la
declaración y la función addMensaje que permite añadir un mensaje nuevo a un usuario, y
devuelve una cuenta nueva con el mensaje añadido (1 punto)
addMensaje adria "2016 2 1 ahora mismo estamos presentando @chicote y @oliver la nueva carta de un
restaurante de Madrid"
à
Usuario "@adria"
["2015 3 10 23 10 La cocina de @osuna es de alta calidad y creativa, sin fronteras, como la de
@berasategui",

"2016 2 1 ahora mismo estamos presentando @chicote y @oliver la nueva carta de un restaurante de
Madrid",

"2016 3 12 9 23 Siempre he cocinado con el objetivo de aportar algo t\233cnico y conceptual a la


cocina y de emocionar a los clientes, como mis amigos @berasategui @sandavoal y @luisjanez"]

["@berasategui","@dacosta","@danigarica","@ramonluis"]
["@berasategui","@davidmunoz","@joseandres","@luisjanez","@sandoval"]

5) Definir la cabecera de librería RedSocial que exporte el tipo de datos Cuenta y las funciones
definidas a lo largo de este ejercicio (0,5 puntos). No hace falta definir el tipo y las funciones de
nuevo, es suficiente con poner un comentario “aquí van los tipo”, “aquí van las funciones”

36. Septiembre 2016. Look-and-say. Tema 3
La secuencia look-and-say es una secuencia recursiva de números que ha sido definida y
estudiada por John Conway. La manera de definir la secuencia es la siguiente:
- Se toma un número de entrada
- Se mira el número y visualmente se agrupan los números que tienen el mismo dígito


17
Ejercicios de Examen. Informática. Haskell. Versión curso 2020/2021


- Se dice el número de izquierda a derecha, grupo por grupo diciendo cuantos dígitos hay y luego el
dígito que es. Así para todos los números de la secuencia.
- Ese el número siguiente de la secuencia.

Ejemplo, si empiezo con el número 1
1 à(un 1) 1 1 à (dos uno) 2 1 à (un dos) (un uno) 1 2 1 1 à (un uno) (un dos) (dos uno) à
1 1 1 2 2 1

1) Definir la función contar que recibe como parámetro una secuencia y devuelve una lista de dos
elementos el número de veces que está éste repetido el primer elemento de la secuencia (hasta que
aparece uno distinto e independientemente de si luego aparece en el resto de la secuencia) y el elemento.
Implementar la función usando recursividad (0,8 puntos):

contar [1,1,1,2,2,1,1,1] à [3, 1] -- al principio, el 1 está 3 veces
contar [2, 1] à [1, 2] –- el 2 está una vez
contar [3,1,1,3,1,4,1,1,3,1,1,2]] à [1, 3] --al principio, el 3 esta una vez

2) Definir la funcion haskell las (de look-and-say) tal que dado un número de inicio y un número n de
términos devuelva la secuencia de n términos correspondiente. Escribir brevemente el procedimiento
seguido y luego poner la implementación (0,7 puntos)

las [1] 6 à
[[1],[1,1],[2,1],[1,2,1,1],[1,1,1,2,2,1],[3,1,2,2,1,1]]

las [2] 7 à
[[2],[1,2],[1,1,1,2],[3,1,1,2],[1,3,2,1,1,2],[1,1,1,3,1,2,2,1,1,2],
[3,1,1,3,1,1,2,2,2,1,1,2]]

3) Utilizando las funciones definidas en el apartado anterior que sean necesarias, definir en
haskell la función las’ (look-and-say’) tal que dado un número de inicio devuelva la secuencia
infinita look-and-say (0,5 puntos)

take 6 (las' [1]) à
[[1],[1,1],[2,1],[1,2,1,1],[1,1,1,2,2,1],[3,1,2,2,1,1]]

take 7 (las' [2]) à


[[2],[1,2],[1,1,1,2],[3,1,1,2],[1,3,2,1,1,2],[1,1,1,3,1,2,2,1,1,2],
[3,1,1,3,1,1,2,2,2,1,1,2]]

37. Septiembre 2016. Matrices. Tema 2.



Tenemos una matriz bidimensional de nXm que representamos por n listas de m elementos.
Los elementos de la matriz son números enteros. Representamos una matriz como una lista
de listas. Por ejemplo, en la variable “matriz” almacenamos una matriz de 3 x 2 (tres filas de
dos columnas)
matriz= [[2,1], [1,0], [3,2]]

Se pide implementar con listas por comprensión y/o funciones de orden superior (sin usar
recursividad) las siguientes funciones:

1) Tres funciones tal que dada una matriz devuelva la fila, columna o elemento de la posición
indicada (0,6 puntos: 0,2 cada una), utilizando listas por comprensión: filaM, columnaM, elementoM

filaM matriz 3 à [3,2]


columnaM matriz 2 à [1,0,2]
elementoM matriz 3 1 à 3


18
Ejercicios de Examen. Informática. Haskell. Versión curso 2020/2021



2) Funcion llamada cerosEnDiagonalPrincipal que, dada una matriz cuadrada, devuelva el
número de ceros en diagonal principal (0,5) y otra llamada cerosEnDiagonalSecundaria que
devuelva el número de ceros en diagonal secundaria, utilizando listas por comprensión(0,4 puntos).
matrizCuadrada =[
[1, 2, 2, 1, 4, 0],
[0, 2, 0, 1, 0, 5],
[1, 2, 0, 0, 4, 0],
[0, 2, 0, 1, 4, 5],
[1, 0, 2, 1, 0, 5],
[1, 2, 2, 1, 4, 0] ]
cerosEnDiagonalPrincipal matrizCuadrada à 3 (en negrita)
cerosEnDiagonalSecundaria matrizCuadrada à 5 (subrayado)

3) Función que haga el producto de dos matrices, llamada productoM que reciba una matriz de (n
x m), y otra de (m x z) y devuelva el producto de ambas. Por ejemplo, el producto de dos matrices de
dimensión 3x2, y 2x3 sería el siguiente (1 punto)


productoM [[3, 2, 1], [1, 1, 3], [0, 2, 1]] [[2, 1], [1, 0], [3, 2]]
à [[11,5],[12,7],[5,2]]



38. Septiembre 2016. Binarios CeroUno. Temas: 5 y 3.

Se ha definido el tipo de datos Binario que trabaja únicamente con ceros y con unos :
data Binario = Cero | Uno deriving (Show, Eq)

En general, un número binario representa con ceros y unos una cantidad numérica. Así el 1001
es el número 9

Uno Cero Cero Uno Numero binario
3 2 1 0 posicion
2 2
3 2 2
1 2 2 posicion
0

8 0 0 1 Multiplico el numero binario (fila 1) *


2posicion (fila 3)
8 + 1 = 9 Sumo los valores



19
Ejercicios de Examen. Informática. Haskell. Versión curso 2020/2021


Para pasar un número en formato decimal a binario, se divide el número del sistema decimal
entre 2, cuyo resultado entero se vuelve a dividir entre 2, y así sucesivamente hasta que el
dividendo sea menor que el divisor, 2. Es decir, cuando el número a dividir sea 1 finaliza la
división. A continuación se ordenan los restos empezando desde el último al primero,
simplemente se colocan en orden inverso a como aparecen en la división. Este será el número
binario que buscamos.




Así, el número 9 en binario se representa como 1001 y con el tipo de datos Binario sería
[Uno, Cero, Cero, Uno]

1) (1,5 puntos) Definir la función aBinarioL que dado un número en formato decimal convierta un número
de formato decimal a binario y como una lista de ceros y unos, en una lista del tipo de datos Binario.
aBinarioL 6 à [Uno,Uno,Cero]
aBinarioL 3 à [Uno,Uno]

2) (1 punto) Definir la función aDecimal dada una lista que representa un numero codificado en binario y
representado con el tipo de datos Binario, lo convierta de formato Binario a un número decimal
utilizando listas por comprensión


aDecimal [Uno, Cero, Cero, Uno] à 9
aDecimal [Uno, Uno, Cero] à 6

La suma de números binarios se realiza de derecha a izquierda, es decir, de los bits de menos
peso a los de más, igual que se hace en la suma de números decimales. Cada par de dígitos se
suma entre ellos, dándose los casos de la tabla adjunta. De esta forma al sumar de derecha a
izquierda el acarreo dígito a dígito, se dan los casos de la tabla adjunta, según los valores de los
dígitos que se suman, y se generan dos valores: el dígito resultante y el correspondiente
acarreo.

Argumentos de entrada Resultado
Digito Uno Digito2 Acarreo [digito-resultante, acarreo-salida]
Cero Cero Cero [Cero,Cero]
Cero Cero Uno [Uno,Cero]
Cero Uno
Cero [Uno,Cero]
Uno Cero
Cero Uno
Uno [Cero, Uno]
Uno Cero
Uno Uno Cero [Cero, Uno]
Uno Uno Uno [Uno, Uno]

3) (1 punto) Definir la función SumaB tal que dados dos números en formato decimal los convierta en tipo
de datos Binario, calcule la suma binaria de ambos y devuelva el resultado en una lista de datos de tipo
Binario, de derecha a izquierda teniendo en cuenta la suma de digito explicada en al tabla.
sumaB 2 1 à [Uno,Uno]
sumaB 10 2 à [Uno,Uno,Cero,Cero]

No son válidas soluciones que no conviertan los números a binario antes de hacer la suma, que
utilicen la suma de haskell o que no realicen la suma de forma binaria según se indica.


20
Ejercicios de Examen. Informática. Haskell. Versión curso 2020/2021




39. Febrero 2017. Nicomano. Tema 3.

Nicomaco de Gerasa descubrió la siguiente propiedad de los números enteros:

Sumando el primer impar se obtiene el primer cubo; 13 = 1 = 1


Sumando los dos impares siguientes se obtiene el segundo cubo; 23 = 5 + 3 = 8
Sumando los tres impares siguientes se obtiene el tercer cubo; 33 = 7+ 9 + 11 = 27
Y así sucesivamente... 43 = 13+15+17+19 = 64


1) Construir la función impares y la función nicomano. La función impares devuelve una lista infinita de números
impares. La función nicomano llamará a la función impares y devolverá el cubo de un numero n utilizando la
propiedad de Nicómaco. Implementar la función usando recursividad ( 1 punto)
take 7 impares à (1, 3, 5, 7, 9, 11, 13, 15)
nicomano 4 à 64
nicomano 3 à 27
nicomano 8 à 512

2) Sin utilizar las funciones anteriores, sino por el método aquí indicado, construir la función cubos que devuelta
una lista infinita de los números naturales al cubo. Para ello se seguirá el siguiente algoritmo:

2.1 Implementar la función empaqueta tal que dada una lista de elementos, devuelva una lista con estos elementos
empaquetados del siguiente modo: el primero, los dos siguientes, los tres siguientes.... hasta al final. Teniendo en
cuenta que la última lista puede estar truncada (es decir, puede que no tenga n+1 elementos q que la lista anterior)
(0,5 puntos)

empaqueta [1..10] à [[1],[2,3], [4, 5, 6], [7, 8, 9, 10]]
empaqueta "matematicas" à["m","at","ema","tica","s"]
empaqueta [1..11] à [[1],[2,3], [4, 5, 6], [7, 8, 9, 10] [11]]
empaqueta (take 6 impares) à [[1], [3,5], [7, 9,11]]


2.2. Implementar la función cubos (que no tiene ningún parámetro) que utilice la función empaqueta, y devuelva
una lista infinita de los cubos de los enteros positivos. Implementar esta función utilizando funciones de orden
superior (1 punto)
take 5 cubos = [1, 8, 27, 64, 125]
take 10 cubos = [1, 8, 27, 64, 125, 216, 343, 512, 729, 1000]







40. Febrero 2017. Valida. Temas 6, 3 y 2

Se va a programar un sistema de envío y recepción de mensajes, que son cadenas de caracteres. En esos mensajes es
importante poder identificar aquellos submensajes dentro de un mensaje que pueden ser caracteres o números,
dependiendo del caso a resolver. Para ello, se implementará un programa que recibe los mensajes, mira si son
correctos, los procesa y actúa en consecuencia.



21
Ejercicios de Examen. Informática. Haskell. Versión curso 2020/2021



1) En una primera versión, los separadores son “(“ para indicar el inicio y “)” para indicar el final. Implementar en
haskell una función tal que dada una cadena de caracteres nos diga si el mensaje es correcto o no. No se pueden
utilizar pilas ni otra estructura de datos, sólo los tipos predefinidos de haskell (números y/o listas).
valida “(2*5+(5-3)*8+(3))” à True
valida “( 2 – (4*6)))” à False
valida “ ())(” à False

a. Implementar la función, llamándola valida1, con recursividad con acumuladores (0,4 puntos)
b. Implementar la función, llamándola valida2, con listas por comprensión (0,4 puntos)

2) En una segunda versión del programa, es necesario separar diferentes grupos de datos, que además son cambiantes
(dependen del caso a resolver), y para ello se decide que los separadores de inicio y de fin se pasan como parámetro de la
función, concretamente como pares donde le primero indica el inicio y el segundo indica el fin. Por ejemplo,

pares = [ ('[', ']'), ('(', ')'), ('{', '}'), ('/', '%') ]

Se pide utilizar el TAD de Pilas Implementar una función llamada valida3 - que utilice como soporte el tipo abstracto de
datos Pila-, tal que reciba un mensaje (que es una cadena de caracteres) y una lista de pares, devuelva como salida True
si está bien formada, y False en caso contario (1,2 puntos)

ejemplo1 = "la casa [grande] esta lejos /distancia >40% y [100 m] de altura "
ejemplo2 = " (4 -2 [6*40]^{65})*{4-(3*5)} "
ejemplo3 = " (4 -2 [6*40]^ {65)} *{4-(3*5)} "

valida3 ejemplo1 pares à True


valida3 ejemplo2 pares à True
valida3 ejemplo3 pares à False -- porque después del 65 hay un ) y no un }

41. Febrero 2017. Fechas. Tema 5.



Se quiere definir un conjunto de funciones que permitan trabajar con fechas, desde el año 1 hasta el año 2500, incluidos los
años bisiestos. Una fecha se representa con un día, mes y año, donde se deben cumplir las restricciones propias de las
fechas:
• los días son números enteros positivos que van desde 1 a, como mucho y dependiendo del mes y el año, va
hasta 28, 29, 30 o 31
• los meses van desde 1 a 12
• los años van desde 1 a 2500.

Para saber si un año es bisiesto, se proporciona en el fichero problema3.hs la función esBisiesto que devuelve True si un
año es bisiesto y False en caso contrario.

1) Definir el tipo Fecha que permita crear las fechas según se indican, utilizar clave para su definición el carácter F y la
función fechaValida tal que dada una fecha indique si es válida, es decir, si cumple todas las restricciones indicadas (1
punto)

fechaValida (F 21 1 2012) à True


fechaValida (F 32 1 2012)à False -- enero no tiene 32 dias
fechaValida (F 31 6 2012) à False -- junio no tiene 31 dias
fechaValida (F 30 22 2012) à False -- no hay mes 22
fechaValida (F 30 2 5000) à False -- no hay año 5000
fechaValida (F 29 2 2010) à False -- 2010 no es bisiesto
fechaValida (F (-1) 2 2011) False -- un dia no puede ser negativo

2) Definir la función hastaFinAnio, tal que dado un dada una fecha devuelva los días que faltan para llegar a fin de año, si
la fecha no es válida dará un error. El dia que se da como parámetro no se cuenta. (1 punto)



22
Ejercicios de Examen. Informática. Haskell. Versión curso 2020/2021


hastaFinAnio (F 1 1 2010) à 364 -- el dia 1 de enero no se cuenta
hastaFinAnio (F 1 1 2012) à 365 -- 2012 es bisiesto, y el dia 1 no se cuenta
hastaFinAnio (F 4 5 1988) à 241
hastaFinAnio (F 4 5 1989) à 241
hastaFinAnio (F 4 15 1988) à Exception: fecha no valida

3) Definir la función entreFechas, tal que dadas dos fechas devuelva los días que hay entre ellas. Se debe tener en cuenta
que (1 punto):
- No se cuenta el día primero, sino a partir de él. Así entre el 1 de enero de 2010 y el 1 de enero de 2011
hay 365 días (porque no contamos el 1 de enero de 2010)
- No se puede utilizar recursividad para implementar esta función. Utilizar listas por comprensión y/o
funciones de orden superior, así como las funciones definidas en los apartados anteriores.
entreFechas (F 1 1 2010) (F 2 1 2011) à 366
entreFechas (F 1 1 2010) (F 1 1 2011) à 365
entreFechas (F 1 1 2011) (F 1 1 2010) à 365 -- igual anterior, distinto orden
entreFechas (F 1 1 2011) (F 2 1 2010) à 364
entreFechas (F 1 2 1988) (F 1 3 1988) à 29 --1988 es bisiesto
entreFechas (F 1 2 1990) (F 1 3 1990) à 28 -– 1990 no es bisiesto
entreFechas (F 1 2 1990) (F 4 3 2015) à 9162

4) Implementar una función fechasNum que reciba una lista de fechas correctas y devuelva aquellas fechas cuya suma de
sus cifras (F 1 2 2010 = 1 + 2+2010 = 2013 -> 2 + 0 +1+3 = 6) sea igual que un parámetro dado. Utilizar para su
implementación funciones de plegado foldr o foldl. (0,5 puntos)

listaE = [ (F 1 2 2010), (F 2 2 2000), (F 5 3 2000), (F 1 4 1900),(F 12 7 1970)]

fechasNum listaE 6 à [F 1 2 2010, F 2 2 2000, F 1 4 1900]

Pista. Es como un filter implementado con foldr

42. Julio 2017. Raiz Cuadrada. Tema 2,3



El cálculo de la raíz cuadrada con “lápiz y papel” se realiza tal y como se indica en la hoja adjunta,
para quien no lo recuerde . Para ello se utilizan únicamente: sumas, restas y productos de números
enteros. Se pide
1) El método indicado, parte de que la persona que resuelve la raíz cuadrada de números de dos cifras
(paso 2 del método explicado en la hoja adjunta) . En nuestro caso, nos lo va a devolver la función
raizEntera.

Definir una función raizEntera tal que dado un número positivo, de dos cifras devuelva el
número entero cuyo cuadrado está más cercano al valor dado. Utilizar listas por comprensión
para resolver este apartado (0,5 puntos)
raizEntera 45 à 6 (36 es el cuadrado menor y más cercano a 45)
raizEntera 49 à 7
raizEntera 48 à 6 (36 es el cuadrado menor, mas cercano a 48, porque aunque
el 49 es más cercano no es menor que 48)

2) Utilizando únicamente las funciones, suma, resta, producto (no utilizar en ningún momento sqrt),
raizEntera y las funciones recursivas que considere necesario implemente una función que devuelva la
raizCuadrada de un número positivo siguiendo el método descrito, devolviendo dos valores, la raíz y el
resto. Para cada función auxiliar, indíquese con una explicación textual entre comentarios, qué realiza,
poniendo un ejemplo de su entrada y salida. (2,2 puntos)
raizCuadrada 123956 à [352,52]
raizCuadrada 25 à [5,0]
raizCuadrada 89224 à [298,420]



23
Ejercicios de Examen. Informática. Haskell. Versión curso 2020/2021


3) Implementar una función quickcheck que permita demostrar la corrección de la función raizCuadrada
del apartado anterior (0,3 puntos)
CALCULO DE LA RAIZ CUADRADA.

1. Agrupamos por parejas empezando a contar desde las unidades
las


2. unidades. Por ejemplo para 125, salen dos parejas 1-25
2.Calculamos la raíz entera de la primera pareja

3. Restamos el cuadrado de 3 a la primera pareja del


radicando (a la izquierda), y un queda un valor – en este
caso, es el 3-



4. Bajamos la siguiente pareja y la unimos al valor
calculado en el caso anterior


5. Multiplicamos por 2 el valor que tenemos en la
parte derecha, y lo apuntamos aparte

6. Buscamos un numero x para los dos huecos de


modo que ese producto sea el mayor posible pero que
no supere al valor que tenemos a la izquierda.
En este caso un numero (6x * x) tal que x tenga una
cifra y el resultado de esa cuenta sea menor que 339.
En este caso el valor seria “5”



7. Subimos el 5 a la parte superior derecha, lo unimos
al numero existente a la derecha.
8. Restamos el producto obtenido de la expresión del
apartado 6m al valor que teníamos a la izquierda, y
nos da 14.


9. Repetimos el proceso con la siguente pareja, y
asi sucesivamente hasta que hayamos usado
todas las parejas.
10. Como resultado se devuelve el valor de la
parte derecha, que es la raiz cuadrada, y el
calculo restante de la parte izquierda, que es el
resto



24
Ejercicios de Examen. Informática. Haskell. Versión curso 2020/2021



43. Julio2017. Collatz. Tema 3 y 4

1) La secuencia de Collatz de un número entero se construye de la siguiente forma:
• si el número es par, se lo divide por dos;
• si es impar, se le multiplica tres y se le suma uno;
• la sucesión termina al llegar a uno.

1.1 Definir una función llamada collatz, tal que dado un número entero devuelva la secuencia
correspondiente, utilizando recursividad normal
collatz 20 à [20,10,5,16,8,4,2,1]
collatz 13 à [13,40,20,10,5,16,8,4,2,1]

1.2 Definir la función cuantosCollatsN que tiene como parámetro de entrada un numero positvo n, y
devuelve cuántas secuencias de collatz entre 1 y 100 tienen una longitud mayor que n.
Implementar la función utilizando alguna función de orden superior (y sin usar recursividad).
cuantosCollatsN 15 à 66
cuantosCollatsN 100 à15

44.Julio2017. Cubos. Tema 3

Entre todos los enteros mayores a 1 hay solamente cuatro que pueden ser representados por la suma de
los cubos de sus dígitos.
n = S xi3 donde x es cualquier numero entre 1 y 500, el numero de xi’s es variable, y son todos los x
son diferentes

Uno de esos números es 153: 13+53+33=1+125+27=153


Implementar la función cubos (que no tiene parámetros) que devuelva una lista con los cuatro números
que cumplen esta condición.

45. Julio 2017. Infija Prefija. Tema 6


Se tienen expresiones matemáticas con las siguientes operaciones para trabajar con números entero
: +,-, * que se corresponden con la suma, resta y , producto. En este ejemplo vamos aconsiderar
únicamente operadores binarios, y vamos a utilizar estos tres tipos de notación (existen otras de
implementar la notación prefija y postfija, pero aquí se considerará esta):
- infija, los operadores van entre los números, y se evalúan de izquierda a derecha
5 + (3 * 4)
-
prefija: todos los operadores van al principio y se aplican por orden: (+ 5 (* 3 4))
-
postfija: todo los operadores van al final y se aplican por orden, según indica el ejemplo (5 (4 3
*) +)
-
1) Definir la función separar tal que dado un string que representa una expresión en notación infija y una
lista de separadores, divida el string en substrings separando por esos separadores, que también se
incluirán en el resultado, y dejando todos los componentes en el mismo orden, es decir, en notación
infija.

separar "2 + 13 - 125 * 4" à ["2","+","3","-","125","*","4"]

2) Tenemos una expresión definida en notación infija con operadores binarios definida como un string y la
queremos convertir a una lista notación prefija y postfija. Para ello se pide definir la función aPrefija y
aPostfija, que conviertan de una notación a la otra respectivamente y devuelvan el resultado como una
lista de strings


25
Ejercicios de Examen. Informática. Haskell. Versión curso 2020/2021



aPrefija "2+13-125*4" ["+","2","-","13","*","125","4"]
aPostfija "2 + 13-125 * 4" ["2","13","125","4","*","-", "+"]

3) Definir la función evaluaPos que evalúen una expresión definidas en notación postfija. Para la
implementación de dichas funciones se debe utilizar la estructura de datos (Pila, Cola, Grafo o Arbol) que
considere más conveniente. Justifique la elección de la estructura de datos con un comentario justo antes
de la definición dela función.

evaluaPos (aPostfija "2+13-125*4") à -485
evaluaPos (aPostfija "3-235*12") à -2818

4) (0,5 p) Definir el tipo de datos ExpresionPre que permita definir expresiones recursivas de sumas,
restas, productos, divisiones anidadas entre paréntesis en notación Prefija). La suma se indicara como
Suma, la resta como Resta, el producto como Prod, y los números enteros con Num. Los paréntesis no
son parte de la definición del tipo, sino que los gestiona el propio lenguaje. Asi, la expresión 5 + (3 * 4)
en el tipo ExpresionPre se escribiría como

e:: ExpresionPre
e = Suma (Num 5)(Prod (Num 3) (Num 4))

46. Septiembre 2017. Juego de la cuerda. Tema 4

El juego de “tirar de la cuerda” es un juego de niños en los que un grupo tira en un sentido y otro en sentido contrario. Gana el
grupo que consigue que el pañuelo rebase la línea señalada en el suelo.

Vamos a simular este juego con dos jugadores, el de la derecha, y otro el de la izquierda. La posición inicial del pañuelo es el 0, y
el movimiento a la izquierda se simula restando un valor a la posición del pañuelo y a la derecha sumando un valor a la posición
del pañuelo. El valor que se suma o se resta se decide con un dado que genera aleatoriamente números entre 1 y 6. El juego se
termina cuando el pañuelo alcanza un valor mayor o igual que 10, o menor o igual que -10.

Veamos un ejemplo, en el que el jugador de la derecha inicia el juego:

• Inicialmente el pañuelo está en la posición 0.


• Ahora el jugador de la derecha tira un dado y sale un 2, el pañuelo queda en la posición 2
• El de la izquierda tira el dado, sale un 3, el pañuelo queda en la posición -1
• El de la derecha tira el dado, sale un 1, el pañuelo queda en la posición 0
• El de la izquierda tira el dado, sale un 6, el pañuelo queda en la posición -6
• El de la derecha tira el dado, sale un 2, el pañuelo queda en la posición -4
• El de la izquierda tira el dado, sale 6, el pañuelo queda en -10
• Como el pañuelo vale -10, el jugador de la izquierda gana

Nombramos al jugador de la derecha como Derecha y al de la izquierda como Izquierda. Para ello definimos el tipo Jugador:
data Jugador = Izquierda | Derecha deriving (Eq, Show)

1) Implementar la función jugar que tiene como entrada el jugador que hace la primera tirada, y la semilla que se usará para
generar los números aleatorios, y devuelva como salida una tupla de dos elementos, el jugador que gana y el número de
jugadas que necesitó para conseguirlo (2 puntos)



26
Ejercicios de Examen. Informática. Haskell. Versión curso 2020/2021


El tipo de la función jugar, donde Semilla es el tipo definido en el paquete Aleatorios, es el siguiente

jugar :: Jugador -> Semilla -> (Jugador, Integer)

Ejemplos
jugar Izquierda 1 à (Derecha,16) -- gana el jugador de la derecha después de 16 jugadas
jugar Izquierda 2 à (Izquierda,13) -- gana el jugador de la izquierda después de 13 jugadas
jugar Izquierda 3 à (Derecha,36) -- gana el jugador de la derecha después de 36 jugadas
jugar Derecha 3 à (Izquierda,36) -- gana el jugador de la izquierda después de 36 jugadas

2) Implementar la función todasJugadas que tiene como entrada el jugador que hace la primera tirada, y la semilla que se usará
para generar los números aleatorios, y devuelva como salida la lista de valores del “pañuelo” hasta llegar al valor final (>=10 o
<=(-10)) (1 punto)

todasJugadas Derecha 3 à
[3,0,1,-1,0,-1,3,-2,0,-2,2,-3,3,-2,2,-3,-2,-6,-1,-3,-1,-2,0,-6,-1,-3,3,-3,0,-6,-3,-9, -8,-9,-6,-10]
todasJugadas Izquierda 1 à
[-4,1,-1,3,0,5,2,7,2,7,5,7,5,9,8,13]

47. Septiembre 2017. La ley d'Hondt. Tema 3.



El sistema d'Hondt es un método de promedio mayor para asignar escaños en sistemas de representación proporcional por listas
electorales. Es el método que se utiliza en España para el reparto de votos en las elecciones oficiales. Explicaremos cómo funciona,
con una versión simplificada de un ejemplo tomado de queaprendemoshoy.com.
Supongamos que en la circunscripción X, a la que corresponden 5 escaños, el resultado de la votación a la que se presentaron 4
partidos A, B, C y D, ha sido el siguiente respectivamente: 258020 votos, 168030 votos, 114040 votos y 60050 votos. El método
de reparto es el siguiente, en el que por simplicidad, vamos a considerar que únicamente se trabaja con números enteros:

i) Se dividen los votos obtenidos por cada candidatura entre 1, 2, 3… hasta completar el número de escaños a repartir, que en este
caso hemos fijado en 5. De este modo, tenemos la siguiente matriz bidimensional con una fila por cada partido (sombreado en esta
tabla)

ENTRADA CALCULOS INTERMEDIOS SALIDA


Votos Escaños
Partidos nº votos/1 nº votos/2 nº votos/3 nº votos/4 nº votos/5
obtenidos obtenidos
Partido A 258020 258020 129010 86006 64505 51604 3
Partido B 168030 168030 84015 56010 42007 33606 1
Partido C 114040 114040 57020 38013 28510 22808 1
Partido D 60050 60050 30025 20016 15012 12010 0

ii) Elegiremos de la tabla los 5 cocientes más altos (casillas en rojo en las columnas de cálculos intermedios), de forma que al
partido A corresponderán tres escaños, al partido B un escaño y al C otro escaño respectivamente. El partido D quedará sin ningún
escaño.

Nota de implementación: Utilizar el tipo Int en lugar del tipo Integer, en este problema

1) Implementar la función fvaloresMasAltos tal que dada una matriz de números enteros todos diferentes y un numero
n, devuelva los n números más altos de esa matriz. (0,5 puntos)

matriz à [[23,21,12,15,24],[14,45,21,34,10],[46,36,124,12,10],[12,33,68,29,1]]
fvaloresMasAltos matriz 5 à[124,68,46,45,36]
fvaloresMasAltos matriz 7 à [124,68,46,45,36,34,33]

2) Implementar la función buscaPosicion que recibe como entrada un elemento y una matriz, y devuelve la posición (x, y)
que ocupa ese elemento en la matriz. Se puede suponer que todos los elementos de la matriz son diferentes. Si no encuentra
el elemento, la función devolverá [0,0]. Implementar la función con recursividad(1punto)
matriz à [[23,21,12,15,24],[14,45,21,34,10],[46,36,124,12,10],[12,33,68,29,1]]
buscaPosicion matriz 23 à (1,1)
buscaPosicion matriz 45 à (2,2)
buscaPosicion matriz 68 à (4,3)
buscaPosicion matriz 99 à (0,0) – no está en la matriz



27
Ejercicios de Examen. Informática. Haskell. Versión curso 2020/2021


3) Implementar la función matrizDhont que recibe la lista de partidos y votos y el de puestos a repartir, y devuelve una
lista de lista de enteros que se corresponde con la tabla de votos repartidos (la tabla gris del ejemplo). Resolver esta
función aplicando listas por comprensión (0,5 puntos)
matrizDhont [("A",258020),("B",168030),("C",114040),("D",60050)] 5 à
[[258020,129010,86007,64505,51604], [168030,84015,56010,42008,33606],
[114040,57020,38013,28510,22808],[60050,30025,20017,15012,12010]]

4)Utilizando las funciones anteriores y las que considere necesarias, implemente la función reparto que dados los
resultados de una votación y el número de puestos a repartir, devuelva la asignación de escaños, según el algoritmo
anterior. Así para el ejemplo descrito, devolvería (1 punto)
reparto [("A",258020),("B",168030),("C",114040),("D",60050)]5
à[("A",3),("B",1),("C",1),("D",0)]

reparto [("A",258020),("B",168030),("C",114040),("D",60050)] 6 à [("A",3),("B",2),("C",1),("D",0)]

reparto [("A",258020),("B",168030),("C",114040),("D",60050)] 2 à [("A",1),("B",1),("C",0),("D",0)]



48. Septiembre 2017. Palíndromo. Temas 3.

Partiendo de cualquier número expresado en base 10, se puede obtener un palíndromo con el siguiente algoritmo
- Dado un número, lo sumamos a su reverso.
- Si esta suma es un palíndromo, entonces paramos;
y si no, repetimos el proceso con el número obtenido de dicha suma, hasta dar con un palíndromo.
Ejemplo:

n=59 n=15 n=60


59 154 605
nà59 à à à 1111
95 451 506
suma 154 605 1111
Escriba la función aPalindromo tal que dado un número n devuelva la lista sucesiva de números hasta que se construye un
palíndromo, según el algoritmo indicado. En la solución se valorará la calidad y lógica en modularización de la solución,
utilizando funciones auxiliares. Indíquese con un comentario el objeto de cada función, cuál es la entrada y cuál es la salida, de
forma descriptiva y con un ejemplo.

Ejemplo de salida:
aPalindromo 59 à [59,154,605,1111]

Nota de implementación. No se puede utilizar la función show


49. Febrero 2018. El número PI. Temas 4
El número pi puede calcularse de muchas maneras. En este problema vamos a resolverlo con series infinitas, según las
propuestas de dos matemáticos famosos.

1) Según la fórmula de Gregory-Leibniz, sumando los términos formados al tomar cuatro, luego restar cuatro y dividir
entre tres, luego sumar y dividir entre 5..... Mientras más sumandos se añaden, más se acercará el resultado al valor de pi

π = (4/1) - (4/3) + (4/5) - (4/7) + (4/9) - (4/11) + (4/13) - (4/15) ...

Se pide:
1.1. Implementar la función spiLeibnizt que devuelva la lista infinita con los términos de esta serie. Usar funciones de
orden superior

take 10 spiLeibnitz à
[4.0,-1.3333333333333333,0.8,-0.5714285714285714,0.4444444444444444,-
0.36363636363636365,0.3076923076923077,-0.26666666666666666,0.23529411764705882,-0.21052631578947367]

1.2 Implementar la función piLeibnizt que devuelva el número pi correspondiente calculado con n términos de la serie.

piLeibnitz 100 à 3.1315929035585537
piLeibnitz 1000 à 3.140592653839794



28
Ejercicios de Examen. Informática. Haskell. Versión curso 2020/2021



2) (1,5 puntos) Por su parte Euler demostró es la multiplicación de la serie de todos los valores p2/(p2-1) siendo p un
número primo (2, 3, 5, 7, 11...) Expresado numéricamente equivale a:

22/(22-1) * 32/(32-1) * 52/(52-1) * 72/(72-1) * ... = π2/6

que es lo mismo que 4/3 * 9/8 * 25/24 * 49/48 *... = π2/6

2.1. (0,5 p)Implementar la función primos que devuelva una lista infinita de números primos. Utilizar recursividad
take 10 primos à [2,3,5,7,11,13,17,19,23,29]

Nota de implementación. Al hacer la división si da error, colocar delante de divisor y/o dividendo la función fromIntegral: fromIntegral a /
fromIntegral b


2.2 Implementar una función spiEuler que devuelva una lista infinita de cada uno de los productos de la formula de Euler,
es decir los valores p2/(p2-1), siendo p un número primo. Utilizar en la definición de la función alguna lista por
comprensión
take 10 spiEuler à
[1.3333333333333333,1.125,1.0416666666666667,1.0208333333333333,1.0083333333333333,1.005952380952381,1.003
4722222222223,1.0027777777777778,1.0018939393939394,1.0011904761904762]

2.2. Implementar la función piEuler que dado un número n devuelva un valor para el número pi resultante con n
elementos de la serie la lista devuelta por la función del apartado anterior, y las operaciones necesarias, según la fórmula
de Euler.
piEuler 100 à 3.1411926604946983
piEuler 1000 à 3.141572703000528

50. Febrero 2018, Codificar. Temas 2 y 3

Tenemos un mensaje escrito como una cadena de caracteres que se va a compartir en una red social. El mensaje se quiere encriptar
antes de su envío, y para leerlo, el receptor lo desencriptará y para ello tendrá en su equipo el código necesario para ello.

El algoritmo de encriptado es el siguiente. La entrada son dos valores:
• mensaje m: un string que contiene un mensaje no vacío, sin espacios al principio y al final y con las palabras
separadas únicamente por un espacio
• numero n: número positivo, menor que la longitud del mensaje menos uno

ALGORITMO
m = “mas vale poco que nada”
n= 4
1. Separar el mensaje en su lista de sus palabras:
[“mas”, “vale”,”poco”,”que”, “nada”]
2. Contar las letras de cada palabra:
[3, 4, 4, 3, 4]
3. Unir todas las palabras:
”masvalepocoquenada”
4. Se reagrupan las letras según el tamaño indicado con el parámetro n. Por ejemplo, si vale 4:
[”masv”, “alep”, “ocoq”, “uena”, “da”]
5. Le damos la vuelta a cada palabra
[”vsam”, “pela”, “qoco”,”aneu”, “ad”]
6. Unir todas la palabras
[”vsampelaqocoaneuad”]
7. Se reagrupan tal como indica la inversa de la lista del paso 2, es decir, [4, 3, 4, 4, 3]
[”vsam”,”pel”, “aqoc”, “oane”, “uad”]

8. Se crea una frase con los espacios. Ese es el mensaje codificado: "vsam pel aqoc oane uad"



29
Ejercicios de Examen. Informática. Haskell. Versión curso 2020/2021

Se pide

1) Implementar la función formatear que recibe como entrada un string y lo devuelve formateado para que sea válido
para su codificación. Implementar esta función con recursividad con acumuladores:
• Le quita los espacios del principio y del final , si los hubiere
• Quita los espacios entre palabras que sean mayores que un espacio

formatear " era una noche muy fria " à "era una noche muy fria"
formatear "mas vale tarde que nunca " à "mas vale tarde que nunca"
formatear " " à ""
formatear " x f" à "x f"
formatear "En esos casos, se dice no. " à "En esos casos, se dice no."

2) Función codificar que recibe como entrada un mensaje, lo formatea con la función anterior y luego aplica el
algoritmo descrito. Como resultado devuelve un nuevo mensaje codificado.
codificar "mas vale poco que nada" 4 à "vsam pel aqoc oane uad"
codificar "mas vale poco que nada" 5 à "avsa mco peln euqo ada"
codificar "esto es un ejemplo" 10 à "jenuseo ts eo lpme"
codificar " " 4 " à *** Exception: el mensjae está vacio *
codificar "la casa es verde" 120 " ..> *** Exception: n debe ser menor que la longitud del
mensaje formateado menos uno

51. Febrero 2018. El tren. Tema 5

Un tren está compuesto de una locomotora principal y un número arbitrario de locomotoras auxiliares y de vagones de
pasajeros y mercancías.
• Cada locomotora (principal o auxiliar) tiene potencia para arrastrar cierta cantidad de kilogramos.
• La potencia de arrastre total de un tren es la suma de las potencias de las locomotoras que lo componen.
• Cada vagón de mercancías lleva una carga en kilogramos. Cada vagón de pasajeros está ocupado por cierto
número de pasajeros (asumiremos que cada pasajero pesa 100 Kg.).

En Haskell, un tren se puede representar por el siguiente tipo algebraico:

data Tren = Principal Int -- kilos que puede arrastrar


| Auxiliar Int Tren -- kilos que puede arrastrar
| Pasajeros Int Tren -- cantidad de pasajeros (100 Kg. por pasajero)
| Mercancias Int Tren -- peso de la mercancia en Kg.
deriving Show

Los siguientes son ejemplos dos trenes:

chuchu :: Tren
chuchu = Pasajeros 28 (Pasajeros 17 (Mercancias 800 (Mercancias 1200 (Auxiliar 2500 (Principal 4000)))))

tracatra :: Tren
tracatra = Pasajeros 28 (Mercancias 800 (Pasajeros 17 (Auxiliar 2000 (Mercancias 1200 (Principal 4000)))))

pesoPasajero :: Int
pesoPasajero = 100

Nota. La definicion de tipo y las variables Tren ya están tecleadas en el fichero prob3.hs en el fichero que había que descargar del campus.

1) Definir una función puedeArrastrar que dado un tren devuelve 'True' si puede arrastrar los vagones de pasajeros y
mercancías enganchados y 'False' en caso contrario.
puedeArrastrar chuchu à True
puedeArrastrar tracatra à False



30
Ejercicios de Examen. Informática. Haskell. Versión curso 2020/2021


2) Definir una función asegurarArrastre que dado un tren añada, solo si es necesario, una locomotora auxiliar con la
potencia mínima para asegurar que se puede arrastrar toda la carga. La locomotora auxiliar debe quedar enganchada a la
principal.
asegurarArrastre chuchu
à Pasajeros 28 (Pasajeros 17 (Mercancias 800 (Mercancias 1200 (Auxiliar 2500 (Principal 4000)))))

asegurarArrastre tracatra
à Pasajeros 28 (Mercancias 800 (Pasajeros 17 (Auxiliar 2000 (Mercancias 1200 (Auxiliar 500 (Principal
4000))))))

2) Definir una función unirAuxiliares que dado un tren reemplace todas las locomotoras auxiliares por una única con la
suma de las potencias de las auxiliares reemplazadas.
i. La única locomotora auxiliar debe aparecer enganchada a la locomotora principal, y su nueva potencia
será la que tenía mas la suma de todas las axiliares del tren.
ii. Puede darse la situación de que debido a la unión de las auxiliares la suma de éstas sea mayor que la
principal, situación que no debería darse. En ese caso, la potencia de la auxiliar se intercambia con la
de la principal (véase el último ejemplo)
unirAuxiliares chuchu
à Pasajeros 28 (Pasajeros 17 (Mercancias 800 (Mercancias 1200 (Auxiliar 2500 (Principal 4000)))))

unirAuxiliares tracatra
à Pasajeros 28 (Mercancias 800 (Pasajeros 17 (Mercancias 1200 (Auxiliar 2000 (Principal 4000)))))

unirAuxiliares (Auxiliar 1 (Auxiliar 2 (Mercancias 3 (Auxiliar 40 (Pasajeros 5 (Principal 6)))))) à


Mercancias 3 (Pasajeros 5 (Auxiliar 6 (Principal 43)))


52. Julio 2018. Sustituir elementos lista. Tema 3.

Implementar, utilizando recursividad, la función sustituirSumando que tiene como entrada una lista de enteros y
devuelve como salida el resultado de reemplazar todos los pares de valores consecutivos iguales a x por la suma de
ambos. El proceso se repite con todas las listas obtenidas hasta que no haya ningún par de números consecutivos iguales.

Para entenderlo mejor, el proceso se describe por pasos. Es importante ver, que cuando se hace la primera sustitución
se repite el proceso con el resto de la lista sin procesar (se pone en negrita en el ejemplo):
[6, 3, 1, 1, 3, 3, 2, 1, 1]
[6, 3, 2 3, 3, 2, 1, 1]
[6, 3, 2, 6, 2, 1, 1]
[6, 3, 2, 6, 2, 2] --- comprobar que no hay sucesivos iguales
[6, 3, 2, 6, 4]
à [6, 3, 2, 6, 4]


Ejemplos
sustituirSumando [6, 3, 1, 1, 3, 3]à [6,3,2,6]
sustituirSumando [7, 3, 1, 1, 2, 2] à [7,3,4,2]
sustituirSumando [6, 3, 1, 1, 3, 3, 2, 1, 1] à [6,3,2,6,4]
sustituirSumando [6, 3, 1, 1, 3, 3, 2, 1, 1, 4] à[6,3,2,6,8]

53. Julio 2018. Anagramas. Temas 3 y 4.



Dos palabras son anagramas si están compuestas de las mismas letras en distinto orden. Por ejemplo, "sordo"" y "dorso"
son anagramas.
Para comprobar si dos palabras son anagramas podemos aplicar el siguiente algoritmo:
1) asociar a cada letra del alfabeto un único número primo
2) para cada palabra, calcular el producto de los primos que corresponden a sus letras
3) si el producto es el mismo, las palabras son anagramas
Implementar la función sonAnagramas tal que dadas dos cadenas de caracteres devuelva True si son anagramas y
false en caso contrario, utilizando el algoritmo descrito anteriormente . Utilizar funciones de orden superior para la
implementación.



31
Ejercicios de Examen. Informática. Haskell. Versión curso 2020/2021


sonAnagramas “sordo” “dorso” à True
sonAnagramas “sordo” “cardo” à False
sonAnagramas “camelia” “micaela” àTrue

54. Julio 2018. Hamming. Tema 6.


Los números de Hamming forman una sucesión estrictamente creciente de números no repetidos:
• El número 1 está en la sucesión, y es el primero
• Si x está en la sucesión, entonces 2x, 3x y 5x también están.
• Ningún otro número está en la sucesión.

Así los doce primeros números de la sucesión son 1,2,3,4,5,6,8,9,10,12,15,16...
Una sucesión de Hamming se puede implementar con tres colas, una para generar los 2x, otra para generar los 3x y otra para
generar los 5x. Para ello, se puede seguir el siguiente algoritmo:

1. Inicializamos la secuencia de haming a []


2. Se definen tres colas, que llamaremos q2, q3 y q5 y las inicializamos con el número 1 cada cola
(encolar el número 1 en cada una de ellas)
3. Repetir el siguiente proceso indefinidamente
a. Mirar cual es el primer elemento de cada cola
b. Calcular el mínimo de los tres elementos del apartado 3a, que llamaremos x
c. Encolar 2x, 3x y 5x a las colas q2, q3 y q5 respectivamente
d. Si x está en alguna de las colas, quitarlo de la cola (es decir, desencolar si está)
e. Apuntar x en la secuencia de hamming
Se pide:
3.1 Implementar la función polimórfica quita, tal que dado un elemento y una cola, quite el elemento x si éste es el
primero de la cola, y si no está la deja tal cual
quita 2 (C.mete 5 (C.mete 1 (C.mete 2 C.vacia))) {1 < 5} -- el 2 está
quita 3 (C.mete 5 (C.mete 1 (C.mete 2 C.vacia))) {2 < 1 < 5} -- el 3 no está

3.2 Implementar la función hamming, que no tiene parámetros, que devuelva una lista infinita de números de la serie
de haming según el algoritmo descrito en este enunciado. Para ello utilizar la librería Colas.hs
take 15 hamming à [1,2,3,4,5,6,8,9,10,12,15,16,18,20,24]

55. Julio 2018. Grafo bidireccional etiquetado. Temas 5 y 6



Se tiene un grafo bidireccional etiquetado con un peso entre cada par de nodos, que indica el coste
para ir de un nodo a otro. Un arco entre dos nodos quiere decir que se puede ir de uno a otro en
ambos sentidos. Por ejemplo, el grafo de la figura se representa en Haskell:

type Peso = Float


type Nodo = Integer
type Arco = (Nodo, Nodo, Peso)
type Grafo = [Arco]

grafo2:: Grafo
grafo2 = [ (1, 2, 10.0), (1, 3, 50.0),
(1, 5, 20.0), (3, 4, 60.0), (3, 6, 6.0),
(4, 6, 15.0), (5, 3, 2.0)]

1) Implementar la función sucesores tal que dado un nodo devuelva sus sucesores ordenados de menor a mayor peso.
Implementar con listas por comprensión.

sucesores grafo2 1 à [(2,10.0),(5,20.0),(3,50.0)]


sucesores grafo2 3 à [(5,2.0),(6,6.0),(1,50.0),(4,60.0)]

2) Implementar la función caminoProf, que utilice la función sucesores definida en el apartado anterior, y que tiene tres
parámetros, el grafo, un nodo inicial y un nodo final. La función devuelve el primer camino resultante de hacer una búsqueda en
profundidad. Suponed, que todos los nodos del grafos son alcanzables desde el nodo inicio, es decir, siempre hay un camino
posible.

caminoProf grafo2 1 4 à [1,5,3,6,4]



32
Ejercicios de Examen. Informática. Haskell. Versión curso 2020/2021


caminoProf grafo2 6 2 à [6,3,5,1,2]

3) Dado un camino, implementar una función costeCamino que devuelva el coste de ese camino, es decir, el coste para ir desde
el nodo inicial al nodo final.

camino1 == [1,5,3,6]
costeCamino camino1 grafo2 à 28.0


56. Septiembre 2018. Números de kaprekar. Tema 3

Un número de Kaprekar es un número entero no negativo tal que los dígitos de su cuadrado se pueden separar en dos
números que sumados dan el número original.
El número 297 es un número de Kaprecar:

- El cuadrado del número 297 es 88209
- Si comprobamos todas las posibles separaciones en dos números y su correspondiente suma vemos que una
de ellas coincide con el original:
8 + 8209 = 8217 es diferente de 297
88 + 209 = 297 = 297 à Es número de Kaprekar
882 + 09 = 891 es diferente de 297
8820 + 9 = 8829 es diferente de 297

El número 345 no es número de Kaprekar:
- El cuadrado es 119025
- Comprobamos las sumas de las posibles separaciones y vemos que ninguan coincide don el original
1 + 19025 = 19026 diferente de 345
11 + 9025 = 9036 diferente de 345
119 + 025 = 144 diferente de 345
1190 + 25 = 1215 diferente de 345
11902 + 5 = 11907 diferente de 345 à No es número de Kaprekar

Queremos definir la la función esKaprekar que devuelva True si el número es de Kaprekar y False en caso contrario
esKaprekar 297 à True
esKapreKar 345 à False

1) Implementar con recursividad normal (esKaprekar1)


2) Implementar con funciones de orden superior (sin plegado y desplegado) (esKaprekar2)
3) Implementar con plegado y desplegado (esKaprekar3)


57. Septiembre 2018. Lista Cuadrados. Temas 2 y 4
El cálculo de la cuartas potencias de números se puede realizar utilizando el método propuesto por Dov Juzuk en 1939:
i. Se parte de una lista infinita de números 1, 2, 3, 4, ....
ii. Se agrupan tomando un elemento, dos tres, cuatro
[ [1], [2, 3], [4, 5, 6], [7, 8, 9, 10], [11, 12, 13, 14, 15] ....
iii. Se seleccionan los elementos de las posiciones impares
[ [1], [4, 5, 6], [11, 12, 13, 14, 15], ....
iv. Sumamos los elementos de cada grupo
[ 1 , 15, 65...
v. Calculamos las sumas acumuladas
[1, 16, 81, ...
La lista resultante es una lista infinita de cuadros de los números enteros desde 1.
Definir la función cuartasPotencia que devuelva una lista infinita de cuartas potencias de números enteros siguiendo el
algoritmo descrito. Resolver el problema con listas por comprensión, y funciones de orden superior.

take 10 cuartasPotencias à [1,16,81,256,625,1296,2401,4096,6561,10000]



33
Ejercicios de Examen. Informática. Haskell. Versión curso 2020/2021


58. Septiembre 2018. Grafo bidireccional 1. Temas 5 y 6

Se tiene un grafo bidireccional etiquetado con un peso entre cada par de nodos, que indica el
coste para ir de un nodo a otro. Un arco entre dos nodos quiere decir que se puede ir de uno
a otro en ambos sentidos. Por ejemplo, el grafo de la figura se representa en Haskell:

type Peso = Float


type Nodo = Integer
type Arco = (Nodo, Nodo, Peso)
type Grafo = [Arco]

grafo2:: Grafo
grafo2 = [ (1, 2, 10.0), (1, 3, 50.0),
(1, 5, 20.0), (3, 4, 60.0), (3, 6, 6.0),
(4, 6, 15.0), (5, 3, 2.0)]

También se ha definido el tipo recursivo Arbol
data Arbol a = Vacio | N a [Arbol a] deriving Show

1) Implementar la función arbolDe tal que dado un grafo g y un nodo n construya el árbol resultante todas las ramas
posibles con todos los nodos que se pueden alcanzar desde el nodo y en el grafo g. Así, para el grafo del ejemplo y el nodo
1 se puede construir el árbol de la figura (1,5 puntos)
arbolDe grafo2 1 à
N 1
[N 2 [],
N 5 [N 3 [N 6 [N 4 []], N 4 [N 6 []]]],
N 3 [N 5 [],N 6 [N 4 []],N 4 [N 6 []]]
]

2) Suponiendo que tenemos la variable arbol2 con el resultado de la función anterior
Implementar la función costeRamas que dado un grafo y un nodo de ese grafo, construya el árbol que se puede generar
a partir de ese nodo de entrada utilizando la función anterior, y a partir de ese árbol calcule la de todas sus ramas, y el
coste de cada rama. Definir las funciones auxiliares que considere necesarias (1,5 puntos)
costeRamasArbol grafo2 1
à[([1,2],10.0),
([1,5,3,6,4],43.0),([1,5,3,4,6],97.0),
([1,3,5],52.0),([1,3,6,4],71.0),([1,3,4,6],125.0)]

59. Febrero 2019. Alternada. Tema 2 y 3


Dada una lista de números enteros mayores que cero (es decir, el cero nunca forma parte de la lista), se dice que es
alternada si son alternadamente par/impar o impar/par. Por ejemplo

esAlternada [1, 2, 3, 4] à True


esAlternada [1, 1, 2, 3, 1] à False
esAlternada [4, 7, 13, 12, 25, 102] à False
esAlternada [1] à True
esAlternada [2] à True

1) Definir la función esAlternada1 sólo con recursividad normal y funciones predefinidas que no sean funciones de
orden superior (0,5 puntos)
2) Definir la función esAlternada2 solo con listas por comprensión y funciones predefinidas (0,5puntos)
3) Definir la función esAlternada3 con plegado y desplegado (0,5 puntos)
4) Definir la función esAlternadaP, función que tiene como entrada una lista y dos dos predicados p1 y p2, devuelve
True si todos los elementos verifican alternadamente uno y otro predicado (p1/p2 o p2/p1). Implementarlo por la
técnica que se quiera. (0,5puntos)
Ejemplo:
esAlternadaP [1, 2,3, 4, 5, 5] even odd àFalse
esAlternadaP [1, 2,3, 4, 5, 5] odd even àFalse
esAlternadaP [1, 2,3, 4, 5, 6] even odd à True
esAlternadaP [1, 2,3, 4, 5, 6] odd even à True
esAlternadaP [1,10, 2, 20, 3, 20, 4, 40, 5] (<10) (>=10) àTrue
esAlternadaP [1,10, 2, 20, 3, 20, 4, 40, 500] (<10) (>=10) àFalse

5) Definir tres propiedades esAlternada_propi (donde i es 1, 2, 3), para comprobar con quickchek las funciones
esAlternada1, esAlternada2 y esAlternada3 (0,5 puntos)


34
Ejercicios de Examen. Informática. Haskell. Versión curso 2020/2021



60. Febrero 2019. El tipo Polinomios. Tema 5
Se ha definido el tipo polinomio como una lista de números donde la posición del elemento de la lista indica el
grado del mismo de mayor a menor exponente.

data Polinomio a = P [a] deriving (Eq, Show)

Así por ejemplo, el polinomio x2 + 2x +3 se escribiría en este tipo como polinomio1= P [1, 2, 3] y 4x3
+ 2x2 + 5 se escribiría como polinomio2 = P [4, 2, 0, 5].

Se pide:
1) Definir las funciones sumaP y restaP que dados dos polinomios devuelva su suma y su resta respectivamente
(0,5 puntos)
sumaP (P [3, 2, 1, 0, 6]) (P [1, 3, 2,1]) à P [3,3,4,2,7]
sumaP (P [1, 0, 6]) (P [1,1, 1, 1, 1, 1])à P [1,1,1,2,1,7]
sumaP (P [1, 0, 6]) (P []) à P [1,0,6]
restaP (P [3, 2, 1, 0, 6]) (P [1,1])à P [3,2,1,-1,5]

2) Definir la función productoP que dados dos polinomios devuelva el producto de los dos polinomios (1 punto)
productoP (P [5,0,0,0]) (P [4, 3, 7]) à P [20,15,35,0,0,0]
productoP (P[2,1]) (P[4,3]) à P[8,10, 3]
productoP (P[2,1]) (P[4,3,2,1]) à P[8, 10, 7, 4, 1]

3) Definir la funcion derivaP tal que dado un polinomio devuelva su primera derivada (0,5 puntos)
derivaP (P[2, 1, 3, 2]) à P [6,2,3]
derivaP (P [2, 1, 0]) à P [4,1]
derivaP (P [2, 1, 0, 4, 1])à P [8,3,0,4]
derivaP (P [4, 1]) à P [4]
derivaP (P [2]) à P [0]

61. Febrero 2019. Un juego de números. Temas 3 y 5

Luis y Juan juegan a un juego muy sencillo que los tiene muy entretenidos:
1) Al inicio de una partida, ambos eligen varios números positivos menores que 100, por ejemplo tres números,
Luis: 4 7 12 Juan : 3 7 8
2) Deciden con una moneda, quien es el primero en jugar. Por ejemplo, el primero es Luis.
3) Después los ponen todos seguidos, 4712378, primero los de Luis y después los de Juan.
4) Ahora juegan por turnos, y tal y como se decidió en el paso 2, empieza Luis. En cada turno, se va sumando 1 a los
números y se ponen todos seguidos. Si ahora se genera un dígito más, el jugador que ha sumado en ese turno gana un
punto. En el ejemplo:
4.1 Luis suma 1 a cada número de forma que el 4 se convierte en 5, el 7 en 8, el 12 en 13, etc. Al ponerlos de
nuevo todos juntos queda: 5813489. Si el número del paso 3 tiene un dígito más este número, se anota un punto
para Luis, sino no se hace nada. Como el número de dígitos es siete en ambos casos, no se hace nada.
4.2. Ahora le toca a Juan que suma 1 a cada numero (por separado), luego los junta el siguiente turno le toca al
siguiente, que vuelve a sumar uno a cada número, se junta y ahora sale 69145910. Ahora 69145910 tiene un
dígito mas que 5813489, entonces se anota un punto para Juan.

Se repite el paso 4 un número de veces, por ejemplo 10. Este sería el resultado

Luis [4, 7, 12] Juan [3, 7, 8]


4712378
1 Luis : 5813489 -- contado en el apartado 4.1
2 Juan: 69145910 // Al sumar 2, Juan gana un punto -– contado en el apartado 4.2
3 Luis : 7101561011 // Al sumar 3, Luis gana un punto
4 Juan : 8111671112
5 Luis : 9121781213
6 Juan : 10131891314 // Al sumar 6, Juan gana un punto
7 Luis : 111419101415 // Al sumar 7, Luis gana un punto
8 Juan : 121520111516
9 Luis : 131621121617
10 Juan : 141722131718



35
Ejercicios de Examen. Informática. Haskell. Versión curso 2020/2021


En este caso el resultado final es 2 puntos para Juan, y 2 puntos para Luis. Es decir, Empate.

1) Implementar la función partidaResumida que recibe como entrada dos listas de n números, una por cada jugador, el
número de veces que se juega, y el número del jugador que empieza (1 para el primero, 2 para el segundo) . Como resultado
devuelven la lista de números que se van generando (considerando sólo los que hacen cambiar el número de cifras, y
alguno de los jugadores puntúa: son los que están marcados en negrita en el ejemplo anterior, donde 1 es Luis y 2 es Juan)
y el numero del jugador que ha puntuado. (1,5 puntos)

Para el ejemplo explicado anteriormente, donde Luis es el 1 y Juan es el 2:


partidaResumida [4,7, 12] [3, 7, 8] 10 1 à
[(69145910,2),(7101561011,1),(10131891314,2),(111419101415,1)]

Se pueden utilizar las siguientes funciones
show entero à pasa un entero a string; read string::Integer à pasa un string a entero

2) Definir un tipo llamado Resultado que diga quien gana una partida o – si no ganara nadie – que empata. Definir una función
quienGana que dada una lista de jugadas de una partida (resultado de la función anterior) diga cual es el resultado de la
partida (1 punto)

quienGana (partidaResumida [4,7, 12] [3, 7, 8] 10 1) à Empate
quienGana [(69145910,2),(7101561011,1),(10131891314,2),(111419101415,1)]à Empate

quienGana (partidaResumida [54, 86, 3, 67] [1, 21, 3, 99] 10 2) à Gana 2


quienGana (partidaResumida [54, 86, 3, 67] [1, 21, 3, 99] 10 1) à Gana 1

3) Se pide, utilizando el módulo Mates.Aleatorios, implementar una función unaPartida que recibe como entrada una semilla,
un número n que indica con cuantos números juegan los jugadores, y otro que indica el número de jugadas que juegan.
Para seleccionar los números del primer jugador se tomarán los n primeros números de la lista de números aleatorios
generados, y los siguientes n para el segundo jugador. Utilizando la misma semilla se decidirá, al azar, quien empieza la
partida. (1 punto)

unaPartida 1 3 10 à [(1932231005717,2)] -- semilla= 1 , numero cifras= 3, numero de jugadas=10
unaPartida 3 4 10 à [(58100598786982996,2),(601026189881003198,2)]
unaPartida 5 2 100 à
[(53106241,1),(914810079,1),(1005710988,2),(11269121100,2),(143100152131,1)]
unaPartida 1 2 100 à
[(193223100,2),(8710091168,2),(96109100177,1),(100113104181,1)]


62. Julio 2019. Fracciones continuas . Tema 3, 4 y 5
Una fracción ordinaria se puede expresar como una fracción continua, en la que todos los números son enteros.
En Haskell, una fracción continua puede expresarse como una lista de números, en este ejemplo [3, 1, 2, 2, 4, 2].

a b sumando Próxima fracción


1280 345 3 (i) 345/245 (iii)
345 245(ii) 1 245/100
En la tabla, 245 100 2 100/45
pueden verse 100 45 ..... ....
los sucesivos
valores que (i) div a b = div 1280 345 = 3
(ii) a - sumando *b = 1280 – (3 *345) = 1280 – 1035 = 245
se van (iii) a / “resultado de (ii)” = 345 / 245
calculando
para generar la fracción continua, en tres iteraciones. El primer sumando
izquierdo es el cociente entero resultante de dividir el numerador por el
denominador (1280 entre 345 = 3, en la primera línea de la tabla ejemplo). Obtenemos ahora un nuevo
denominador, con la diferencia entre el numerador y el producto del sumando izquierdo obtenido por el antiguo
denominador (1280 – (3 * 345) = 245, en la primera línea de la tabla ejemplo, marcada con ii). Habría ahora que
repetir el mismo proceso con la fracción cuyo numerador es el antiguo denominador y cuyo denominador es el
que acabamos de calcular (345/245, en la primera línea de la tabla ejemplo, marcadacon iii). Repitiendo este
proceso, podemos obtener los distintos sumandos izquierdos.

1) Implementar la función fcontinua_de que recibe como entrada una fracción ordinaria como dos números enteros
donde el primero es el numerador y el segundo es el denominador. La función devuelve como salida la fracción
continua correspondiente como una lista (1p). Utilizar recursividad

fcontinua_de 1280 345 à [3,1,2,2,4,2] -- es la del ejemplo de arriba



36
Ejercicios de Examen. Informática. Haskell. Versión curso 2020/2021


fcontinua_de 1000 24 à [41,1,2]
fcontinua_de 245 100 à [2,2,4,2]

2) Utilizando plegado y desplegado definir la función valor_fcontinuaFold que reciba como entrada una función
continua como una lista y devuelva como resultado el número real resultante de evaluarla. (1,5 p)
NOTA DE IMPLEMENTACIÓN. Se puede hacer antes, si es de utilidad (no se contabilizará en la nota), una función como fcontinua_de pero
implementada con acumuladores, y luego hacer el plegado.

valor_fcontinuaFold [3,1,2,2,4,2] à 3.710144927536232


valor_fcontinuaFold [2,2,4,2] à 2.45

3) Definir el tipo de datos FraccionOrdinaria que permita representar una fracción ordinaria.
Definir un tipo de datos FraccionContinua recursivo que permita representar una fracción continua (no es un tipo
lista, como en los apartados anteriores, es un tipo recursivo). Definir una variable de cada tipo, utilizando alguno de los
ejemplos de este apartado (0,5 puntos)

4) Definir la función deContinuaOrdinaria que recibe como entrada una variable de tipo FraccionContinua y devuelve
como resultado una variable del tipo fraccionOrdinaria equivalente. Para comprobar la solución, se puede definir el
predicado esEquivalente (la definición de esta función no se puntúa), que dadas dos fracciones ordinarias nos diga si
son equivalentes o no (1,5 p).

esEquivalente (256,69) (1280, 345) à True


esEquivalente (167,45) (1280,345) à False

Una solución posible es que si la entrada es la función continua del ejemplo devuelva la fracción ordinaria 256/69
que es equivalente a 1280/345. Tanto en la entrada como en la salida se debe utilizar la representación y el tipo
elegida por el estudiante cuando definió los tipos, en el apartado anterior.

63. Julio 2019. Ampliando las funcionalidades de las Pilas . Tema 6
Se quiere ampliar el modulo Pilas.hs con las siguientes funciones.

pila1 = foldr mete vacia [1,2,3,3,4,5, 34, 5, 6, 9, 2, 5, 5, 2, 2]


pila 1 à {1 > 2 > 3 > 3 > 4 > 5 > 34 > 5 > 6 > 9 > 2 > 5 > 5 > 2 > 2}

1) lengthPila: función que recibe como entrada una pila y devuelve el número de elementos de la pila
lengthPila pila1 à 15

2) nubPila: función que quita todos los repetidos de una pila de números enteros. Como los números no tienen que estar
ordenados, la función se queda con el primer numero que aparece en la pila (más arriba).
nubPila pila1 à {1 > 2 > 3 > 4 > 5 > 34 > 6 > 9}

3) filterPila: función de orden superior que recibe con entrada una pila y un predicado, y devuelve como resultado a
los elementos que verifican el predicado , en el mismo orden
filterPila (>5) pila1 à {34 > 6 > 9}
filterPila (odd) pila1 à {1 > 3 > 3 > 5 > 5 > 9 > 5 > 5}

4) alternandoF1F2Pila: función de orden superior que tiene como parámetros una pila y dos funciones f1 y f2, y aplica
alternadamente f1 a un elemento y f2 al siguiente y apila el resultado en la misma pila
alternandoF1F2Pila (*10) (*100) pila1 à
{10 > 200 > 30 > 300 > 40 > 500 > 340 > 500 > 60 > 900 > 20 > 500 > 50 > 200 > 20}

64. Julio 2019. El 46 . Tema 3,4


Empezando con 46 se forma una secuencia de dígitos colocando en cada paso, a continuación del ultimo número escrito,
el producto de los dos últimos dígitos que se escribieron. Así el siguiente al 46 es 4624; el siguiente es 46248.. .. y así
sucesivamente
3.1. Implementar la función despues46 que devuelva una lista infinita con toda la secuencia de números. Utiliza
todas las funciones auxiliares que consideres necesarias. (1 punto)
take 5 despues46 à [46,4624,46248,4624832,46248326]



37
Ejercicios de Examen. Informática. Haskell. Versión curso 2020/2021


take 10 despues46 à
[46,4624,46248,4624832,46248326,4624832612,46248326122,462483261224,4624832612248,46248326122
4832]

3.2. Utilizando funciones de orden superior implementar la función numTam que tiene como parámetro un numero
n entero mayor que tres y devuelve como resultado el primer número de la secuencia cuya longitud es al menos
n. (0,5 puntos)
numTam10 à 4624832612
numTam 20 à 46248326122483261224
numTam 3 à Error: el numero debe ser mayor que 3
numTam 4 à 4624

65. Septiembre 2019. Numeros desnudos y de Dudeney. Tema 2 y 3



1) Un número de Dudeney es un entero que es un cubo perfecto, de forma que la suma de sus dígitos da como resultado
la raíz cúbica del número. Por ejemplo:
1 = 1 x 1 x 1 ; 1 = 1
512 = 8 x 8 x 8 ; 8 = 5 + 1 + 2
4913 = 17 x 17 x 17 ; 17 = 4 + 9 + 1 + 3
5832 = 18 x 18 x 18 ; 18 = 5 + 8 + 3 + 2

Utilizando listas por comprensión, implementar la función dudeney que genere los números de Dudeney (0,5 puntos)
take 4 dudeney à [1, 512, 4913, 5832]

2) Un número desnudo es aquel cuyos dígitos son todos divisores del número. Un ejemplo es el número 424, que es
divisible entre 2 y 4, es capicúa, y todo sus números no son iguales. Otro ejemplo de número desnudo es el número 212.

Define la función desnudos que no tiene parámetros y devuelva una lista con todos los números desnudos de 3 dígitos
que sean capicúas y que no tengan todas las cifras iguales. Utiliza todas las funciones auxiliares que consideres necesarias.
(0,5 puntos)
Aqui no se pone ejemplo de la ejecución porque la solución es única

66. Septiembre 2019. Multiplicacion Rusa. Tema 3 y 4


El método de la multiplicación rusa es un método para multiplicar dos números enteros, positivos. A por B
a) Se divide por 2 el multiplicando A hasta que éste tome el valor 1 (columna 1 del ejemplo)
b) Se suma dos veces el multiplicando B, las veces que sean necesarias (columna 2 del ejemplo)
c) Selecciono en B los valores, que en la columna de A tienen un valor impar (columna3)
d) Se suman esos valores. Dicha suma resulta ser el producto de los dos números. (columna4)

Ejemplo 37 x 12 -> 345

A B seleccion SUMANDO RESULTADO


23 15 15 porque 23 es impar 15
11 30 30 porque 11 es impar 30
5 60 60 porque 5 es impar 60
2 120 NO porque 2 es par -
1 240 240 porque 1 es impar 240
15+30+60+240=
345

1.1. Implementar la función multiplicaR, que multiplique dos números enteros mediante el algoritmo de la
multiplicación rusa. No se podrá utilizar el *en toda la implementación, sino el algoritmo descrito. Definir una
propiedad quick_check multiplicaR_p para la función multiplicaR (las dos funciones, funcionando
correctamente 1 punto) para números enteros positivos.
multiplicaR 27 82 à 2214
multiplicaR 234 124 à 29016
multiplicaR 23 15à 345
quickCheck multiplicaR_p à
+++ OK, passed 100 tests.



38
Ejercicios de Examen. Informática. Haskell. Versión curso 2020/2021


67. Septiembre 2019. Multiplicacion Egipcia . Tema 3 y 4

El método de multiplicación egipcia, consiste en lo siguiente A * B

a) Empezando por 1, hago una lista donde cada elemento es dos veces el anterior y así sucesivamente hasta
llegar a un número que sea mayor que b (ese número ya no se añade) (columna 1: Se para aquí porque el 16
porque el 32 ya es mayor que 21)
b) Empezando por el número A, voy haciendo una lista donde cada elemento es dos veces el anterior. Tendrá
tantos elementos como la lista anterior (columna 2)
c) De la lista del apartado 1, selecciono aquellos números que sumados dan el número B (columna 3)
d) Sumo los elementos de la columna 2, que ocupan la misma posición que los seleccionados en el apartado
anterior y que han sido seleccionados en el paso 3.

Ejemplo 23 X 21 à 483

A B seleccion SUMANDO RESULTADO


1 23 SI 23
2 46 NO -
4 92 SI 92
8 184 NO -
16 368 SI 240
1 +4+16 = 21 23+92+368 = 483

2.1. Implementar la función calcularLista que recibe como entrada una lista de números enteros y una cantidad n, y
devuelve como resultado la lista de números no repetidos que sumados dan el valor n, o la lista vacia si no es posible. (1
punto)
calcularLista [1, 2, 4, 8, 16] 34 à [] --no es posible
calcularLista [1, 2, 4, 8, 16] 21 à [1,4,16]

2.2 Implementar la función multiplicaE, que multiplique dos números enteros mediante el algoritmo de la multiplicación
egipcia. No se podrá utilizar el *en toda la implementación, sino el algoritmo descrito. Definir una propiedad
quick_check multiplica_e para la función multiplicaE. (las dos funciones funcionando correctamente, 1,5
puntos)
multiplicaE 23 21 à 483
multiplicaE 21 23 à 483
multiplicaE 23 15 à 345

68. Septiembre 2019. Arboles de Calkin-Wilf. Tema 5
Un árbol de Calkin-Wilf son arboles binarios done su nodo raíz es una fracción a/b, la rama izquierda es la
fracción a/a+b y la rama derecha es la facción a+b/b. Así un árbol cuya raíz es 1/1 sería el de la figura.


Se ha definido el tipo Fraccion para representar un nodo
data Fraccion a b = F a b deriving Show

1) Definir la función sucesores que tiene como entrada una fracción y como salida una lista de dos nodos, el
primero una rama izquierda del árbol de CalkinWilf, y la segundo la rama derecha.
sucesores (F 1 1) à [F 1 2, F 2 1]
sucesores (F 3 4) à [F 3 7,F 7 4]

2) Definir una nivelCW que recibe como entrada un nodo y un numero n mayor que 0 y nos devuelve de
todos los nodos de un árbol de CalkinWilf en el nivel n (contando que el nodo dado está en el nivel 1).
nivelCW (F 1 1) 2 à [F 1 3,F 3 2,F 2 3,F 3 1]
nivelCW (F 1 1) 3 à [F 1 4,F 4 3,F 3 5,F 5 2,F 2 5,F 5 3,F 3 4,F 4 1]



39
Ejercicios de Examen. Informática. Haskell. Versión curso 2020/2021


3) Utilizando el tipo Arbol de la librería Arbol.hs y las funciones de la librería que considere necesarios,
definir la función cocanstruirCW que dado un nodo, y un número n que indica la profundidad del árbol, devuelva
el árbol de Calkin-Wilf correspondiente.
construirCW (F 1 1) 2 à
Nodo (F 1 1) [Nodo (F 1 2) [],
Nodo (F 2 1) []]

construirCW (F 1 1) 3 à
Nodo (F 1 1) [Nodo (F 1 2)
[Nodo (F 1 3) [],
Nodo (F 3 2) []],
Nodo (F 2 1)
[Nodo (F 2 3) [],
Nodo (F 3 1) []]]

69. Febrero 2020. Una sucesión (Tema 3)

Se tiene una sucesión que se aplica a un parámetro n. El primer elemento es n. Cada elemento sucesivo se calcula como
la suma del término anterior y el producto de los dígitos no nulos del anterior.

Ejemplo: si un término es 102, el siguiente término es, 102+ (2*1) = 102 + 2 = 104
Sucesiones generadas para sucesivos valores de n
n=1 à 1, 2, 4, 8, 16, 22, 26, 38, 62, 74, 102, 104, 108, 116, 122
n=2 à 2, 4, 8, 16, 22, 26, 38, 62, 74, 102, 104, 108, 116, 122, 126, …
n=3 à 3, 6, 12, 14, 18, 26, 38, 62, 74, 102, 104, 108, 116, 122, 126, …
n=4 à 4, 8, 16, 22, 26, 38, 62, 74, 102, 104, 108, 116, 122, 126,..

Como puede verse en las sucesiones anteriores, a partir de un número (que no es el mismo en todos los casos)
una sucesión converge a la del 1, en cualquier posición de la sucesión y en cualquier número. Así, la sucesión
con n=2 converge a partir del número 2, y la sucesión con n=3 converge a partir del número 26.

Se pide

1. Definir una función sucesion que para un número n devuelva la sucesión infinita correspondiente. Usar
recursividad (0,5 p)

take 15 (sucesion 1)à [1,2,4,8,16,22,26,38,62,74,102,104,108,116,122]


take 15 (sucesion 4)à [4,8,16,22,26,38,62,74,102,104,108,116,122,126,138]
take 15 (sucesion 10)à [10,11,12,14,18,26,38,62,74,102,104,108,116,122,126]

2. Definir la función converge que dada un valor n>1 devuelva trtes valores, el término a partir del cual
converge con la sucesión del 1, y la posición que tiene el término en la sucesión n. Usar recursividad con
acumuladores (1p)

converge 3 à (26,7,6) --- a partir del 26 son iguales, y el 26 esta en la pos 7 en al


sucesion1
--- y en la posicion 6 de la sucesión 3
converge 2 à (2,2,1)
converge 1 à *** Exception: n debe ser mayor o igual que 1 -- error porque n no es mayor que
1
70. Febrero 2020. Donde Está (Temas 2 y 3)
Dada una cadena, implementar la función dondeEsta que tiene dos parámetros una cadena y un carácter, y
devuelva como resultado una lista que diga en que posiciones está un carácter dado.
dondeEsta "la casa es azul" 'r' à []
dondeEsta "la casa es azul" 'z' à [13]
dondeEsta "la casa es azul" 'a' à [2,5,7,12]

a) dondeEstaLPC: Con listas por comprensión y sin recursividad (0,5p)
b) dondeEstaFOS: Con funciones de orden superior y sin recursividad (0,5p)



40
Ejercicios de Examen. Informática. Haskell. Versión curso 2020/2021

71. Febrero 2020. Polinomios (Temas 5)


El polinomio
a*x^5 + b*x^4 + c*x^3 + d*x^2 + e*x + f [1]
es equivalente a la siguiente expresión
((((a * x + b) * x + c) * x + d) * x + e) * x + f [2]
Puede verse que la evaluación se hace de dentro hacia afuera, y que es una expresión generalizable a un
polinomio de cualquier grado.

Vamos a trabajar con polinomios cuyos coeficientes son números enteros. El polinomio [1] lo representamos
con un sinónimo de tipo
type Polinomio = [Integer]

Y el polinomio según [2] con un tipo de datos recursivo


data ExpresionP = |N Integer
| X
| ExpresionP:+ ExpresionP
| ExpresionP:* ExpresionP
deriving (Eq, Show)

Ejemplos
Polinomio ExpresionP
[1, 0,1, 2, 0] (((((((N 1 :* X) :+ N 0) :* X) :+ N 1) :* X) :+ N 2) :* X) :+ N 0 No está simplificada
(((((N 1 :* X ):* X) :+ N 1) :* X) :+ N 2) :* X Está simplificada
Cuando el polinomio se representa como una lista, los ceros son necesarios porque indican el grado de cada
coeficiente. Como puede observarse, los ceros aparecen en la expresión, pero realmente no son necesarios,
Así, el polinomio derivado de la lista [1, 0,1, 2, 0] es igualmente válido con o sin ceros. Lo ideal sería que los
términos con cero no aparecieran en la expresión. El binomio nulo se representa como N 0

1) Definir el predicado estaSimplificada que dado un polinomio del tipo ExpresionP devuelva True si
está
simplificada, y False en caso contrario (0,5 p)
estaSimplificada ((((((((N 1 :* X) :+ N 0) :* X) :+ N 1) :* X) :+ N 2) :* X) :+ N 0) à False
estaSimplificada ((((((N 1 :* X) :* X) :+ N 1) :* X) :+ N 2) :* X) à True

2) Definir la función simplificarP que tiene como entrada un polinomio del tipo ExpresionP y devuelva
la misma expresión pero simplificada, es decir, sin términos con valor 0 , excepto si es el polinomio
nulo que devolvería N 0 (0,5 p)

simplificarP ((((((((N 1 :* X) :+ N 0) :* X) :+ N 1) :* X) :+ N 2) :* X) :+ N 0)à


(((((N 1 :* X) :* X) :+ N 1) :* X) :+ N 2) :* X

3)Definir la función aPolinomioExp tal que dada como entrada una lista, devuelva como resultado la
ExpresiónP equivalente simplificada. Resolver este apartado con plegado y desplegado y sin recursividad. No
se considerarán válidas las soluciones en las que el plegado hace un trabajo auxiliar.. Si se necesita, se puede
usar la función simplificarP definida en el apartado anterior. (1 p)

aPolinomioExp [1,2,0,0,1]à (((((N 1 :* X) :+ N 2) :* X) :* X) :* X) :+ N 1


aPolinomioExp [5, (-2), 1, 2, 0, 1] à ((((((((N 5 :* X) :+ N (-2)) :* X) :+ N 1) :* X) :+ N
2) :* X) :* X) :+ N 1
aPolinomioExp [5, 3] à (N 5 :* X) :+ N 3
aPolinomioExp [5, 0] à N 5 :* X

4)Utilizando recursividad, implementar la función evaluarE tal que dado un polinomio en forma de
ExpresionP, lo evalúe con el valor de x dado como parámetro. (0,5 p)
evaluarE:: ExpresionP -> Integer -> Integer
evaluarE (N 5 :* X) 10 à 50 -– 5x para 10, vale 50
evaluarE (aPolinomioExp [1,2,0,0]) 2 à16 -- x^3 + 2x^2 para 2 vale 16
evaluarE ((((((N 4 :* X) :+ N 2) :* X) :+ N 1) :* X) :+ N 1) 3 à 130
--4*x^3 + 2*x^2 * x + 1 para x = 3 vale
130
evaluarE (N 0) 100 à 0



41
Ejercicios de Examen. Informática. Haskell. Versión curso 2020/2021

72. Febrero 2020. Arbol de Factorización (Tema 6)

1) Los divisores medios de un número son el divisor medio menor y el divisor medio mayor de un numero se obtienen
con el siguiente algoritmo:
• Se obtienen todos los divisores de un número n y se ordenan de menor a mayor
• Si el número de divisores es par, se extraen los dos del centro, el menor de ellos el es divisor medio menor, el
mayor de ellos es el divisor medio mayor.
• Si el número de divisores es impar. Hay dos casos:
- Si son tres divisores, el divisor medio mayor y menor, es el numero que ocupa la posición central
- Si tiene más de tres divisores, el divisor medio mayor y menor es respectivamente el que está a derecha
e izquierda de la posición central
Ejemplos:
n Divisores divisor medio menor divisor medio mayor
60 [1,2,3,4,5,6,10,12,15,20,30,60] 6 10
64 [1,2,4,8,16,32,64] 4 16
4 [1,2,4] 2 2

Implementar la función divisoresMedios que dado un número n devuelva un par con sus divisores medios, primero
el menor y segundo el mayor. (0,5p).
divisoresMedios 60 à (6,10) divisoresMedios 64 à (4,16) divisoresMedios 4 à
(2,2)

2)Los árboles de factorizacion son una representación eficiente de descomposición de un número en factores, que
cumplen las siguientes condiciones:
• El 1 nunca está en un árbol
• Los nodos que son números primos no se factorizan, y por lo tanto son hojas (nodos finales) del árbol final
• Si el nodo no es primo se factoriza generando un subarbol según el algoritmo descrito abajo. El producto
de sus sucesores inmediatos el valor del nodo padre.
• El producto de todas las hojas de cada subárbol de un nodo raíz, da como resultado el número del nodo
raíz.
ALGORITMO para construir un árbol de factorización de un número n
1.El nodo n es la raíz del árbol
2. Calcular todos los divisores del numero n.
2.1 Si el numero es un número primo, el algoritmo termina.
2.2 Si no es primo, calcular su divisor medio menor y su divisor medio mayor.
3. La rama izquierda es el árbol de factorización de divisor medio menor
4. La rama derecha es el árbol de factorización de divisor medio mayor
Se ha definido el tipo ArbolBinario para representar un árbol de factorización
data Arbol a = Hoja a
| Nodo a (Arbol a) (Arbol a)
deriving Show

2.1. Implementar la función arbolFactorizacion que tiene como entrada un numero n y devuelva como salida el
árbol de factorización correspondiente, (1 p)
arbolFactorizacion 60 à Nodo 60 (Nodo 6 (Hoja 2) (Hoja 3)) (Nodo 10 (Hoja 2) (Hoja 5))
arbolFactorizacion 15 à Nodo 15 (Hoja 3) (Hoja 5)
arbolFactorizacion 7 à Hoja 7
arbolFactorizacion 8 à Nodo 8 (Hoja 2) (Nodo 4 (Hoja 2) (Hoja 2))
arbolFactorizacion 1à *** Exception: el 1 no tiene árbol de factorizacion

2.2. Definir la propiedad esArbolFactorizacion tal que dado un árbol, devuelva True si es un árbol de factorización
y False en caso contrario. Un árbol dado es de factorización si cumple las condiciones descritas al inicio del apartado
2 (0,5p)
esArbolFactorizacion (Nodo 15 (Hoja 2) (Hoja 5)) à False. -– 2*5 no da 15
esArbolFactorizacion (Nodo 15 (Hoja 3) (Hoja 5)) à True. –- 3 y 5 son primos y 3*5==15
esArbolFactorizacion (Nodo 8 (Nodo 4 (Hoja 2) (Hoja 2)) (Hoja 2)) à True



42
Ejercicios de Examen. Informática. Haskell. Versión curso 2020/2021


esArbolFactorizacion (Nodo 15 (Nodo 10 (Hoja 2) (Hoja 5)) (Hoja 3)) à False, 10 *3 no da 15

2.3 Los arboles de factorización se pueden usar encontrar los primos de un número. Se pide implementar la función
factores cuya entrada es un número, internamente construye un árbol de factorización, y a partir de éste obtenga la
lista de factores primos en que puede descomponerse, ordenados de menor a mayor. Comprobar la corrección de la
función con el predicado factores_p que se probará con quickCheck. (1p)
factores 15 à [3,5]
factores 18 à [2,3,3]
factores 64 à [2,2,2,2,2,2]
factores 60 à [2,2,3,5]

quickCheck factores_p à +++ OK, passed 100 tests;

73. Julio 2020. Pirámide de números


Una pirámide de números es una estructura en la que un número es la suma de los dos que
tiene debajo. Tienen como mínimo dos pisos, sin que haya límite para el máximo de pisos.
Ejemplos:

ejemplo
tamaño 2 3 4 5

Una pirámide está completa cuando todas sus casillas tienen números, y todos los que están en
casillas superiores a la base, cumplen la condición de que cada casilla es la suma de los dos
inferiores. Cuando no está completa, en lugar de números hay huecos. A partir de unos números
más unos huecos, se resuelve una pirámide teniendo en cuenta la regla de que la casilla inferior
es la suma de las dos inferiores.

Una pirámide números puede representarse como una lista, donde el primer elemento es la
cima, los dos siguientes el piso inferior, y así sucesivamente. Así, una pirámide con huecos la
representamos en Haskell con la lista de la izquierda, y , su pirámide completa como la lista de
la casilla de la derecha; ambos en la tabla inferior:



[Num 22, Hueco, Hueco, Num 8, [Num 22, Num 11,
Num 3, Hueco] Num 11, Num 8, Num 3, Num 8]

Pirámide con huecos Piramide completa: sin huecos, todos los números son correctos

Para resolver el problema, definir previamente las estructuras de datos y tipos que se consideren
necesarios. Deben ponerse al principio del fichero.


1) (2 puntos) Definir la función esPiramideCompleta tal que dada una lista nos diga si es una
pirámide completa, con números que cumplen las condiciones indicadas



43
Ejercicios de Examen. Informática. Haskell. Versión curso 2020/2021


esPiramideCompleta [Num 22, Hueco, Hueco, Num 8, Num 3, Hueco] à False -- tiene huecos

esPiramideCompleta [Num 22, Num 11, Num 8, Num 3, Num 8] à False -- no es piramide, sobran o faltan nums

esPiramideCompleta [Num 22, Num 11, Num 11, Num 8, Num 3, Num 8] à True

esPiramideCompleta [Num 22, Num 11, Num 15, Num 8, Num 3, Num 8] à False ---11 + 15 es diferente de 22


2) (2 puntos) Definir la función resolverPiramide que devuelva todas las posibles soluciones de
una pirámide con huecos de un número n de pisos. En nuestra solución tendremos en cuenta que en la
pirámide de entrada nos van a dar al menos tantos valores como pisos puedan hacerse con los
datos que nos dan. Es decir, si la pirámide es de 3 pisos, habrá al menos tres valores en la lista de
entrada; si es de 4 pisos, al menos cuatro, etc. Aún así, pueden darse casos de pirámides que no tengan
solución (véanse los ejemplos).
La solución de este problema requiere implementar varias funciones auxiliares. Entre ellas al menos una deberá haber, una recursiva, una con
funciones de orden superior y una con listas por comprensión. Es importante que se explique el algoritmo seguido para implementar
resolverPiramide. Para cada función, su entrada, salida y qué hace cada función. SI NO SE PUEDE SEGUIR LA IMPLEMENTACIÓN CON LOS
COMENTARIOS, no se corregirá el problema.

resolverPiramide [Num 22, Hueco, Hueco, Num 8]


à *** Exception: Numero incorrecto de elementos. Faltan o sobran numeros para ser piramide

resolverPiramide [Num 22, Hueco, Hueco, Num 8, Hueco, Hueco]


*** Exception: hay demasiados huecos. No se puede resolver

resolverPiramide [22, Hueco, Hueco, 8, 3, Hueco] à Error de tipo

resolverPiramide [Num 22, Hueco, Hueco, Num 8, Num 3, Hueco]à [Num 22,Num 11,Num 11, Num 8,Num
3,Num 8]

resolverPiramide [Hueco, Hueco, Hueco, Hueco, Num 11, Num 33, Num 1, Num 4, Num 9, Num 24]
à [Num 60,Num 16,Num 44,Num 5,Num 11,Num 33,Num 1,Num 4,Num 9,Num 24]



resolverPiramide [Num 22, Num 11, Num 11, Hueco, Hueco, Hueco]
à [Num 22,Num 11,Num 11,Hueco,Hueco,Hueco]
No tiene solución, aunque solo tiene 3 huecos (pensad el motivo). La función devuelve hasta donde
puede resolver

74. Julio 2020. Un juego con la baraja española
Este es un juego para la baraja española, en la que hay 4 palos (oros, bastos, espadas y copas),
cada uno de los cuales tiene 12 cartas, del 1 al 12. Vamos a contar las normas para dos
jugadores:

1) Al principio se reparten todas las cartas entre todos los
jugadores, la mitad para cada uno
2) A partir de ahí comienza el juego, donde le primero en
tirar es el jugador que no ha repartido, que echa la
primera carta que le dieron en el reparto sobre la mesa.
3) Por turnos, cada jugador echa otra carta en la que
coincida o bien el palo o bien el número con la carta que
el anterior jugador puso en la mesa.
4) Si un jugador no tiene ninguna carta para poner en la
mesa, directamente, no hace nada y cede su turno al otro
jugador.
5) El juego tiene dos formas de finalizar:
a. Si ningún jugador puede poner, porque no
tienen ninguna carta que coincida con el palo ni con el número. En ese caso se devuelve
Empate


44
Ejercicios de Examen. Informática. Haskell. Versión curso 2020/2021


b. Cuando un jugador se queda sin cartas; en este caso, será el ganador del juego. Se devuelve
Gana 1 si el que se queda sin cartas es el segundo jugador, o Gana 2, en el otro caso.

Los jugadores pueden tener al menos tres estrategias, que seguirán durante toda la partida:
eMismoPalo. Asistir al palo: mientras tenga cartas del palo que está en la mesa, echa del
palo. Si no tiene del palo, entonces pone del mismo número, si tiene.
eMismoNumero. Asistir al numero: mientras tenga cartas con el número que está en la
mesa, echa carta con ese número. Si no tiene con el mismo número, entonces pone del
mismo palo, si tiene.
eAzar. Al azar: Se se elige al azar entre palo y número, y luego de éntrelas elegidas, se
selecciona una carta.


1) (3,0 puntos) Implementar la función jugar2 que simule una partida de un juego de dos jugadores con
todos los elementos que sean necesarios y las funciones (con la sintaxis, entrada, salida y estructura
que se consideren necesarios):
i. Representación de los elementos del juego: las cartas y el grupo de cartas que recibe cada
jugador.
ii. Implementar la función repartir que haga el reparto de las cartas a los dos jugadores
utilizando la librería Aleatorios
iii. Implementar el juego, en la función jugar2. La semilla s será el primer parámetro y se utiliza
tanto para el reparto de cartas como para seleccionar las cartas en las estrategias.
iv. Implementar las tres estrategias descritas, que se pasarán como parámetro cuando se realice
el juego, las estrategias utilizarán la librería Aleatorios para seleccionar entre varias cartas
posibles en una jugada, para ello cada estrategia tendrá, aparte de los parámetros que se
consideren necesarios, uno para la semilla de para generar los números aleatorios.

Aunque no funcione completamente jugar2, se valorarán por separado las funciones
implementadas para simular el juego. Los nombres de los tipos de datos y de las funciones se
dejan a elección del alumno. Explicar con comentarios que hace cada función
jugar2 3 "luis" eMismoNumero "ana" eMismoPalo à Empate
jugar2 3 "luis" eMismoPalo "ana" eMismoNumero à Gana1 -- gana luis
jugar2 8 "luis" eMismoPalo "ana" eMismoNumero à Gana1 -– gana luis
jugar2 8 "luis" eMismoPalo "ana" eMismoPalo à Gana2 -- gana ana
jugar2 8 "ana" eMismoPalo "luis" eAzar à Gana1 -- gana ana

2) (1,0 puntos) Implementar la función simula que recibe como parámetro una semilla, el nombre de dos
jugadores, y la estrategia que sigue cada uno de ellos y el número de pruebas que se van a realizar. La
función devolverá dos pares: el primero con la estrategia y la probabilidad mayor de ganar, y la
segunda con su correspondiente probabilidad. La función tiene que funcionar llamando a la función
jugar anterior.

simula "ana" eMismoNumero "antonio" eMismoPalo 10 à [("ana",0.0),("antonio",0.2),("empate",0.8)]
simula "ana" eMismoNumero "antonio" eMismoPalo 100 à
[("ana",0.0),("antonio",0.11),("empate",0.89)]
simula "antonio" eMismoPalo "ana" eAzar 100 à
[("antonio",0.3),("ana",0.7),("empate",0.0)]

Vamos a realizar un experimento que nos permita saber cual de las tres estrategias es la mejor
para este juego, teniendo en cuenta que siempre reparte jugador1 y empieza jugador 1. Para ello,
se pide realizar una simulación de n jugadas con la misma semilla en las siguientes situaciones

Jugadas Jugador1 Jugador2
100 eMismoNumero eMismoPalo
100 eMismo Palo eAzar



45
Ejercicios de Examen. Informática. Haskell. Versión curso 2020/2021


100 eAzar eMismoNumero

Utilizando la función simula, implementar la función experimento que haga los cálculos
pertinentes para decir cual de las tres estrategias es la más ventajosa para cualquier jugador.
Para ello devolverá como resultado una lista con las estrategias ordenadas según se han
llamado en el experimento.

experimento eMismoNumero eMismoPalo eAzar 100 à [3.5e-2,0.40499999999999997,0.745]

Nos dice que jugar al azar tiene más probabilidades de ganar, y que jugar al mismo
número es el que tiene menos probabilidades de ganar

75. Septiembre 2020. Fichas de dominó
El dominó es un juego de mesa en el que se emplean unas fichas rectangulares. Una de sus caras
está dividida por dos cuadrados, cada uno de los cuales está numerado normalmente mediante
disposiciones de puntos como los dados (Wikipedia).

La numeración habitual es de cero a seis puntos, lo que compone un total de 28 piezas de dominó
siendo la ficha más grande la del seis doble. También hay dominós de 0 a 9 puntos y de 0 a 12 puntos.
En este problema vamos a llamarlo domino tamaño n, siendo las piezas de 0 a n.

En el dominó, las fichas se colocan de forma que una ficha coincide con al menos un extremo de las
que están en el tablero. Como resultado se construyen caminos de fichas, como el que se muestra en
la figura.


Fuente: http://oledomino.com/EL%20DOMINO/Eljuego.htm

Tenemos definido el tipo Ficha que nos permite representar una ficha del dominó con un par de
números enteros. Se considera que es lo mismo la ficha D 0 3 que la ficha D 3 0 (ya que así se
consideran en el juego, las fichas se giran para unirse por un lado o por otro)

data Ficha = D Integer Integer deriving (Show, Eq)

Son la misma ficha

Se representa como D 3 0 o como D 0 3. Solo habrá una de ellas en el tablero.

Se pide



46
Ejercicios de Examen. Informática. Haskell. Versión curso 2020/2021


1) (1 punto ) Implementar la funcion grafoDomino, que tenga como entrada un tamaño de
dominó, y de vuelva el grafo correspondiente, teniendo en cuenta las fichas que están
relacionas con una ficha (D x y), son aquellos coinciden o bien en la x o en la y o en ambos.

Para construir la solución de la función pedida, elige una representación para el Grafo, y explicala
brevemente en el fichero de la solución. Puede ser alguna de las utilizadas en los problemas de
clase o de prácticas.

En la figura inferior se muestra un ejemplo de un grafo para un dominó de tamaño 3. La salida en


Haskell dependerá la representación elegida para el grafo.

2) (1 punto) Utilizando el grado definido por la función grafoDominio, implementar la función


caminoCorto que calcule el primer camino más corto (con el mínimo numero de fichas) que se
puede construir con dos piezas que se dan como entrada. Utilizad una estructura de datos adicional
(Pila, Cola o Grafo) para obtener una solución eficiente (no es valida una solución en la que
calculo todos los caminos y me quedo con el de menos longitud porque es sería muy poco
eficiente). En la función deberá hacerse una llamada a la función grafoDominio para generar el
grafo como paso inicial para el cálculo de la función.

caminoCorto (D 0 0) (D 2 3) 3 à [D 0 0,D 0 3,D 2 3]


caminoCorto (D 0 0) (D 2 3) 3 à [D 0 0,D 0 3,D 2 3]
caminoCorto (D 2 3) (D 0 0) 3 à [D 2 3,D 0 2,D 0 0]
caminoCorto (D 0 0) (D 2 5) 3 à []
-– (D 2 5) no está en un dominó de tamaño 3, por eso sale []

3) (1punto) Dada una ficha y un dominó de tamaño n, implementar la funcion arbolFicha que
devuelva el árbol con todas las posibles combinaciones que se pueden producir a partir de esa
ficha en ese tablero de dominó. Elige la representación de Arbol que consideres más conveniente,
explicándola previamente en el fichero de la solución. En la figura inferior se muestran algunos
ejemplos. La salida en Haskell dependerá de la representación elegida, puede ser alguna de las
utilizadas en los problemas de clase o de las prácticas.

arbolFicha::Ficha -> Integer -> Arbol


El grafico muestra salida para la ficha (D 0 0) con un dominó de 0 a 2.



47
Ejercicios de Examen. Informática. Haskell. Versión curso 2020/2021

4) (1 punto) Las series de dominós se utilizan mucho para tests psicotécnicos. En este caso, las fichas
de dominó se utilizan para que el aspirante demuestre su capacidad para conceptualizar, y para
aplicar el razonamiento sistemático a nuevos problemas, por lo que constituye una buena
medición del factor “g” de inteligencia general (www.psicoactiva.es) . En este problema,
vamos a considerar series de dominós que están en posición horizontal y solo aquellos casos en
los que hay una relación entre las posiciones x y las posiciones y de las fichas. Pueden ser series
infinitas siempre y cuando no haya fichas negativas en la serie.

Esta serie se representaría como [ (D 3 3) (D 3 2) (D 3 1) (D 3 0)] y la relación entre las x es dejarlo


tal cual y la relación entre las y es restar una unidad al valor de la y

Se pide implementar la función generarSerie que recibe como entrada, una ficha y dos nombres de
funciones: la función que se aplica entre las XX, la que se aplica entre YY. El resultado de la serie
puede ser una serie infinita, pero no puede ser una serie con números negativos (en este caso la serie
se pararía)

Notas:
- Ahora las series de casillas ya no cumplen las restricciones del juego del dominó,
son series dobles de números.
- La función suma0 deja la casilla igual a la anterior

take 10 (generarSerie (D 3 3) suma0 restay1) à


[D 3 3,D 3 2,D 3 1,D 3 0] – serie que no es infinita

take 10 (generarSerie (D 0 0) sumax2 sumay1)


[D 0 0,D 2 1,D 4 2,D 6 3,D 8 4,D 10 5,D 12 6,D 14 7,D 16 8,D 18 9]
--serie infinita





48
Ejercicios de Examen. Informática. Haskell. Versión curso 2020/2021


Otros ejercicios (no de examen, de otras


relaciones de problemas)
1. División exacta de números
Este ejercicio estudia la división exacta de números entero y el calculo de divisores. Se pide definir las siguientes
funciones y sus declaraciones de tipo, donde los valores numéricos son del tipo Integral.
a) Define una función divideA que compruebe si su primer argumento divide exactamente al segundo. Por
ejemplo:
2 `divideA` 10 => True
4 `divideA` 10 => False
b) (*) Lee, entiende y comprueba con QuickCheck la siguiente propiedad referente a la función divideA:
p1_divideA x y = y/=0 && y `divideA` x ==> div x y * y == x
c) (*) Escribe una propiedad p2_divideA para comprobar usando QuickCheck que si un número divide a otros
dos, también divide a la suma de ambos.

d) Usando una lista por comprensión y la función divideA, define una función divisores que devuelva una lista
con todos los divisores de un número natural. Por ejemplo:
divisores 10 => [1,2,5,10]

2. Máximo común divisor


El máximo común divisor de dos números x e y es el máximo de los divisores comunes de x e y.
1) Define, usando una lista por comprensión y la función divisores del ejercicio anterior, una función mcd
que calcule el máximo común divisor de dos números. Por ejemplo:
mcd 30 75 => 15
Para ello, calcula primero los divisores de x, y luego quédate con los elementos de esta lista que también son
divisores de y. Tendrás ahora los divisores comunes de x e y, por lo que basta que selecciones el elemento
máximo de esta lista. Para ello, usa la función predefinida
maximum :: (Ord a) => [a] -> a
que devuelve el mayor elemento de una lista.
2) (*) Escribe y comprueba usando QuickCheck la siguiente propiedad: para x,y,z > 0, el mcd de z*x y z*y es
igual al valor absoluto de z por el mcd de x e y.
3) A partir de la siguiente propiedad que relaciona el mcd con el mcm (mínimo común múltiplo) de dos
números
mcd x y ∙ mcm x y = x ∙ y
escribe una función que calcule el mcm de dos números. Por ejemplo:
mcm 9 15 => 45
mcm 30 75 => 150
Nota: el algoritmo de Euclides para el cálculo de mcd es más eficiente que el que has desarrollado en este
ejercicio.



49

También podría gustarte