Nom : RICM1-2009/2010 Prénom : Langage et Programmation 2 EXAMEN Durée : 2h, le seul document autorisé est une feuille recto-verso manuscrite de notes personnelles Le barème est indicatif pour une note sur 100 points. Partie 1 Lambda-calcul Exercice 1 : Entiers de Barendregt : 14 points On rappelle que les booléens sont définis par :V =λxy.x etf =λxy.y. On considère le codage de Barendregt pour les entiers naturels : B 0 =λp.pvv B n =λp.pfb n 1 pourn 1 1. 4 points ÉcrireB 2, etβ-réduireb 2 F. 4 points ÉcrireB 2, etβ-réduireb 2 F. B 2 =λp.pfb 1 =λp.pfλp.p Fλp.p VV On ne peut parβ-réduire, ces entiers sont en forme normales B 2 F =λp.pfb 1 F =FFB 1 =B 1 2. 3 points S = λxp.pf x définit le successeur d un entier de Barendregt. Vérifier quesb n se réduit enb n+1. Vérifier queb=λxp.pfx définit le successeur d un entier de Barendregt. BB n = λxp.pfxb n =λp.pfb n =B n+1 1
3. 4 points Définir le prédécesseurp d un entier naturel de Barendregt. Définissez le prédécesseur P d un entier naturel de Barendregt. P =λp.pf 4. 3 points Vérifier quepb n se réduit enb n 1. Vérifier quepb n se réduit enb n 1 PB n =λp.p FB n =B n F = λp.pfb n 1 F =FFB n 1 =B n 1 Partie 2 Programmation sur des listes 1 Le codage R.L.E. Run-Length Encoding 15 points Le codage R.L.E. Run Length Coding est une méthode de compression de listes très simple. Son principe est de remplacer dans une liste une suite de caractères identiques par le couple constitué du nombre de caractères identiques et du caractère. Ainsi, la liste [ a ; a ; a ; b ; a ; b ; b ] est compressée en [3, a ; 1, b ; 1, a ; 2, b ]. Exercice 2 : 8 points Écrire une fonction de décompression qui prend une liste de données compressées et retourne la liste initiale vous pouvez utiliser la concaténation append : @ de deux listes. 2
let rec expand x s = if x = 0 then [ ] else s :: expand x 1 s let rec decodage l = match l with [ ] [ ] n, e :: r expand n e @ decodage r Exercice 3 : 7 points Écrire la fonction de compression, qui prend une liste de données l et retourne la liste de données compressées par le codage R.L.E associée àl. let rec code l n e = match l with [ ] [n, e] x :: r if x = e then code r n + 1 e else n, e :: code r 1 x let codage l = match l with [ ] [ ] x :: r code l 0 x 2 Preuves Exercice 4 : 16 points Soit la fonctionf de typeαlist αlist définie par l induction suivante : f[ ] = [ ] fx :: [ ] = [ ] fx ::y ::l =x::fl Démontrer que pour toute listel, fl l 2. Rappel : l et fl désignent les longueurs des listesletfl. 3
Solution : Montrons cette propriété par récurrence forte sur la longueur de la liste. Base : l = 0 doncl=[ ]. Ainsi f[ ] = [ ] = 0 [ ] /2 = 0 OK. Soitnun entier, supposons que pour toute listelde longueurm n, fl l = 2, montrons qu alors pour toute listelde longueur n + 1, fl L = 2.Lest nécessairement de la formee ::l oùl est de longueurn. On distingue 2 cas : L =e:: [ ], alors fl = [ ] = 0 L /2 = 1/2 OK. L =e::e0 ::l0 donc fl = fe ::e0 ::l0 = e ::fl0 = 1+ fl0. Orl0 est de longueur inférieure àndonc par hypothèse de récurrence : fl0 l0 /2. Donc fl 1 + l0 /2 = 2 + l0 /2 = L /2. OK. Partie 3 Flots Exercice 5 : 15 points On considère la grammaire suivante : S CS N S ǫ N CN C 0... 9 On rappelle queǫest le mot vide. La première étoile marque l ouverture d un commentaire, la seconde marque la fermeture du commentaire, et ainsi de suite. Écrire un analyseur de flot qui prend en entrée un flot de caractères numériques et retourne le nombre de chiffres en commentaire si le programme est bien commenté tous les commentaires ouverts sont refermés, et a un comportement non spécifié sinon. 4
let rec p S = parser [ 0.. 9 ; nb = p S ] nb [ * ; nb1 = p N; * ; nb2 = p S ] nb1 + nb2 [ ] 0 and p N = parser [ 0.. 9 ; nb = p N ] nb + 1 [ ] 0 Partie 4 Module Date Exercice 6 : 20 points + 10 points facultatifs Nous voulons manipuler des dates. 1. 2 points Définir le type date, correspondant au format usuel manipulant des entiers jj/mm/aaaa. type jour = int type mois = int type annee = int type date = jour mois annee 2. 5 points Considérons l interface suivante : module type TypeOrdonne = sig type t val plus grand : t t bool end Donner un module implémentant cette interface pour les entiers. 5
module Entier : TypeOrdonne = struct type t = int let plus grand x y = x > y end 3. 5 points Étant donnés trois types ordonnésx,y etz, l ordre lexicographique surx Y Z est défini par a,b,c>d,e,f si et seulement si c> 1 f ou c =f etb> 2 e ou c =f etb=eeta> 3 d, où > 1 est l ordre surz,> 2 est l ordre sury et> 3 est l ordre surx. On considère un foncteur OrdreLex dont la signature TOrdreLexico est la suivante : module type TOrdreLexico = functor E : TypeOrdonne functor F : TypeOrdonne functor F : TypeOrdonne TypeOrdonne En instanciant OrdreLex, construire un module implémentant l interface TypeOrdonne qui compare des dates. module OrdreDate = OrdreLex Entier Entier Entier Nous supposons que nous avons la fonction estbissextile : int -> bool qui dit si une année est bissextile ou non. 4. 1 point Écrire une fonction qui donne le nombre de jours dans une année. let jourannee y = if estbisextile y then 365 else 366 5. 2 points Écrire une fonction qui donne le nombre de jours dans un mois. let joursmois m y = match m with 1 3 5 7 8 10 12 31 4 6 9 11 30 2 if estbisextile y then 29 else 28 6. 3 points Écrire une fonction qui dit si une date est valide ou non. 6
let datevalide d = let j, m, a = d in m 1 j 12 j 1 j joursmois m a 7. Sachant que 2012 est une année bissextile et que 2009 ne l est pas : 1 point Combien y-a-t-il de jours d écart entre le 14 juillet 2009 et le 15 Août 2012 du dimanche au dimanche de la semaine d après il y a 7 jours? 1+31+365+1+2 * 365 = 1128 1 point Combien y-a-t-il de jours d écart entre le 18 juin 2012 et le 15 Août 2012? 12+15+31 = 58 Facultatif 10 points Écrire une fonction qui donne le nombre de jours d écart entre deux dates. *** 7
let rec ecart d1, d2 = let j1, m1, a1 = d1 and j2, m2, a2 = d2 in if j1 < j2 then if m1 = m2 then j2 j1 + ecart j2, m1, a1, d2 else if m1<m2 then if j2 joursmois m1 a1 then j2 j1 + ecart j2, m1, a1, d2 else joursmois m1 a1 j1 + ecart 1, m1 + 1, a1, d2 else m1 >m2 j1 + ecart joursmois m1 1 a1, m1 1, a1, d2 else if j1 > j2 then if m1 = m2 then j1 j2 + ecartd1, j1, m2, a2 else if m1 < m2 then j2 + ecartd1, joursmois m2 1 a2, m2 1, a2 else m1 > m2 j1 + ecartjoursmois m1 1 a1, m1 1, a1, d2 else j1= j2 if m1< m2 then if a1 a2 then joursmois m1 a1+ ecartj1, m1+ 1, a2, d2 else a1>a2 -joursmois m2 1 a1+ecartd1, j2, m2 1, a2 else if m1>m2 then if a1 a2 then joursmois m1 a1 + ecartj1, m1 1, a1, d2 else a1 < a2 ecart j1, m1 1, a1, d2 joursmois m1 1 a1 8 else m1 = m2 if a1 < a2 then jourannee a1 + ecart j1, m1, a1 + 1, d2
Partie 5 Étoiles Exercice 7 : 25 points Nous considérons le programme suivant : let etoiles n = let compt = ref 0 in for i = 1 to n do for j =1 to i do print_string "*"; compt :=!compt +1 done; print_newline ; done; print_int!compt; print_string " etoiles";; 5 points Quel est le type de etoiles 4 et qu affiche cette instruction dans un interpréteur? Solution : Que vaut etoiles de 4? etoile 4 ; ; * ** *** **** 10 etoiles- : unit = 5 points Écrire une fonction print_ligne qui prend en paramètre un entiernet qui affichenétoiles sur une ligne. Solution : let rec print ligne n = match n with 0 print string "*" ; print ligne n 1 10 points Écrire la version fonctionnelle du programme etoiles. 9
Solution : let rec etoile n = let rec ligne nb = if nb = 0 then 0 else print string "*" ; 1 + ligne nb 1 in let rec aux nb = if nb > n then 0 else let n = ligne nb in print newline ; n + aux nb + 1 in print int aux 1; print string " etoiles" let etoiletermin n = let rec ligne acc nb = if nb = 0 then acc else print string "*" ; ligne 1+acc nb 1 in let rec aux acc nb = if nb > n then acc else let n = ligne acc nb in print newline ; aux n nb + 1 in print int aux 0 1 ; print string " etoiles" let etoile sophie n = let rec aux l nb = if l = n + 1 then print int nb; print string " etoiles" else print ligne l; print newline; aux l + 1 nb + l in aux 1 0 10