soluzioni
Transcript
soluzioni
Cognome Nome Matricola Programmazione funzionale 22-01-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). (&);; bool -> bool -> bool String.contains;; string -> char -> bool if String.length "cia"=5 then true else "";; NT fun f [x;y;z] -> (f x y),(f z);; (’a->’a->’b)->’a list->’b * (’a->’b) fun x -> (List.hd x) @ x;; NT let f1 c d l = List.hd l = (c+d);; int -> int -> int list -> bool let f1 c d l = List.hd l = (c+d);; fun l a b -> List.filter (f1 a b) l;; int list list->int->int->int list list let f1 l = [List.hd l;List.length l];; int list -> int list let f1 l = [List.hd l;List.length l];; f1 [1;4;2;3];; [1;4] fun x l -> List.map (fun y -> y.[x]) l;; int -> string list -> char list 2. (10 punti) Per ogni programma determinare il tipo e descrivere cosa fa. Nota: i programmi sono funzionanti let f c = let rec aux count = if count > float_of_int c then 0. else 1.0/.count +. aux (count +. 1.0) in aux 1.0;; int -> float Calcola la serie armonica fino a c let rec f l1 l2 = match l2 with [] -> l1 |x::xs -> f (List.filter (fun y -> y <> x) l1) xs;; 2 ’a list -> ’a list -> ’a list Calcola la differenza tra insiemi tra l1 e l2. let f l c = let rec aux count = function [] -> count > c |x::xs -> if x = count then aux (count+1) xs else aux count xs in aux 0 l;; int list -> int -> bool Controlla che i numeri da 0 a c siano presenti in sequenza in l type ’a tree = Empty | Tr of ’a * ’a tree * ’a tree;; let rec f el = function Empty -> [] |Tr(x,l,r) -> if x < el then (f el l)@(f el r) else x::(f el l)@(f el r);; ’a -> ’a tree -> ’a list Effettua una visita in preordine dell’albero tenendo solo i nodi la cui etichetta sia maggiore o uguale a el type ’a tree = Empty | Tr of ’a * ’a tree * ’a tree;; let f tr = match tr with Empty -> true |Tr(x,l,r) -> let rec aux prev = function Empty -> true |Tr(x,l,r) -> (x > prev) && (aux x l) && (aux x r) in (aux x l)&&(aux x r);;;; 3 ’a tree -> bool Controlla ricorsivamente se le etichette dei figli sono maggiori delle etichette dei padri 3. (3 punti) Ridurre a forma normale le seguenti espressioni di lambda-calcolo e mostrare le riduzioni passo passo. (λx.xx)(λx.xy) 7→ (λx.xy)(λx.xy) 7→ (λx.xy)y 7→ yy (λz.zx)(λx.y(xx)) 7→ (λx.y(xx))x 7→ (y(xx)) (λt.tx)((λz.y(zx))(λx.xx)) 7→ (λt.tx)(y((λx.xx)x)) 7→ (λt.tx)(y(xx)) 7→ (y(xx))x 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 num_match st ch num = let rec aux c = if c = -1 then 0 else (if (st.[c]=ch) then 1 else 0) && aux (c - 1) in num_match(String.length st-1)>=num;; Controlla che il carattere ch sia presente almeno num volte nella stringa st 1: in num match con in aux 2: Sostiture && con + (* 2 errori *) let rec subs = match l with [] -> [] |x::xs -> [x]::List.map (fun l->x::l) (subs x);; (* 2 errori *) let ’a tree = Empty | Tr of ’a * ’a tree * ’a tree;; let rec b_tree c = function Empty -> Empty |(x,l,r) -> Tr(x > c, b_tree c l, b_tree c r);; Presa in input una lista genera una lista di liste con il primo elemento, il primo e il secondo e cosı̀ via. 1: Sostituire subs x con subs 2: Aggiungere l dopo rec subs Costruisce un albero di booleani in cui l’etichetta è true se la corrispondente etichetta dell’albero in input è maggiore di c e false altrimenti 1: let ’a tree con type ’a tree 2: Aggiungere Tr prima di (x,l,r) 5 5. (6 punti) Creare una funzione tree symmetry: ’a tree -> bool che preso in input un albero binario COMPLETO (ossia, in cui tutti i rami hanno la stessa altezza) cosı̀ definito type ’a tree = Empty | Tr of ’a * ’a tree * ’a tree;; restituisca true se l’albero a sinistra della radice è simmetrico all’albero a destra della radice. Sia dato per esempio il seguente albero (Opzionale (+2 punti): La soluzione scorre l’albero una volta sola). let tr = Tr(3,Tr(4,Tr(6,Empty,Empty),Tr(5,Empty,Empty)),Tr(4,Tr(5,Empty,Empty),Tr(6,Empt in disegno 3 6 4 4 5 5 6 allora tree symmetry tr;; -:bool = true Opzionale (+ 2 punti): La soluzione scorre l’albero una sola volta. let tree symmetry tr = let rec visit left = function Empty -> [] |Tr(x,l,r) -> if left then (visit left l)@[x]@(visit left r) else (visit left r)@[x]@(visit left l) in match tr with Empty -> true |Tr(x,l,r) -> 6 let ll = visit true l in let lr = visit false r in let rec equal = function [],[] -> true |x::xs,y::ys -> x = y && equal (xs,ys) | , -> false in equal (ll,lr);; 7