IIE - Contrôle IAP1 - Corrigé Vendredi 12 novembre 2004

Transcription

IIE - Contrôle IAP1 - Corrigé Vendredi 12 novembre 2004
IIE - Contrôle IAP1 - Corrigé
Vendredi 12 novembre 2004 - durée : 1h30
Sans documents - Calculette sans usage
Les exercices sont indépendants. Ne vous bloquez donc pas sur une question. Pour la plupart des
exercices, les questions peuvent être traitées même si les questions précédentes ne l’ont pas été.
Si nécessaire, vous pouvez utiliser les fonctions min, length, hd (tête d’une liste) et tl (reste d’une liste)
sans les redéfinir. De même pour les fonctionnelles étudiées en cours map, fold right, fold left ou filter.
Pour répondre à certaines questions, il se peut que vous ayez besoin de définir des fonctions auxiliaires.
Dans ce cas indiquez clairement ce que font ces fonctions auxiliaires en donnant par exemple leur interface.
Pour les fonctions explicitement demandées dans l’énoncé, n’écrivez leur interface que si celle-ci est
explicitement demandée dans l’énoncé.
Exercice 1 (Sur 3 points)
let rec list_hom e f l = match l with
[] -> e
| a::r -> f a (list_hom e f r);;
let qui_suis_je l = list_hom 0 (+) l;;
1. Quel est le type de la fonction list hom ?
1 point - tout ou rien. Enlever une fois pour toutes 0,5 à ceux qui mettent la réponse de
OCaml avec fun.
’a -> (’b -> ’a -> ’a) -> ’b list -> ’a
2. Écrire l’interface de la fonction qui suis je. 2 points - Enlever 0,5 si il manque les tests, 1
point si le type ou la postcondition ne sont pas justes.
interface qui_suis_je
type : int list -> int
arguments l
precondition rien
postcondition qui_suis_je l retourne la somme des éléments de l
tests qui_suis_je [], qui_suis_je [1;2;4]
Exercice 2 (Sur 5 points)
1. Ecrire la fonctionnelle takeWhile qui prend 2 arguments : un prédicat p et une liste l et qui retourne
la sous-liste préfixe de l composée d’éléments qui vérifient p :
takeWhile p [a1; a2 ...an] = [a1; ...ak] (1 ≤ k ≤ n) avec a1, . . . ak éléments qui vérifient p et
ak+1 ne vérifie pas p, =[] si a1 ne vérifie pas p.
Par exemple, takeWhile (function x -> x mod 2=0) [2; 4; 6; 5; 7; 8; 10] = [2; 4; 6] et
takeWhile (function x -> x mod 2=0) [1; 2; 4; 6; 5] = [].
1 point
let rec takeWhile p l = match l with
[] -> []
| x::r -> if p x then x::(takeWhile p r) else [];;
2. Quel est le type de la fonction takeWhile ? 1 point - tout ou rien
(’a -> bool) -> ’a list -> ’a list
1
3. Quel est le type de l’expression takeWhile ((<) 2) ? Si ce type n’existe pas, expliquez brièvement
pourquoi l’expression est mal typée. 1 point ou rien
int list -> int list
4. Démontrer que pour tout prédicat p et toute liste l, la longueur de takeWhile p l est inférieure ou
égale à la longueur de l. Vous rédigerez cette démonstration le plus clairement possible.
2 points - Vérifier que l’élève a bien écrit quel était son principe de récurrence. Attention
il y a du mélange. Mettre 0 à ceux qui ne font pas de démonstration mais écrivent ”on
voit que”.
Exercice 3 (Sur 4 points)
Dans cet exercice, on représente en OCaml la matrice

a1,1 a1,2 · · ·
 a2,1 a2,2 · · ·

 ..
 .
ap,1
ap,2
···

a1,n
a2,n 

.

ap,n
par la liste de listes
[[a1,1 ; a1,2 ; · · · a1,n ]; [a2,1 ; a2,2 ; · · · a2,n ]; · · · ; [ap,1 ; ap,2 ; · · · ap,n ]]
c’est-à-dire la liste des lignes de la matrice.
1. Définir une fonction transpose qui transpose une matrice représentée par la liste de ses lignes. On
supposera que l’argument est une liste de listes qui ont toutes la même longueur. Par exemple la
transposition de la matrice représentée par [[1; 2; 3; 4]; [1; 2; 3; 4]; [1; 2; 3; 4]] est la
matrice représentée par [[1; 1; 1]; [2; 2; 2]; [3; 3; 3]; [4; 4; 4]].
On remarquera que la première ligne de la transposée est composée des têtes des lignes de la matrice
initiale.
La fonction transpose devra autant que possible utiliser les fonctionnelles classiques sur les listes
comme map, fold right, fold left ou filter.
3 points si la solution utilise les fonctionnelles, 2 si une solution correcte sans fonctionnelle
est correcte. Si la solution n’est pas juste, je vous laisse apprécier et donner les points
en conséquence entre 0 et 1,5 points.
let rec transpose m = match m with
| [] -> []
| []::r -> []
| _ -> (List.map List.hd m)::(transpose (List.map List.tl m));;
Beaucoup d’éléves ont une solution où manque le cas []::r, d’où échec : dans ce cas j’enlève 1 point.
2. Quel est le type de la fonction transpose ?
1 point, 0,5 si pas polymorphe
’a list list -> ’a list list
Exercice 4 (Sur 8 points)
Un rationnel est constitué d’un numérateur et d’un dénominateur entiers.
On appelle valeur un entier ou un rationnel.
1. Définir le type valeur. 1 point - tout ou rien
2
type rat = {den : int ; num : int};;
type valeur = E of int | R of rat;;
ou une solution avec des couples pour les rationnels.
On souhaite définir des expressions arithmétiques construites à partir de variables munies d’un nom, de
nombres munies d’une valeur et de sommes de deux expressions.
2. Définir le type des expressions arithmétiques. 1 point - tout ou rien
type arith = Var of string |
Const of valeur | Plus of arith * arith;;
3. Représenter l’expression 34 + (y + 3).
1 point - tout ou rien - compter la réponse si le type valeur ne comportait pas de constructeur mais que le reste est bien typé.
On considérera comme bien typée l’addition de deux expressions entières ou l’addition de deux expressions
rationnelles mais pas l’addition d’une expression rationnelle et d’une expression entière.
4. Définir une fonction type expression qui, à partir d’un environnement (liste de couples associant un
nom de variable à une valeur), retourne le type d’une expression. Le cas échéant, cette fonction lève
une exception Inconnue paramétrée par le nom de la variable inconnue ou l’exception Mal typé si
l’expression est mal typée. Vous commencerez par déclarer ces deux exceptions.
Par exemple, dans l’environnement où "x" est associé à la valeur entière nulle, 34 + x est mal typée
mais dans l’environnement où "x" est associé à 27 , cette expression est bien typée. Enfin, dans
l’environnement vide, le typage de cette expression échoue avec l’exception Inconnue paramétrée par
"x".
0,5 point pour la déclaration des exceptions - 2,5 points pour la fonction Sanctionner les
copies où aucun commentaire n’est fait sur les fonctions auxiliaires.
J’ai l’impression, au vu des copies que j’ai regardées, que les élèves n’ont pas bien compris ce qui était
attendu, i.e. un résultat indiquant rationnel ou entier.
Accepter les fonctions à résultat dans string.
let type_val v = match v with
E _ -> Int | R _ -> Rat;;
exception Inconnue of string;;
exception Mal_typée;;
let rec bien_typée a env = match a with
Var s -> (try type_val (List.assoc s env ) with
Not_found -> raise (Inconnue s))
| Const c -> type_val c
| Plus (a1, a2) -> let t1 = bien_typée a1 env and t2 = bien_typée a2 env
in if t1 = t2 then t1 else raise Mal_typée;;
5. Définir une fonction évalue qui, à partir d’un environnement (défini comme précédemment), retourne
la valeur (de type valeur) résultat de l’évaluation d’une expression supposée bien typée. Par exemple,
29
dans l’environnement où "x" est associé à 27 , 34 + x s’évalue en la valeur qui représente 28
.
On ne fera aucune simplification sur les valeurs rationnelles.
2 points
3
let val_plus v1 v2 = match v1, v2 with
(E n1, E n2) -> E (n1 + n2)
| R {num=n1;den=d1},R {num=n2;den=d2} ->
R {den = d1*d2;num = n1*d2 + n2*d1}
| _ -> failwith "val_plus";;
let rec evalue a env = match a with
Var s -> (try (List.assoc s env ) with
Not_found -> raise (Inconnue s))
| Const c -> c
| Plus (a1, a2) -> let v1 = evalue a1 env and v2 = evalue a2 env
in val_plus v1 v2;;
4

Documents pareils