Cognome Nome Matricola Programmazione funzionale 12-09-2014 PROVA SCRITTA 1 2 3 4 5 Somma Il compito ha la durata di 1 ora, per la compilazione attenersi alle seguenti istruzioni: Scrivere in maniera chiara. Nome e cognome devono essere scritti in stampatello. Non sono ammessi appunti o altro materiale, a chiunque copia verrà ritirato l esame Gli esercizi possono essere eseguiti in qualsiasi ordine. L esame si ritiene superato se si raggiunge il punteggio di 18. In linea di massima le risposte parziali NON saranno accettate (salvo casi eccezionali). Salvo esplicita indicazione, si può usare qualsiasi funzione del modulo standard (pervasives), String e List. Sono permesse soluzioni con un qualsiasi numero di funzioni ausiliarie e con qualsiasi metodo a meno di indicazioni diverse presenti nel testo dell esercizio. Nell esercizio 1, se sono presenti più funzioni, tipizzare solo l ultima. 1
1. (5 punti) Determinare il tipo o il valore delle seguenti espressioni. Se non è possibile farlo scrivere NT (non tipizzabile). snd;; a * b -> b List.filter;; ( a -> bool) -> a list -> a list fun x y -> (x, y, [x::y]);; a-> a list-> a * a list * a list list let f x y = x > [y];; a list -> a -> bool fun x y z -> (x y, y z);; (( a-> b)-> c)->( a-> b)-> a-> c * b let f1 l = List.filter (fun x -> x < l) l;; NT let f2 l = List.map (List.tl) l;; a list list -> a list list let f2 l = List.map (List.tl) l;; [[]; []] f2 [[1,2];[3,4]];; fun x -> if snd x = 1 then [] else [fst x];; a * int -> a list fun (x,y,z) t -> t (x,y z);; a * ( b-> c) * b->( a * c-> d)-> d 2. (10 punti) Per ogni programma determinare il tipo e descrivere cosa fa. Nota: i programmi sono funzionanti let rec f = let rec aux n = function 0 -> 1 c -> n * aux n (c - 1) in function 0 -> 0 n -> (aux (-1) n) * n + f (n-1);; int -> int Calcola la somma n ( 1) i i i=0 let rec f n = let rec aux = function 0 -> 0 1 -> 1 n -> aux (n-1) + aux (n-2) in function [] -> n = 0 x::xs -> x = (aux n) && f (n-1) xs;; int -> int list -> bool Controlla se una lista contiene la successione di Fibonacci fino ad un numero n 2
let rec f s = function [] -> s = "" x::xs -> string -> bool list -> bool if x then s.[0] = 1 && Dato in input una stringa e una lista di f(string.sub s 1 (String.length s-1)) xs booleani controlla se la stringa rappresenta else il numero in binario contenuto nella lista. s.[0] = 0 && f(string.sub s 1 (String.length s-1)) xs;; type a tree = Empty Tr of a * a tree * a tree;; let rec f g = function Empty -> [] Tr (x,empty, Empty) -> [[x]] Tr (x,l,r) -> if g x then let ll = f g l @ f g r in List.map (fun l -> x::l) ll else [[]];; ( a->bool)-> a tree-> a list list Dato in input un albero e un predicato booleano restituisce tutti i percorsi dalla radice fino ai nodi che rispettano il predicato. type a tree = Empty Tr of a * a tree * a tree;; let rec f m = let aux a b c = max a (max b c) in function Empty -> m Tr (x,l,r) -> aux x (f m l) (f m r);; a -> a tree -> a Calcola il massimo tra gli elementi di un albero e un elemento m in input 3
3. (3 punti) Ridurre a forma normale le seguenti espressioni di lambda-calcolo e mostrare le riduzioni passo passo. (λx.xyz)(λz.(λx.xz)) (λz.(λx.xz))yz (λx.xy)z zy (λx.x(λw.y)x)(λz.z(xz)) (λz.z(xz))(λw.y)(λz.z(xz)) ((λw.y)(x(λw.y)))(λz.z(xz)) y(λz.z(xz)) (λx.x(λw.wy))(λy.y(yz)) (λy.y(yz))(λw.wy) (λw.wy)((λw.wy)z) (λw.wy)(zy) (zy)y 4
4. (6 punti) Segnare gli errori presenti nei seguenti programmi e fornire una descrizione del comportamento previsto in assenza degli stessi. (* 2 errori *) let rec f = function [] -> [] _::xs -> (List.hd x)::(f x);; Presa una lista di liste restituisce la lista ottenuta dalla concatenazione dei primi elementi di ogni lista. 1: Sostituire con x 2: Sostituire f x con f xs (* 2 errori *) let rec f l1 l2 = match l1,l2 with [],[] [],_ _,[] -> [] (k1,v1)::xs;(k2,v2)::ys -> if k1=k2 then (k1,v1)::(k2,v2)::(f xs ys) else k1 < k2 then f xs ((k2,v2)::ys) else f ((k1,v1)::xs) ys;; Prese due liste di coppie k,v costruisce una lista di coppie solo le due chiavi corrispondono 1. Sostituire ; con, prima di (k2,v2) 2. Aggiungere if prima di k1 < k2 (* 2 errori *) type a tree = Value of a Tr of a * a tree * a tree;; let rec children_list = function Value x -> (x,[]) Tr(l,r) -> let ll = children_list l in let lr = children_list r in let (x1,l1) = List.hd ll in let (x2,l2) = List.hd lr in (x,x1::x2::(l1@l2))::ll@lr;; Restituisce la liste (nodo,lista figli) per ogni nodo di un albero binario 1. Sostituire (x,[]) con [(x,[])] 2. Aggiungere x dopo Tr( 5
5. (6 punti) Dato un tipo colore, così definito: type a color = White of a Black of a;; e un albero colorato: type a marked tree = Empty Tr of a color * a marked tree * a marked tree;; creare una funzione color cluster: a marked tree-> a list * a list che preso in input un albero colorato restituisca due liste in cui nella prima sono contenuti tutti gli elementi di tipo White e nella seconda quelli di tipo Black. Sia dato per esempio il seguente albero let tr = Tr(White 5, Tr(Black 1, Tr(White 1,Empty,Empty), Tr(Black 3,Empty,Empty) ), Tr(White 2,Empty,Empty));; allora la chiamata color cluster tr;; restituirà - : int list * int list = ([5; 1; 2], [1; 3]) Opzionale (+ 2 punti): Costruire una funzione max points:int marked tree -> int che preso in input un albero colorato di interi restituisca il massimo tra le somme dei nodi bianchi e dei nodi neri. La chiamata max points tr;; per esempio restituirà 8. 6
let color clusters tr = match tr with Empty -> [],[] Tr (x,l,r) -> let rec aux last = function Empty -> [],[] Tr (x,l,r) -> let lw,lb = aux x l in let rw,rb = aux x r in (match x with White n -> n::(lw@rw),(lb@rb) Black n -> (lw@rw),n::(lb@rb)) in aux x (Tr(x,l,r));; Opzionale: let max points tr = let rec sum list = function [] -> 0 x::xs -> x + sum list xs in let w,b = color clusters tr in max (sum list w) (sum list b);; 7