TD n 4 Rappel Filtrage 1/ Remplace une alternative : if expression = valeur then expression1 else expression2;; match expression = valeur with true -> expression1 false -> expression2;; ici le filtre est booléen if x mod 2 = 0 then "pair" else "impair";; match x mod 2 = 0 with true -> "pair" false -> "impair";; x mod 2 = 0 et true sont de type bool match expression with valeur1 -> expression1 valeur2 -> expression2;; match expression with valeur -> expression1 -> expression2;; l'expression et la valeur doivent être de même type la notation signifie dans tous les autres cas match x mod 2 with 0 -> "pair" 1 -> "impair";; Warning 8: this pattern-matching is not exhaustive. Here is an example of a value that is not matched: 2 le filtrage n'est pas défini pour tous les entiers match x mod 2 with 0 -> "pair" -> "impair";; x mod 2 et 0 sont de type int 2/ Remplace un test en cascade : if expression = valeur1 then expression1 else if expression = valeur2 then expression2 else if expression = valeur3 then expression3 else expression4;; if choix= a then action1 else if choix='b' then action2 else if choix='c' then action3 else action4;; match expression with valeur1 -> expression1 valeur2 -> expression2 valeur3 -> expression3 -> expression4;; match choix with 'a' -> action1 'b' -> action2 'c' -> action3 -> action4;;
3/ Remplace un test avec énumération de cas multiple if expression = valeur1 expression = valeur2 expression = valeur3 then expression1 else expression2;; if choix='a' choix='e' choix='i' choix='o' choix='u' choix='y' then "voyelle" else "";; match expression with valeur1 valeur2 valeur3 -> expression1 -> expression2;; match choix with 'a' 'e' 'i' 'o' 'u' 'y' -> "voyelle" -> "";; 4/ ET association de deux conditions if expression1 = valeur1 && expression2 = valeur2 then action1 else action2;; match (expression1,expresion2) with (valeur1,valeur2) -> action1 -> action2;; if yeux="marron" && cheveux="noir" then "oui" else "non";; match (yeux,cheveux) with ("marron","noir") -> "oui" -> "non";; 5/ OU association de deux conditions if expression1 = valeur1 expression2 = valeur2 then action1 else action2;; match (expression1,expresion2) with (valeur1,_) (_,valeur2) -> action1 -> action2;; if yeux="marron" cheveux="noir" then "oui" else "non";; match (yeux,cheveux) with ("marron",_) (_,"noir")-> "oui" -> "non";; 6/ Filtrage de n-uplet a. Extraire le premier élément d'un couple : let premier_element_du_couple couple = val premier_element_du_couple : 'a * 'b -> 'a = <fun> premier_element_du_couple energie1;; - : string = "bois" match couple with (a,b) -> a;; b. Extraire le second élément d'un triplet : let second_element_du_triplet triplet = match triplet with (a,b,c) ->b;; val second_element_du_triplet : 'a * 'b * 'c -> 'b = <fun> c. Création d'un couple constitué des deux premiers éléments d'un couple de triplet : let deux_premiers (triplet1,triplet2) = match (triplet1,triplet2) with ((a1,b1,c1),(a2,b2,c2)) -> (a1,a2);; val deux_premiers : ('a * 'b * 'c) * ('d * 'e * 'f) -> a * 'd = <fun>
Exercice 1 Ecrire une fonction qui associe à un entier positif, 3 fois sa valeur si l entier est multiple de 3 (il s écrit 3n), 7 fois sa valeur si l entier est multiple de 3 plus 1 (il s écrit 3n+1), 21 fois sa valeur si l entier est un multiple par 3 plus 2 (il s écrit 3n+2). Ecrire une solution qui utilise un filtre. Autrement dit Ecrire une fonction solution qui associe à un entier positif x, 3 fois sa valeur si x est divisible par 3, 7 fois sa valeur si x-1 est divisible de 3, 21 fois sa valeur si x-2 est divisible par 3. Dans cet exercice le filtrage s applique à x mod 3 let f x = match x mod 3 with 0 -> 3*x 1 -> 7*x 2 -> 21*x;; Warning P: this pattern-matching is not exhaustive. Here is an example of a value that is not matched: 3 val solution : int -> int = <fun> L interpréteur considère que le filtre x mod 3 est un entier. Il vérifie que tous les entiers sont prévus dans le filtrage et indique une anomalie potentielle car 3 n est pas prévu. Le programmeur ( à la différence de l interpréteur ) sait que le reste de la division par 3 a pour seules valeurs possibles 0 1 ou 2, néanmoins il convient ici pour éviter le warning d indiquer que le troisième cas couvre tous les autres cas avec la notation symbolique. let f x = match x mod 3 with 0 -> 3*x 1 -> 7*x -> 21*x;; val solution : int -> int = <fun> f 6;; - : int = 18 f 7;; - : int = 49 f 8;; - : int = 168
Exercice 2 Dans un filtrage un ensemble de valeurs consécutives dans un ensemble ordinal peut être remplacé par un intervalle d extrémités a et b dont la syntaxe est a.. b 1 / Ecrire une fonction booléenne qui vérifie qu un argument caractère est une des 26 lettres de l alphabet. 2 / Ecrire une fonction dont le résultat est une chaîne indiquant si un argument caractère est une voyelle, une consonne, un chiffre ou autre. 1 / let lettre c = match c with a.. z A.. Z -> true -> false;; val lettre : char -> bool = <fun> 2 / let caractere c = match c with a e i o i y -> "voyelle" A E I O U Y -> "voyelle" a.. z A.. Z -> "consonne" 0.. 9 -> "chiffre" -> "autre";; val caractere : char -> string = <fun> Les cas prévus sont analysés séquentiellement. Si un cas est rencontré, les cas suivants ne sont pas analysés. Dans cette exemple si c est une voyelle le 3ème cas n est pas analysé, il en résulte que si le 3ème cas est rencontré nous sommes en présence d une lettre qui n est pas une voyelle donc nous sommes en présence d une consonne.
Exercice 3 1 / Ecrire une fonction ttc qui calcule un prix TTC en fonction de deux arguments, le prix HT de l objet et sa catégorie 1, 2 ou 3. Les pourcentages de TVA s'appliquent en fonction de la catégorie et ont respectivement pour valeur 5%, 7% et 20%. 2 / Ecrire l appel à la fonction ttc pour un objet appartenant à la catégorie 3 dont le prix HT est égal à cinquante euros. 1 / let ttc prix categorie = match categorie with 1 -> prix *. 1.05 2 -> prix *. 1.07 -> prix *. 1.2;; val ttc : float -> int -> float = <fun> 2 / ttc 50. 3;; -: float = 60. Exercice 4 Ecrire une fonction qui à deux couples formés d une chaîne et d un entier associe la chaîne et la somme des entiers si les deux chaînes en argument sont identiques et la chaine différents et l entier nul si les chaînes ne sont pas identiques. let f c1 c2 = match (c1,c2) with (s1,x1),(s2,x2) -> if s1=s2 then (s1,x1+x2) else ("différents",0);; val f : string*int -> string*int -> string*int = <fun> let f (s1,x1) (s2,x2) = if s1=s2 then (s1,x1+x2) else ("différents",0);; val f : string*int -> string*int -> string*int = <fun> Exemples : let (a,b) = ("bois",300.);; val a : string = "bois" val b : int = 300 Utilisation du couple (a,b) pour définir les valeurs de a et de b Cette instruction ne définit pas de couple mais réalise une affectation multiple. ("bois",300);; - : string * int = ("bois",300) Evaluation interne d'un couple constitué d'une chaine de caractère et d'un entier. let energie1 = ("bois",300);; val energie1 : string * int = ("bois", 300) Définition du couple energie1 constitué de la chaine de caractère "bois" et de l entier 300 let energie2 = ("bois",500);; val energie2 : string * int = ("bois", 500) Définition du couple energie2 constitué de la chaine de caractère "bois" et de l entier 500 let energie3 = ("fuel",300);; val energie3 : string * int = ("fuel", 300) Définition du couple energie3 constitué de la chaine de caractère "fuel" et de l entier 300 f energie1 energie2;; -: string * int = ("bois", 800) f energie1 energie3;; -: string * int = ("différent", 0)
Exercice 5 1 / Ecrire une fonction qui calcule le nombre de racines réelles d'une équation du second degré. La fonction aura 3 arguments réels (les 3 coefficients de l'équation et on supposera non nul le coefficient du terme du second degré. On pourra créer des fonctions intermédiaires. 2 / Résoudre l'équation du second degré. Le résultat sera un triplet dont le premier élément est un entier qui indique le nombre de solutions de l'équation, les deux suivants sont les solutions éventuelles de l'équation.. 0 / Ecrire une fonction compare qui pour un couple donné (x,y) associe 1 si x > y 0 si x = y -1 si x < y Ici l argument est imposé, il est de la forme (x,y). Il y a un seul argument qui est un couple. let compare (x,y) = if x>y then 1 else if x=y then 0 else -1;; val compare : 'a * 'a -> int = <fun> let compare (x,y) = match x>y with true -> 1 false -> match x=y with true -> 0 false -> -1;; val compare : 'a * 'a -> int = <fun>
1 / 1a/ On aura besoin de calculer la valeur de delta pour résoudre l exercice. Ecrire une fonction delta qui calcule la valeur de delta pour une équation du second degré définie par les coefficients a b et c. Les coefficients sont des réels (les opérateurs doivent être suivis d un point, ainsi que les parties entières des réels qui apparaissent sous forme de constantes). Solution avec 3 arguments réels : let delta a b c = b ** 2. -. 4. *. a *. c;; val delta : float -> float -> float -> float = <fun> delta 1. 2. 1.;; -: float = 0. Solution avec 1 argument qui est 1 triplet de réels exprimé de manière littérale : let delta (a,b,c) = b ** 2. -. 4. *. a *. c;; val delta : float * float * float -> float = <fun> delta (1., 2., 1.);; -: float = 0. Solution avec 1 argument nommé t qui est 1 triplet de réels : let delta t = match t with (a,b,c) -> b ** 2. -. 4. *. a *. c;; val delta : float * float * float -> float = <fun> delta (1., 2., 1.);; -: float = 0. 1b/ Ecrire une fonction nombre_de_racines qui permet de calculer le nombre de racines réelles d'une équation du second degré. La fonction aura 3 arguments réels (les 3 coefficients de l'équation et on supposera non nul le coefficient du terme du second degré. On pourra créer des fonctions intermédiaires. Ecrire une fonction nombre_de_racines. La fonction aura 3 arguments réels. On a donc l en-tête : let nombre_de_racines a b c = On supposera non nul le coefficient du terme du second degré.on vérifie la condition à l aide de la fonction assert (a est un réel) : assert (a<>0.) ; Ecrire une fonction nombre_de_racines qui permet de calculer le nombre de racines réelles d'une équation du second degré.on filtrera le résultat de la fonction compare qui compare la valeur de delta à 0. afin définir le nombre de solutions.l argument de la fonction compare est un couple (, ) match compare (delta(a,b,c),0.) with (-1) -> 0 0 -> 1 -> 2;; Solution : let nombre_de_racines a b c = assert (a<>0.) ; match compare (delta(a,b,c),0.) with (-1) -> 0 0 -> 1 -> 2;; val nombre_de_racines : float -> float -> float -> int = <fun>
2 / Résoudre l'équation du second degré. Le résultat sera un triplet dont le premier élément est un entier qui indique le nombre de solutions de l'équation, les deux suivants sont les solutions éventuelles de l'équation.. On suppose que la fonction compare d intérêt général est préalablement définie. Si on suppose que les fonctions delta et nombre_de_racines sont préalablement définies. let solution (a,b,c) = let racine1 (a,b,c) = (-.b +. sqrt(delta (a,b,c)))/. (2. *. a) in let racine2 (a,b,c) = (-.b -. sqrt(delta (a,b,c)))/. (2. *. a) in match nombre_de_racines a b c with 0 -> (0,0.,0.) 1 -> (1,racine1 (a,b,c),0.) -> (2,racine1 (a,b,c),racine2 (a,b,c));; val solution : float * float * float -> int * float * float = <fun> Ici les fonctions nécessaires sont définies dans la fonction solution_globale let solution_globale (a,b,c) = let delta (a,b,c) = b ** 2. -. 4. *. a *. c in let racine1 (a,b,c) = (-.b +. sqrt(delta (a,b,c)))/. (2. *. a) in let racine2 (a,b,c) = (-.b -. sqrt(delta (a,b,c)))/. (2. *. a) in let nombre_de_racines a b c = assert (a<>0.) ; match compare (delta(a,b,c),0.) with (-1) -> 0 0 -> 1 -> 2 in match nombre_de_racines a b c with 0 -> (0,0.,0.) 1 -> (1,racine1 (a,b,c),0.) -> (2,racine1 (a,b,c),racine2 (a,b,c));; val solution_globale : float * float * float -> int * float * float = <fun> Remarque : Les fonctions racine1 et racine2 ne sont exécutées que dans le cas ou le calcul a un sens en fonction du nombre de solutions réelles de l équation du second degré. solution (1.,2.,1.);; - : int * float * float = (1, -1., 0.) solution (1.,4.,3.);; - : int * float * float = (2, -1., -3.) solution (2.,1.,4.);; - : int * float * float = (0, 0., 0.)
Exercice 6 1 / On considère des triplets contenant une chaîne et deux réels. Ecrire une fonction trans3to2 admettant x pour argument, qui transforme un tel triplet en un couple qui contient la chaîne et la somme des deux réels. Ainsi ( caml, 2.4, 5.1) est transformé en ( caml, 7.5 ) 2 / Un couple contient une chaîne et un réel. Ecrire une fonction trans2to3 admettant un seul argument, qui transforme un tel couple en un triplet qui contient la chaîne, le réel et un second réel égal à la somme du premier réel et de la longueur de la chaîne. Ainsi ( caml, 2.4 ) est transformé en ( caml, 2.4, 6.4 ) 1 / Ecrire une fonction trans3to2 admettant x pour argument. On a donc l en-tête : let trans3to2 x = Dans cet exercice x est un triplet contenant une chaîne et deux réels, il est ici nécessaire de filtrer x afin de distinguer les trois éléments constitutifs du triplet. Les noms de ces trois éléments sont choisis arbitrairement : s représente la chaîne de caractères r1 représente le premier réel r2 représente le deuxième réel On a donc le filtre : match x with (s,r1,r2) -> Il reste alors à construire le couple qui définit le résultat attendu. Le deuxième élément est une somme de réels, l opérateur est donc +. (s,r1+.r2) Solution : let trans3to2 x = match x with (s,r1,r2) -> (s,r1+.r2);; val trans3to2 : a*float*float -> a*float = <fun> Vous noterez que le type du premier élément du triplet est 'a. Dans l expression (s,r1+.r2) le type de s ne peut être déduit. Le type sera défini lors de l appel de la fonction. Exemple : trans3to2 ("caml", 2.4, 5.1);; - : string*float = ( caml, 7.5 ) 2 / Ecrire une fonction trans2to3 admettant un seul argument qui transforme un couple. On a donc l en-tête : let trans2to3 x = ou let trans2to3 (s,r) = Dans les deux cas la fonction n a qu un seul argument. Le nom de l argument n est pas imposé on peut choisir un identificateur x qui représente le couple ou exprimer le couple de manière littérale (s,r). Dans le premier cas x sera filtré afin de distinguer les deux éléments constitutifs du couple let trans2to3 x = match x with (s,r) -> let r2= r +. float_of_int (String.length s) in (s,r,r2);; val trans2to3 : string*float -> string*float*float = <fun> let trans2to3 (s,r) = let r2= r +. float_of_int (String.length s) in (s,r,r2);; val trans2to3 : string*float -> string*float*float = <fun> trans2to3 ("caml", 2.4);; - : string*float*float = ( caml, 2.4, 6.4 )