Planche d`exos

Transcription

Planche d`exos
Université de Nice Sophia-Antipolis
Master 1 Informatique
Année 2006/2007
Module I3 - Introduction à CAML
Planche d'exercices n°2
Exercice 1. Récursivité et filtrage
1. Reprenons, avec des définitions par filtrage, certaines des fonctions récursives de l'exercice 3
de la planche n°1 :
Définir une fonction sommelst qui calcule la somme des éléments d'une liste d'entiers passée
en argument.
Définir une fonction concat qui calcule la concaténation de deux listes passées en arguments.
Définir une fonction monmap qui calcule la liste résultant de l'application d'une fonction f à tous
les éléments d'une liste l, toutes deux passées en arguments.
2. Définir, avec filtrage, une fonction ensemblep qui prend en paramètre une liste et renvoie
true si cette liste représente un ensemble (i.e. il n'y a pas de doubles) et faux sinon.
Exemples :
#
#
-
ensemblep [5;3;8;2;8] ;;
: bool = false
ensemblep [10;2;8;3;1;0] ;;
: bool = true
Définir, avec filtrage, une fonction intersection qui prend en paramètres deux listes e1 et
e2 et qui renvoie l'intersection (au sens ensembliste) de ces deux listes si elles représentent toutes
deux des ensembles, et la liste vide sinon.
Exemples :
#
#
-
intersection
: int list =
intersection
: int list =
[8;9;3] [5;3;8;2;8] ;;
[]
[8;9;3] [5;3;8;2] ;;
[8; 3]
3. Définir, avec filtrage, une fonction elts_impairs, qui renvoie la liste des éléments de rang
impair de la liste passée en argument.
Exemple :
# elts_impairs [ 'k' ; 'd' ; 't' ; 'y' ; 'z' ; 'h' ; 'o'];;
- : char list = ['k'; 't'; 'z'; 'o']
Exercice 2. Type somme et filtrage
Que se passe-t-il si vous réalisez les définitions suivantes ? Pourquoi ?
type valeur =
| Entier of int
| Reel of float
| Couple of int * int ;;
let to_int v = match v with
| Entier x -> x
| Couple (a,b) -> a;;
Donner une définition correcte pour la fonction to_int.
Exercice 3. Types somme et filtrage
Considérons des expressions arithmétiques dans lesquelles les lexèmes sont : identificateurs de
variables, constantes entières, +, - , * , / , et parenthèses gauche et droite. Une telle expression
peut être par exemple 3 * ( a - 12 )
1. Définir le type somme lexeme, à 8 constructeurs, pour les lexèmes de telles expressions.
2. Définir par filtrage une fonction toString permettant de transformer tout élément de type
lexeme en une chaîne de caractères appropriée à l'affichage.
3. Définir par filtrage une fonction listeToString permettant de transformer une liste de
lexemes en une chaîne de caractères appropriée à l'affichage.
Quelle est la liste de lexemes qui donnera comme résultat la chaîne 3 * ( a - 12 ) ?
Exercice 4. Types somme et filtrage
1. Définir un type expbool modélisant les expressions booléennes à base de connecteurs non,
ou et et. Ce type aura 4 constructeurs : Cte pour les constantes vrai et faux, Not pour les
expressions non, Or pour les expressions ou, et And pour les expressions et.
2. Définir une fonction eval pour l'évaluation de telles expressions.
Exemple :
# eval (Or (And (Cte true, Cte false), Not (Cte false))) ;;
- : bool = true
3. Modifier le type expbool pour admettre un 5ème constructeur Var pour les variables propositionnelles (une variable sera simplement représentée par un caractère).
4. Définir une fonction simplif permettant la simplification de telles expressions, en utilisant
les simplifications induites par les tables de vérité des connecteurs logiques :
non(true) = false, non(false) = true, true ou x = true (et symétriquement), false ou x = x (et
symétriquement), true et x = x (et symétriquement), false et x = false (et symétriquement).
Attention, penser que tout ceci doit se faire récursivement !
Exemple :
# simplif (Or (And (Cte true, Var 'a'), Or (Var 'b', Not (Cte true)))) ;;
- : expbool = Or (Var 'a', Var 'b')
Exercice 5. Types paramétrés et filtrage
1. Définir un type arbre modélisant les arbres binaires d'éléments d'un type quelconque 'a. Ce
type aura 2 constructeurs : Nil pour les arbres vides, et Noeud pour les noeuds de l'arbre.
2. Définir une fonction cherche permettant de rechercher un élément dans un tel arbre, en
supposant que l'arbre est un arbre binaire de recherche (optimiser la recherche). On considérera
que les éléments peuvent être comparés avec les opérateurs habituels =, < et >.
Exercice supplémentaire. (non obligatoire, pour ceux qui auraient tout fini...)
On se place dans le même contexte que dans l'exercice 3, avec le type somme lexeme, à 8
constructeurs, pour les expressions arithmétiques simples. Ces expressions arithmétiques seront
donc représentées sous forme de listes de tels lexèmes.
Définir une fonction filtrer permettant de réaliser un filtrage d'une telle expression t par
rapport à un patron p, c'est à dire une fonction répondant à la question : le terme t est-il une
instance du patron p ?
Si le filtrage réussit, cette fonction renvoie l'ensemble des substitutions permettant de passer du
patron p au terme t, par exemple :
# let p =
[ Pargauche ; Var "x" ; Moins ; Cte (-2) ; Pardroite ; Div ; Var "y" ; Plus ; Var "x" ];;
val p : lexeme list =
[Pargauche; Var "x"; Moins; Cte (-2); Pardroite; Div; Var "y"; Plus;
Var "x"]
# let t =
[ Pargauche ; Cte 3 ; Moins ; Cte (-2) ; Pardroite ; Div ; Cte 5 ; Plus ; Cte 3 ];;
val t : lexeme list =
[Pargauche; Cte 3; Moins; Cte (-2); Pardroite; Div; Cte 5; Plus; Cte 3]
# filtrer p t [] ;;
- : (lexeme * lexeme) list = [(Var "y", Cte 5); (Var "x", Cte 3)]
# let t2 =
[ Pargauche ; Var "a" ; Moins ; Cte (-2) ; Pardroite ; Div ; Cte 5 ; Plus ; Var "a" ];;
val t2 : lexeme list =
[Pargauche; Var "a"; Moins; Cte (-2); Pardroite; Div; Cte 5; Plus; Var "a"]
# filtrer p t2 [] ;;
- : (lexeme * lexeme) list = [(Var "y", Cte 5); (Var "x", Var "a")]
# let t3 =
[ Pargauche ; Cte 3 ; Moins ; Var "z" ; Pardroite ; Div ; Cte 5 ; Plus ; Cte 3 ];;
val t3 : lexeme list =
[Pargauche; Cte 3; Moins; Var "z"; Pardroite; Div; Cte 5; Plus; Cte 3]
# filtrer p t3 [] ;;
Exception: Failure "echec filtrage".
On notera que cette fonction reçoit un troisième paramètre, initialisé à la liste vide, qui sert à
accumuler les substitutions au fur et à mesure du filtrage. C'est cette valeur qui est renvoyée en
cas de succès.
Pour gérer les cas d'échec, on pourra avoir recours à la fonction failwith permettant de lever
une exception (voir http://caml.inria.fr/pub/docs/manual-ocaml/libref/Pervasives.html).
On définira toutes les fonctions annexes nécessaires.