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