# CorrectionExamen2019 ## Exo 1 : typage ### Question 1 ```ocaml= f1 : int -> int ref -> int f2 : 'a -> 'a ref -> 'a ref -> unit f3 : (* int ref versus ref *) f4 : ('a ref -> bool) -> 'a ref -> unit ``` ## Exo 2 : Tak ### Question 2 ```ocaml= let rec tak x y z = if y<z then tak (tak (x-1) y z) (tak (y-1) z x) (tak(z-1) x y) else z ``` ### Question 3 ```ocaml= let table = Hashtbl.create 17 let rec tak x y z = if y<z then memo_tak (memo_tak (x-1) y z) (memo_tak (y-1) z x) (memo_tak (z-1) x y) else z and memo_tak x y z = try Hashtbl.find table (x,y,z) with Not_found -> let v = tak x y z in Hashtbl.add table (x,y,z) v ; v ``` ## Exo 3 : Evaluation ### Question 4 Initialement : ```ocaml= t = [| 0; 1; 2 |] r = { a = [| t; t |]; b = t } ``` Après `r.b.(0) <- 10` : ```ocaml= t = [| 10; 1; 2 |] r = { a = [| t; t |]; b = t } ``` Après `r.a.(0).(0) <- 4` : ```ocaml= t = [| 4; 1; 2 |] r = { a = [| t; t |]; b = t } ``` Après `r.a.(0) <- [|0;0|]` : ```ocaml= s = [| 0 ; 0 |] t = [| 4; 1; 2 |] r = { a = [| s; t |]; b = t } ``` ### Question 5 La fonction `mystere` décrémente `x` récursivement jusqu'à arriver `1`puis ajoute, à ce `1`, les anciens `x` qui ont été retenus sous `y`. ```ocaml= (* On commence par retenir y=5 qu'on ajoutera à la toute fin, avant ça on appelle mystere en décrémentant x. *) mystere 2 => x:= 2 + !x mystere 3 => x:= 3 + !x mystere 4 => x:= 4 + !x mystere 5 => x:= 5 + !x ``` On a `1+2+3+4+5=15` donc `mystere x; !x` où `x` est une référence vers `5` donne `15`. ### Question 6 ```ocaml= let f l = List.map (fun x -> incr x; if !x>2 then (ref 10) else x) l (* La fonction incr incrémente de 1 une référence entière *) ``` On peut représenter les itérations de `List.map` par les listes successives suivantes : Début : `[r ; r; r; r]` où `r -> 1` (`r` pointe vers `1`) Itération 1 : `[r ; r; r; r]` où `r -> 2` Itération 2 : `[r ; r'; r; r]` où `r -> 3` et `r' -> 10` Itération 3 : `[r ; r'; r''; r]` où `r -> 4`, `r' -> 10` et `r'' -> 10` Itération 4 : `[r ; r'; r''; r''']` où `r -> 5`, `r' -> 10`, `r'' -> 10` et `r''' -> 10` Le résultat est donc une liste contenant 4 références toutes distinctes pointant vers les valeurs `5`, `10`, `10` et `10` respectivement. ## Exo 4 : Radix ### Question 7 ```ocaml= 1=>1=>N(false,V,N(true,V,V)) 4=>100=>N(false,N(false,N(false,N(true,V,V),V),V),V) 5=>101=>N(false,V,N(false,N(false,N(false,V,N(true,V,V),V),V),V),V) 6=>110=>N(false,N(false,V,N(false,V,N(true,V,V))),V) (* mais il faut les combiner: *) let a1 = N(false , N(false, N(false, V, N(true,V,V) ), N(false, V, N(true,V,V) ) ), N(true, N(false, V, N(true,V,V) ), V )) ``` En examen, produire le dessin aurait suffit car la question est trop calculatoire. ### Question 8 ```ocaml= let rec find x t = match t with | V -> false | N (b,t0,t1) -> if x=0 then b else let r = x mod 2 in let x2 = x/2 in if r = 0 then find x2 t0 else find x2 t1 ``` ### Question 9 ```ocaml= let rec add t x = match t with | V -> add (N (false, V, V)) x | N (b, t0, t1) -> if x = 0 then N (true, t0, t1) else let r = x mod 2 in let x2 = x/2 in if r = 0 then N (b, add t0 x2, t1) else N (b, t0, add t1 x2) ``` ### Question 10 ```ocaml= let from_list l = List.fold_left add V l ``` ### Question 11 La liste l est la représentation en binaire de l'entier en base 10 que l'on veut calculer dans cette question. ```ocaml= let list_to_int l = List.fold_left (fun acc b -> 2 * acc + b) 0 l ``` ### Question 12 ```ocaml= let to_list t = let paths = ref [] in let rec tlp p t = match t with | V -> () | N (b, t0, t1) -> if b then paths := p :: !paths; tlp (0::p) t0; tlp (1::p) t1 in tlp [] t; List.map list_to_int !paths ``` ### Question 13 ```ocaml= let rec union t1 t2 = match t1, t2 with | V, t | t, V -> t | N (b1, t11, t12), N (b2, t21, t22) -> N (b1||b2, union t11 t21, union t12 t22) ``` Ou, plus concis mais moins efficace : ```ocaml= let union t1 t2 = List.fold_left add t1 (to_list t2) ```