Ejercicio 1

La función mapdoble recibe como argumentos dos funciones y una lista, y devuelve una lista
resultado de aplicar la primera función a los elementos de la lista que ocupan posición impar, y la
segunda a los que ocupan posición par.
Por ejemplo:

# mapdoble (function x -> x) (function x -> -x) [1;1;1;1;1];;
- : int list = [1; -1; 1; -1; 1]

Se pide:

  • Implemente la función mapdoble.
  • Indique el tipo de la función mapdoble.
  • Indique el valor de:
mapdoble (function x -> x*2) (function x -> "x") [1;2;3;4;5];;
  • Indique el tipo de:
let y = function x -> 5 in mapdoble y;;

Respuesta

Uso una función recursiva en la que se coge el primer elemento y se le aplica la funcion 1 y se llama de nuevo a la función esta vez siendo la función 2 y la lista que queda.

let rec mapdoble f1 f2 = function
    [] -> []
  | h::[] -> [f1 h]
  | h::t -> f1(h)::mapdoble f2 f1 t;;
 
Line 1, characters 44-47:
1 | mapdoble (function x -> x*2) (function x -> "x") [1;2;3;4;5];;;;
                                                ^^^
Error: This expression has type string but an expression was expected of type
         int
- : ('_weak1 -> int) -> '_weak1 list -> int list = <fun>

Ejercicio 2

manejar exceciones

  • Defina una función primero_que_cumple, que dado un predicado (es decir, una función de tipo ‘a bool) y una lista, devuelva el primer elemento de la lista que verifica dicho predicado.

  • Indique el tipo de la función primero_que_cumple.

  • Utilizando la función primero_que_cumple, defina una función existe, que dado un predicado y una lista devuelva true si en la lista hay algún elemento que verifica el predicado, y false en caso contrario.

  • Se quiere mantener un conjunto de valores etiquetados de cualquier tipo, mediante una lista de pares ‘a * ‘b, donde la primera componente del par es la etiqueta o clave, y la segunda es el valor asociado a esa clave en dicho conjunto. Utilizando la función primero_que_cumple, defina una función asociado : (‘a * ‘b) list ‘a ‘b, que dado un conjunto y una clave, devuelva su valor asociado.

    usar pares (funciones propias)

Respuesta

let rec primero_que_cumple f = function
    [] -> raise Not_found
  | h::t -> if f(h) = true then h else primero_que_cumple f t;;
 
let existe f l =
    try (let _ = primero_que_cumple in true)
    with Not_found -> false;;
 
let asociado l key =
  snd(primero_que_cumple(function(a,b) -> a = key) l);;
 

Ejercicio 3

recursividad
Se ha construido el siguiente tipo de dato con el fin de poder representar árboles binarios donde la información que aparece en cada nodo puede ser de cualquier tipo:

type 'a arbol_binario =
    Vacio
  | Nodo of 'a * 'a arbol_binario * 'a arbol_binario;;

Se pide:

  • Construya las funciones in_orden, pre_orden, post_orden y anchura, todas ellas de tipo ‘a arbol_binario ‘a list, que devuelvan los correspondientes recorridos sobre un árbol binario dado, tal y como se muestra en los siguientes ejemplos:
  3
 / \
2   5
   / \
  4   1
let tree = Nodo(3,Nodo(2,Vacio,Vacio),Nodo(5,Nodo(4,Vacio,Vacio),Nodo(1,Vacio,Vacio)));;
# in_orden t;;
- : int list = [2; 3; 4; 5; 1]
# pre_orden t;;
- : int list = [3; 2; 5; 4; 1]
# post_orden t;;
- : int list = [2; 4; 1; 5; 3]
# anchura t;;
- : int list = [3; 2; 5; 4; 1]

Respuesta

let rec in_orden = function
    Vacio -> []
  | Nodo (head, left, right) -> (in_orden left) @ (head::(in_orden right));;
 
in_orden tree;;
let rec pre_orden = function
    Vacio -> []
  | Nodo (head, left, right) -> head::(pre_orden left) @ ((pre_orden right));;
 
pre_orden tree;;
let rec post_orden = function
    Vacio -> []
  | Nodo (head, left, right) -> (post_orden left) @ ((post_orden right) @ [head]);;
 
post_orden tree;;
let anchura tree =
  let rec aux queue l = match queue with
    | [] -> List.rev l
    | Nodo(head, left, right) :: rest ->
       let new_queue = rest @ [left; right] in
       aux new_queue (head :: l)
    | Vacio :: rest -> aux rest l
  in aux [tree] [];;
 
anchura tree;;

Ejercicio 4

tipos de datos
Consideremos el siguiente tipo de dato para una representación de conjuntos basada en listas sin elementos repetidos:

type 'a conjunto = Conjunto of 'a list;;

Por ejemplo, el conjunto vacío se podría representar mediante el siguiente valor:

let conjunto_vacio = Conjunto [];;

Se pide implementar las siguientes funciones:

  • pertenece : ‘a ‘a conjunto bool
  • agregar : ‘a ‘a conjunto ‘a conjunto
  • conjunto_of_list : ‘a list ‘a conjunto
  • suprimir : ‘a ‘a conjunto ‘a conjunto
  • cardinal : ‘a conjunto int
  • union : ‘a conjunto ‘a conjunto ‘a conjunto
  • interseccion : ‘a conjunto ‘a conjunto ‘a conjunto
  • diferencia : ‘a conjunto ‘a conjunto ‘a conjunto
  • incluido : ‘a conjunto ‘a conjunto bool
  • igual : ‘a conjunto ‘a conjunto bool
  • producto_cartesiano : ‘a conjunto ‘b conjunto (‘a * ‘b) conjunto
  • list_of_conjunto : ‘a conjunto ‘a list

Respuesta

let c1 = Conjunto([1;2;3;4;5]);;
let c2 = Conjunto([4;5;6;7;8]);;

pertenece

val pertenece : 'a -> 'a conjunto -> bool = <fun>
let rec pertenece x = function
    Conjunto [] -> false
  | Conjunto (h::t) -> if h=x then true else pertenece x (Conjunto t);;
 
pertenece 1 c1;;

#+begin_src ocaml :tangle p0_4.ml

false

agregar

val agregar : 'a -> 'a conjunto -> 'a conjunto = <fun>
let rec agregar x c =
  if pertenece x c then c else match c with
  Conjunto l -> (Conjunto (x::l));;
 
agregar 1 c1;;
agregar 9 c1;;

conjunto_of_list

val conjunto_of_list : 'a list -> 'a conjunto = <fun>
let conjunto_of_list l =
  let rec aux (Conjunto l2) = function
      [] -> (Conjunto l2)
    | h::t -> aux (agregar h (Conjunto l2)) t
  in aux (Conjunto []) l;;
 
conjunto_of_list [1;3;2;4;5;1;2;3;9];;

suprimir

val suprimir : 'a -> 'a conjunto -> 'a conjunto = <fun>
let suprimir x (Conjunto l) =
  let rec aux x = function
      [] -> []
    | h::t -> if h=x then t else h::(aux x t)
  in Conjunto (aux x l);;
 
suprimir 3 c1;;

cardinal

val cardinal : 'a conjunto -> int = <fun>
let cardinal (Conjunto l) =
  let rec aux count = function
      [] -> count
    | _::t -> aux (count+1) t
  in aux 0 l;;
 
cardinal c1;;

union

val union : 'a conjunto -> 'a conjunto -> 'a conjunto = <fun>
let union c1 (Conjunto l2) =
  let rec aux (Conjunto l1) = function
      [] -> l1
    | h::t -> if pertenece h c1 then (aux c1 t) else h::(aux (Conjunto l1) t)
  in Conjunto (aux c1 l2);;
 
union c1 c2;;

interseccion

val interseccion : 'a conjunto -> 'a conjunto -> 'a conjunto = <fun>
let interseccion c1 (Conjunto l2) =
  let rec aux (Conjunto l1) = function
      [] -> []
    | h::t -> if pertenece h c1 then h::(aux c1 t) else (aux (Conjunto l1) t)
  in Conjunto (aux c1 l2);;
 
interseccion c1 c2;;

diferencia

val diferencia : int conjunto -> int conjunto -> int conjunto = <fun>
let diferencia (Conjunto l1) c2 =
  let rec aux (Conjunto l2) = function
      [] -> []
    | h::t -> if pertenece h c2 then (aux c1 t) else h::(aux (Conjunto l2) t)
  in Conjunto (aux c2 l1);;
 
diferencia c1 c2;;

incluido

val incluido : 'a conjunto -> 'a conjunto -> bool = <fun>
let rec incluido (Conjunto l1) c2 = match l1 with
    [] -> true
  | h::t -> if pertenece h c2 then (incluido (Conjunto t) c2) else false;;
 
incluido c1 c2;;
incluido c1 (Conjunto [0;1;2;3;4;5;6;7;8;9]);;

igual

val igual : int conjunto -> int conjunto -> bool = <fun>
let igual c1 c2 =
  (diferencia c1 c2) = (diferencia c2 c1);;
 
igual c1 c2;;
igual c1 c1;;

producto_cartesiano

val producto_cartesiano : 'a conjunto -> 'b conjunto -> ('a * 'b) conjunto = <fun>
let producto_cartesiano (Conjunto l1) (Conjunto l2)=
  let rec aux l1 l2 laux = match l1,l2 with
      [],_ -> []
    | (h::t),([]) -> aux t laux laux
    | (h1::t1), (h2::t2) -> (h1,h2)::(aux l1 t2 laux)
  in Conjunto (aux l1 l2 l2);;
 
producto_cartesiano c1 c2;;

list_of_conjunto

val list_of_conjunto : 'a conjunto -> 'a list = <fun>
let list_of_conjunto (Conjunto l) = l;;
 
list_of_conjunto c1;;