Explorer les Livres électroniques
Catégories
Explorer les Livres audio
Catégories
Explorer les Magazines
Catégories
Explorer les Documents
Catégories
Alain David St ephane Fechter Lucie Galand Christophe Gonzales Paul Guyot Yann Hendel Nicolas Lumineau Bruno Pagano Olivier Spanjaard Pierre-Henri Wuillemin
version du 10/09/2008
3
5 24 24 30 44 44 47 51 55 62 62 64 66 75
page 2
II
6 7 8
97
99 117 117 126 129 129 141 149 157 163 169
page 4
page 5
page 6
Q 2.1 Donnez une expression OCaml permettant de calculer la valeur de lexpression a c3 . Q 2.2 En utilisant les valeurs de lenvironnement, donnez une expression permettant dobtenir la cha ne de caract` eres la valeur de 6 fois 3.14, ` a savoir 185.754864, est stock ee dans lidentiant b . Exercice 3 (Environnements locaux) On suppose dans chaque question que lenvironnement a initialement pour valeur : E = (x,6), (y,1), (z,2), . . .. Q 3.1 D ecrivez la succession des modications denvironnement, y compris les cr eations denvironnements locaux, occasionn es par lexpression ci-dessous et donnez la valeur de cette expression : 01 let a = x + 2 and y = z + 4 in 02 let z = a + y in 03 x + a + y + z;; Q 3.2 D ecrivez la succession des modications denvironnement, y compris les cr eations denvironnements locaux, occasionn es par lexpression ci-dessous et donnez la valeur de cette expression :
page 7
01 let x = y + 1 and y = x + 2 in 02 let x = y and y = x in 03 let x = 3 and z = y and y = x in 04 y + 1;; Exercice 4 (Evolution de lenvironnement) On suppose quau d ebut de lexercice lenvironnement a pour valeur : E = (x,6), (y,1), (z,2), . . .. D ecrivez la succession des modications denvironnement, y compris les cr eations denvironnements locaux, occasionn es par le programme ci-dessous : 01 let y = x + 3;; 02 let x = 3;; 03 let a = let z = x + 5 and x = x and y = x + 3 in y + z;; 04 let b = z + 1;; 05 let c = let x = 1 in let y = x in let z = 2 in b;; Exercice 5 (Savoir utiliser la documentation OCaml) Voici deux extraits du manuel de r ef erence dOCaml. . .
page 8
Q 5.1 (Syntaxe des valeurs de type oat) float-literal ::= [-] { 0...9 }+ [. { 0...9 }] [(e|E) [+|-] { 0...9 }+] Floating-point decimals consist in an integer part, a decimal part and an exponent part. The integer part is a sequence of one or more digits, optionally preceded by a minus sign. The decimal part is a decimal point followed by zero, one or more digits. The exponent part is the character e or E followed by an optional + or sign, followed by one or more digits. The decimal part or the exponent part can be omitted, but not both to avoid ambiguity with integer literals. The interpretation of oating-point literals that fall outside the range of representable oating-point values is undened. Donnez des exemples de float. Q 5.2 (Linterpr eteur OCaml) Extrait du chapitre 9 The toplevel system (OCaml) : This chapter describes the toplevel system for Objective Caml, that permits interactive use of the Objective Caml system through a read-eval-print loop. In this mode, the system repeatedly reads Caml phrases from the input, then typechecks, compile and evaluate them, then prints the inferred type and result value, if any. The system prints a # (sharp) prompt before reading each phrase. Input to the toplevel can span several lines. It is terminated by ;; (a double-semicolon). The toplevel input consists in one or several toplevel phrases, with the following syntax : toplevel-input ::= { toplevel-phrase } ;;
page 9
toplevel-phrase ::= definition | expr | # ident directive-argument definition ::= let [rec] let-binding { and let-binding } | external value-name : typexpr = external-declaration | type-definition | exception-definition | module module-name [ : module-type ] = module-expr | module type modtype-name = module-type | open module-path directive-argument ::= nothing | string-literal | integer-literal | value-path A phrase can consist of a denition, similar to those found in implementations of compilation units or in struct. . . end module expressions. The denition can bind value names, type names, an exception, a module name, or a module type name. The toplevel system performs the bindings, then prints the types and values (if any) for the names thus dened. A phrase may also consist in a open directive (see section 6.11), or a value expression
page 10
(section 6.7). Expressions are simply evaluated, without performing any bindings, and the value of the expression is printed. Finally, a phrase can also consist in a toplevel directive, starting with # (the sharp sign). These directives control the behavior of the toplevel ; they are listed below in section 9.2. D enissez une variable a ayant pour valeur 3.4, puis deux variables b et c valant respectivement a + 1 et a + 2. D enissez deux variables d et e ayant respectivement pour valeurs a et d + 1. Testez des variantes avec let...and. Exercice 6 (Ecriture dexpressions) Q 6.1 Ecrivez une expression permettant de calculer y (x7 z )2 en eectuant le moins de multiplications possible. Q 6.2 Ecrivez une expression permettant d echanger les valeurs associ ees ` a deux identiants a et b. Par exemple, si a vaut 4 et b vaut 5, apr` es evaluation de votre expression, a vaut 5 et b vaut 4. Exercice 7 (Le jeu des 2763 erreurs) Trouvez les erreurs dans le programme ci-dessous (au d epart, lenvironnement est suppos e vide, bien que ce ne soit jamais vrai car, cest bien connu, la nature a horreur du vide) : 01 let x = 3 and y = x + 1 in y + x;;
page 11
02 03 04 05
x x x x
= = = =
3 3 3 3
y = let y = y =
Exercice 8 (Prise en main de lenvironnement Unix des salles de TME) Q 8.1 (Vous connecter en bin ome sur une machine) Mettez vous en bin ome sur nimporte quelle machine et d emarrez sous Linux si la machine est eteinte ou si elle est sous windaube. Lorsque la machine vous demande un login, lun des etudiants du bin ome tapera son num ero de carte d etudiant et, ` a linvite du password, son mot de passe imprim e sur la carte d etudiant. Conservez la session par d efaut. Cliquez 5 fois dans le bouton Suivant de lassistant dinstallation de KDE. Q 8.2 (Congurer votre compte) Pour utiliser les editeurs de texte emacs ou xemacs, vous avez besoin de chiers de conguration. Dans un terminal, tapez la commande : /Infos/lmd/2008/licence/ue/li213-2008oct/bin/install qui doit r epondre :
page 12
Installation termin ee. sinon corrigez la commande (attention ` a la majuscule de Infos ainsi quaux fautes de frappe) Q 8.3 (Utiliser l editeur xemacs) Attention : l editeur xemacs r epond ` a tout appui sur une touche du clavier ! Les caract` eres normaux sont ins er es dans le tampon d edition, les caract` eres de contr ole (un ou plusieurs) sont interpr et es comme des appels de commandes. Notations : C-X indique le caract` ere Control X obtenu en maintenant la touche Ctrl enfonc ee et en appuyant sur la touche X. M-X indique la suite de 2 caract` eres obtenu par appui sur la touche Alt puis, tout en maintenant la touche Alt enfonc ee, appui sur la touche X. Pour annuler une frappe involontaire dun (ou plusieurs) caract` ere(s) de contr ole, utilisez C-G. Q 8.3.1 (Lancer l editeur xemacs) Toujours dans le terminal, tapez la commande : xemacs & Une nouvelle fen etre sache avec le logo xemacs. Il est d econseill e de louvrir en plein ecran, sa largeur initiale de 80 colonnes doit etre respect ee pour une impression correcte sur papier. De plus, vous aurez aussi besoin de g erer dautres fen etres sur le bureau. Prenez donc lhabitude de ne pas d epasser 80 caract` eres
page 13
sur une ligne dans vos chiers. En revanche, vous pouvez maximiser sa taille verticale en cliquant, avec le bouton central de la souris dans le bouton de changement de taille de la fen etre, bouton central ` a lextr emit e droite de la barre de titre de la fen etre xemacs. Remarquez la ligne du bas de la fen etre xemacs, appel ee mini-buer, o` u l editeur communique avec vous par messages. Q 8.3.2 (Cr eer un nouveau chier pour OCaml) Dans le menu d eroulant Fichier, s electionner le sous menu Ouvrir. . . (Fichier Ouvrir. . .) ou cliquez sur lic one Open ` a gauche dans la barre doutils (troisi` eme m ethode pour les hackers en herbe : taper C-x C-f). Dans le mini-buer, compl etez la ligne par le nom du chier pour obtenir : ~/li213-2008oct/tme1.ml puis appuyez sur la touche Entr ee. Lextension .ml du nom du chier active automatiquement le mode Tuareg (en rouge dans la barre inf erieure), sp ecialis e pour travailler avec OCaml. Vous pouvez entrer une phrase telle que let a = 3 ;; suivie par Entr ee. Q 8.3.3 (Sauvegarder le chier) Cliquez sur le bouton Save ou s electionner avec la souris : Fichier Enregistrer tme1.ml
page 14
(pour les hackers en herbe, on pr ef erera taper C-x C-s plut ot que de suser le poignet ` a cliquer sur la souris). Q 8.3.4 (Lancer OCaml sous xemacs) Dans la barre de menus, s electionner le menu puis les sous-menus : Tuareg Interactive Mode Run Caml Toplevel La fen etre xemacs se divise en deux : en haut : la fen etre d edition du chier tme1.ml, en bas, une fen etre d edition communiquant avec un processus OCaml. Vous pouvez : soit entrer des phrases dans la fen etre du bas apr` es le dernier prompt (#) OCaml, soit envoyer une phrase de la fen etre du haut ( editant tme1.ml) vers la fen etre du bas OCaml. Pour ce dernier choix, s electionner avec la souris le menu : Tuareg Interactive Mode Evaluate Phrase ou tapez le raccourci clavier C-C C-E (signiant : avec la touche Ctrl maintenue enfonc ee, tapez sur les touches C puis E). Vous pourrez sauvegarder ult erieurement une trace de votre travail en sauvegardant le contenu de la fen etre inf erieure OCaml dans un chier (par exemple tme1.trace). Avec cet environnement, vous allez pouvoir entrer des phrases (au sens OCaml) dans la fen etre du haut et lire la r eponse de OCaml ` a ces phrases dans la fen etre du bas.
page 15
Q 8.3.5 (Consulter la documentation en ligne dOCaml) S electionnez, avec la souris Tuareg Reference Manual... et attendez louverture de votre browser sur lintroduction du manuel OCaml. Vous pouvez enregistrer un signet pour cette page que vous aurez souvent ` a atteindre. . . Dans la suite du TME, des commentaires vous indiquent des recherches ` a eectuer dans cette documentation. Exercice 9 (Essai du langage OCaml) Entrez les phrases propos ees ci-dessous et analysez les r eponses dOCaml avec vos connaissances du cours. Vous pouvez compl eter et approfondir ces essais. . . Les portions de texte comprise entre (* et *) sont des commentaires en syntaxe OCaml. Q 9.1 (Le type int et ses expressions) (* la syntaxe : cf doc -> Part II -> The Objective Caml language -> Lexical conventions -> Integer literals *) 12 ;; -6 ;; (* les expressions : cf doc -> Part V -> Index of modules -> Pervasives -> Integer arithmetic *)
page 16
12 - 4 ;; 3 * 2 ;; 3 / 5 ;; 7 / 2 ;; 7 / 0 ;; 7 mod 3 ;; 8 mod 3 ;; 9 mod 3 ;; -7 / 3 ;; -7 mod 3 ;; -8 / 3 ;; (* les priorit es : cf doc -> Part II -> The Objective Caml language -> Expressions -> tableau des op erateurs *) 12 - 4 + 3 ;; 12 - (4 + 3) ;; 6 / 2 * 3 ;; 6 / (2 * 3) ;; 1 + 3 * 2 ;; (1 + 3) * 2 ;; 1 - 3 / 2 ;; (1 - 3) / 2 ;;
page 17
(* les constantes et fonctions : cf doc -> Part V -> Index of modules -> Pervasives -> Integer arithmetic *) max_int ;; max_int + 1 ;; min_int ;; min_int -1 ;; max_int * 2 ;; succ ;; succ 0 ;; pred ;; pred 0 ;; abs ;; abs (-3) ;; Q 9.2 (Le type oat et ses expressions) (* la syntaxe : cf doc -> Part II -> The Objective Caml language -> Lexical conventions -> Floating-point literals *) 0.3 ;; 3. ;; .3 ;; 1.5 ;;
page 18
1e-3 ;; (* les expressions : cf doc -> Part V -> Index of modules -> Pervasives -> Floating-point arithmetic *) 2. +. 3.5 ;; 2 +. 3.5 ;; 2 + 3.5 ;; 3.5 /. 2. ;; 3. /. 2 ;; 2.0 /. 0.0 ;; -2.0 /. 0.0 ;; 0.0 /. 0.0 ;; 2. ** 3. ;; abs_float ;; abs_float (-3.2) ;; sqrt ;; sqrt 4.0 ;;
(* Vous pouvez tester les priorit es - m^ eme principe que pour les entiers. * Q 9.3 (Le type bool) (* les constantes : cf doc -> Part II -> The Objective Caml language
page 19
-> Values -> Variant values *) true ;; false ;; (* les expressions : cf doc -> Part V -> Index of modules -> Pervasives -> Boolean operations *) not ;; not true ;; ( && ) ;; true && false ;; ( || ) ;; true || false ;; Q 9.4 (Les comparaisons) (* cf doc -> Part V -> Index of modules -> Pervasives -> Comparisons *) ( < ) ;; 2 < 3 ;; 2 = 4 ;; 2 <> 4 ;; 2. >= 4. ;; 2 < 3.0 ;; true > false ;;
page 20
"grumph" < "schmurtzouille";; Q 9.5 (Le type char) (* la syntaxe : cf doc -> Part II -> The Objective Caml language -> Lexical conventions -> Chracter literals *) A ;; \n ;; (* les fonctions : cf doc -> Part V -> Index of modules -> Pervasives -> Caracter operations *) int_of_char ;; char_of_int 10 ;; a > A ;; Q 9.6 (Le type string) (* la syntaxe : cf doc -> Part II -> The Objective Caml language -> Lexical conventions -> Strings literals *) "Bonjour " ;; "Monsieur\n" ;; "Bonjour " ^ "Madame\n" ;; print_string ("Bonjour " ^ "Madame\n") ;;
page 21
print_string "Bonjour " ^ "Madame\n" ;; print_string 4;; Q 9.7 (Lier un nom ` a une valeur)
(* D efinition globale : cf doc -> Part III -> The toplevel system (ocaml) * let a = 10 ;; a ;; let b = 3.0 ;; b ;; float_of_int a +. b ;; let souhait = "Bonjour " and dest = "tout le monde\n" ;; let message = souhait ^ dest ;; print_string message ;; (* par_10 n retourne n * 10 *) let par_10 n = n * a ;; par_10 2 ;; let a = 100 ;; a ;; par_10 3 ;;
page 22
Exercice 10 (Terminer une session de TME) Enregistrez votre chier tme1.ml : cliquez dans la fen etre sup erieure puis dans le bouton Save (ou bien tapez C-x C-s). Vous pouvez sauvegarder la trace de vos essais : cliquez dans la fen etre inf erieure puis dans le bouton Save. Dans le mini-buer, xemacs vous demande un nom de chier : tapez par exemple tme1.trace puis appuyez sur la touche Entr ee. Activez avec la souris Fichier Exit XEmacs (ou bien, pour les etudiants sensibles du poignet, taper plut ot C-x C-c). R epondez aux eventuelles questions pos ees dans le mini-buer. Ouvrez un browser web et faites en sorte que vos connexions internet passent par le proxy SOCKS de lUFR, proxy.infop6.jussieu.fr : pour cela, dans refox, cliquez sur litem Pr ef erences du menu Edit puis, dans le menu General du popup ainsi ouvert, cliquez sur Connexion settings . S electionnez manual proxy conguration et tapez dans la rubrique SOCKS Host le nom du serveur, proxy.infop6.jussieu.fr, et indiquez ` a droite le port 1080. Cliquez sur OK. Vous pouvez maintenant vous connecter sur des pages ou` ebes sur Internet. Chargez maintenant la page du module Types et Structures : http://www-desir.lip6.fr/~gonzales/teaching/li213-2008oct et s electionnez la rubrique compte-rendu . Vous voyez la page de soumission des TME. Acceptez tous les cookies si on vous le demande et remplissez les renseignements
page 23
qui vous sont demand es. En particulier, renseignez le champ Compte-rendu avec le bouton Parcourir et s electionnez votre chier li213-2008oct/tme1.ml. Eectuez la soumission avec le bouton Envoyer. Lisez la r eponse de soumission pour vous assurer que celle-ci a bien fonctionn e. Fermez toutes les autres applications eventuellement ouvertes, conservez le terminal console. Terminez votre session : bouton rouge ` a droite de la barre de t aches ou menu K (` a lextr eme gauche) Quitter lenvironnement. Dans la fen etre de conrmation, s electionnez Vous connecter sous un autre nom puis OK.
page 24
2. Les fonctions
2 Les fonctions
2.1 Les fondamentaux
Exercice 11 (Fonctions myst` eres) Inf erez les signatures des fonctions suivantes : let mystere1 x = print_string x;; let mystere2 x y = sqrt (x (int_of_float y));; let mystere3 x y = y +. float_of_int x;; let mystere4 x = if x then print_string "mystere" else ();; let mystere5 v w x y z = String.fill w x y z; String.contains w v;; On saidera des extraits suivants du manuel OCaml (trouv es dans les modules Pervasives et String) : val print_string : string -> unit Print a string on standard output. val sqrt : float -> float Square root. val float_of_int : int -> float Convert an integer to oating-point.
page 25
val fill : string -> int -> int -> char -> unit String.ll s start len c modies string s in place, replacing the characters number start to start + len - 1 by c. Raise Invalid argument if start and len do not designate a valid substring of s. val contains : string -> char -> bool String.contains s c tests if character c appears in the string s. Exercice 12 (Moyenne de trois nombres) D enissez une fonction moyenne3 telle que (moyenne3 a b c) retourne la moyenne arithm etique des trois r eels a, b et c. Donnez deux exemples dapplication de cette fonction ` a des valeurs. Exercice 13 (Moyenne pond er ee de trois nombres) Q 13.1 D enissez une fonction moy3p telle que (moy3p p1 p2 p3 n1 n2 n3) retourne la moyenne pond er ee des trois nombres r eels n1, n2 et n3 avec les poids r eels respectifs p1, p2 et p3. Q 13.2 Utilisez une application partielle de la fonction moy3p pour d enir une fonction er ee des trois nombres moyp 235 telle que (moyp 235 a b c) retourne la moyenne pond a de poids 2, b de poids 3 et c de poids 5.
page 26
2. Les fonctions
Exercice 14 (Nombre de digits dun entier) En vous aidant de la fonction log10 : float -> float (qui renvoie le logarithme en base 10 dun nombre quelconque), d enissez une fonction nb_digits : int -> int telle que, pour tout n entier positif, (nb digits n) renvoie le nombre de digits de n (autrement dit, le nombre de chires utilis es pour repr esenter n en base 10). Exercice 15 (Evaluation dun polyn ome) Q 15.1 D enissez une fonction poly telle que (poly x) retourne la valeur r eelle du polyn ome 2x3 3x2 + 4x + 1. Vous prendrez soin de minimiser le nombre de multiplications (sch ema de Horner). Q 15.2 D enissez une fonction poly2 telle que (poly2 x) retourne la valeur r eelle du polyn ome 4x4 + 3x2 + 1. Utilisez une liaison locale : let nom = expression1 in expression2 pour minimiser le nombre de multiplications. Q 15.3 D enissez une fonction trinome telle que (trinome a b c x) retourne la valeur r eelle en x du trin ome du second degr e ax2 + bx + c.
page 27
Utilisez une application partielle de cette fonction trinome pour d enir une fonction value telle que (value x) retourne la valeur du trin ome 3x2 5x + 3. Exercice 16 (Pr edicats) Q 16.1 D enissez une fonction pair : int -> bool telle que (pair n) retourne true si et seulement si lentier n est pair. Q 16.2 D enissez, de deux fa cons di erentes, en utilisant la fonction pr ec edente pair, le pr edicat impair : int -> bool tel que (impair n) retourne true si et seulement si lentier n est impair. Indications : un entier n est impair si et seulement si il nest pas pair. un entier n est impair si et seulement si son successeur est pair. Exercice 17 (Fonctions curri ees) Q 17.1 En ne faisant appel qu` a des fonctions ` a un seul param` etre (ce proc ed e est appel e currication), d enissez une fonction f telle que (f x y z t) renvoie x w y + z . ` laide de la fonction f, et en ne faisant appel qu` a des fonctions ` a un seul Q 17.2 A param` etre, d enissez une fonction g telle que (g x y) renvoie 2y + z .
page 28
2. Les fonctions
Exercice 18 (Fonctionnelles) On appelle fonctionnelle une fonction dont la valeur de retour est une fonction. OCaml permet d ecrire des fonctionnelles de la m eme mani` ere que les fonctions usuelles. Q 18.1 D enissez une fonction plus x telle que (plus x x) retourne une fonction qui, appliqu ee ` a un entier y , retourne x + y . Q 18.2 D enissez une fonction plus telle que (plus x y ) retourne la valeur de x + y . La comparer ` a la fonction plus x et ` a la fonction (+) associ ee ` a lop erateur inxe +. Q 18.3 D enissez une fonction itere2 telle que (itere2 f x) retourne la valeur de f (f (x)). Q 18.4 D enissez une fonction double, ` a laide de itere2 et plus x, telle que (double x) retourne le double de lentier x. Exercice 19 (Nombre de racines dune equation du second degr e) Q 19.1 D enissez une fonction nb_rac_s : float -> float -> float -> string ne de caract` eres pr ecisant le nombre de telle sorte que (nb rac s a b c) retourne une cha de solutions r eelles de l equation ax2 + bx + c = 0. Q 19.2 D enissez une fonction nb_rac : float -> float -> float -> int telle
page 29
que (nb rac a b c) retourne le nombre de solutions r eelles de l equation ax2 + bx + c = 0. Comment traiter correctement le cas o` u le coecient a est nul (l equation nest pas du second degr e !) ? Exercice 20 (Prix hors taxe et TTC) Q 20.1 Ecrivez la sp ecication et une d enition de la fonction prix ttc telle que e au centime deuro inf erieur, dun (prix ttc taux pht) retourne le prix TTC, tronqu objet de prix hors taxe pht exprim e en euro et soumis ` a la taxe de taux taux exprim e en pourcentage (19,6%, 5,5%. . .). Par exemple, (prix ttc 19.6 100.0) renverra 119.6. Indication : cherchez dans la documentation une fonction de type float -> float retournant la valeur, en virgule ottante, du plus grand entier inf erieur ou egal au param` etre donn e (si, si . . . elle existe !). Q 20.2 Ecrivez quelques expressions v eriant de fa con claire et signicative que la programmation de votre fonction est correcte. Q 20.3 Ecrivez la sp ecication et une d enition, par application partielle, de la fonction e au centime deuro prix 196 telle que (prix 196 pht) retourne le prix TTC, tronqu inf erieur, dun objet de prix hors taxe pht exprim e en euro et soumis ` a la taxe de 19,6%. quelques expressions permettant de tester cette seconde fonction. Q 20.4 Ecrivez
page 30
2. Les fonctions
Exercice 21 (Jour dune date) On repr esente une date par la donn ee de 3 entiers, dans lordre : j repr esentant le quanti` eme du mois (1, 2, 3. . .), m repr esentant le num ero du mois (1 pour janvier, 2 pour f evrier. . .), a repr esentant une ann ee comprise entre 1901 et 2099 inclus (dans ce domaine, toutes les ann ees divisibles par 4 sont bissextiles y compris 2000). Q 21.1 D enissez un pr edicat valide : int -> int -> int -> bool tel que (valide j m a) retourne true si et seulement si les donn ees j, m et a correspondent ` a une date valide comprise entre le 1er Janvier 1901 et le 31 D ecembre 2099 inclus. Q 21.2 Le 1er Janvier 1901 tombait un mardi. On veut d enir une fonction jour : int -> int -> int -> string telle que (jour j m a) : retourne, lorsque la date repr esent ee par ces trois param` etres est valide, le jour de la semaine correspondant ` a cette date sous forme de string : lundi, mardi. . . ou sinon l` eve lexception (Invalid argument "date invalide"). Pour v erication de votre programmation, vous pouvez utiliser la commande unix cal (man cal).
page 31
page 32
2. Les fonctions
Q 23.3 Comparez les valeurs retourn ees par ces deux fonctions pour quelques valeurs de leur param` etre. Exercice 24 (Somme des inverses) Ecrivez une d enition de la fonction somme inverse telle que (somme inverse n) retourne la somme, pour i variant de 1 ` a n, des inverses de i. Quel type choisissez-vous pour le r esultat de cette fonction ? Exercice 25 (R ep etition dune cha ne) Ecrivez une d enition de la fonction repete telle que, lorsque s est une cha ne de caract` eres et n un entier naturel, (repete s n) retourne la concat enation de n r ep etitions de la cha ne s. Exercice 26 (R ecurrence sur l ecriture des entiers) Q 26.1 Soit n un entier naturel et rk rk1...r0 sa repr esentation en base b de sorte que : n = rk bk + rk1bk1 + . . . + r0. On pose q0 = rk bk1 + rk1bk2 + . . . + r1 et donc n = q0b + r0.
page 33
Quelles sont les expressions OCaml permettant de calculer q0 et r0 en fonction de n et de b ? Q 26.2 Ecrivez ee ` a un entier naturel n, une fonction somme chiffres qui, appliqu retourne la somme des chires de sa repr esentation d ecimale. Ecrivez une fonction etendant somme chiffres aux entiers relatifs. une d enition de la fonction to octal telle que, pour tout entier naturel Q 26.3 Ecrivez esentation en base 8 de n. n, (to octal n) retourne la repr Exercice 27 (R ecurrence sur une cha ne de caract` eres) Ecrivez une d enition de la fonction est dans de type char -> string -> bool telle que (est dans c s) retourne true si et seulement si le caract` ere c a au moins une occurrence dans la cha ne s. Exercice 28 (Compte ` a rebours) Q 28.1 Ecrivez une d enition de la fonction rebours telle que, lorsque n est un entier naturel : (rebours n) renvoie la cha ne "n,n-1,...,0." si n > 0, (rebours n) l` eve lexception Failure "pas le temps" si n = 0.
page 34
2. Les fonctions
une d enition de la fonction repete telle que, lorsque s est une cha ne de Q 28.2 Ecrivez caract` eres et n un entier naturel, (repete s n) retourne la concat enation de n r ep etitions de la cha ne s. une d enition de la fonction rebours successifs telle que, lorsque n Q 28.3 Ecrivez ne compos ee et p sont des entiers naturels, (rebours successifs n p) renvoie la cha de p comptes ` a rebours successifs ` a partir de n. Exercice 29 (Polymorphisme) Donnez les signatures des fonctions suivantes : fun g x y -> g x y, fun f g h x -> g (h x), fun f g h x -> h x + g h, fun f g h x y z -> g x y z + h (g x y z). Exercice 30 (Fonctions mutuellement r ecursives) Q 30.1 Ecrivez deux d enitions mutuellement r ecursives des fonctions : mul3 : int -> bool et pas_mul3 : int -> bool telles que, lorsque n est un entier naturel strictement sup erieur ` a 3, (mul3 n) renvoie true si et seulement si n est un multiple de 3 et (pas mul3 n) renvoie true si et seulement si
page 35
n nest pas un multiple de 3. deux fonctions mutuellement r ecursives Q 30.2 Ecrivez ping : int -> unit et pong : int -> unit telles que, pour n un entier naturel, (ping n) ache une s equence ping pong ping... de longueur n et (pong n) ache une s equence pong ping pong... de longueur n. Exercice 31 (M ethode de la s ecante) La m ethode de la s ecante est un algorithme permettant de trouver des approximations des racines dune fonction d erivable ` a valeurs r eelles. Cette m ethode consiste, ` a partir dun point x0 proche dune racine, ` a it erer : xn+1 f (x n ) = xn f (x n )
o` u f (xn) est estim ee par (f (xn + ) f (xn))/. Si x0 est un point proche dune racine , alors la suite (xn) va converger vers . Q 31.1 Ecrivez une d enition de la fonction secante : (float -> float) -> float -> float -> float telle que secante f x epsilon renvoie lapproximation ` a epsilon pr` es de la racine de la fonction f obtenue par application de la m ethode de la s ecante ` a partir de x.
page 36
2. Les fonctions
Q 31.2 Assurez-vous du bon fonctionnement de votre fonction en v eriant que : secante (fun x -> 3.*.x*.x-.x) 1. 0.001 renvoie 0.333..., secante (fun x -> 2.*.x*.x-.x) 1. 0.001 renvoie 0.500... . Exercice 32 (Nombres premiers) La fonction suivante prend un nombre entier en argument. Elle renvoie une exception si ce nombre nest pas strictement positif, et un bool een indiquant si le nombre en question est un nombre premier sinon. let premier x = if x <= 0 then failwith "ce nombre nest pas strictement positif" else let rec iter nb = (x = nb) or ((x mod nb <> 0) && (iter (nb+1))) in iter 2;; Lorsque lon ex ecute cette fonction, iter peut etre appel ee successivement avec nb = 2, puis nb = 3, nb = 4, et ainsi de a nb = x. Or cest totalement inecace car il suite jusqu` sut dex ecuter iter jusqu` a x pour obtenir le m eme r esultat, tous les autres appels ` a iter etant superus. Modiez la fonction premier de telle sorte que iter soit appel ee pour nb variant de 2 ` a au plus y = x. Vous ferez en sorte que le calcul de y ne soit r ealis e quune seule fois. Remarque : La modication ci-dessus am eliore sensiblement la rapidit e de lalgorithme. N eanmoins, celui-ci reste tr` es inecace lorsque x est grand et il existe des algorithmes
page 37
bien plus performants pour calculer si un nombre est premier ou pas (cf. des livres sur la cryptographie). Exercice 33 (Repr esentation dun entier en chires romains) On veut obtenir la repr esentation dun entier de lintervalle 1..3999 en chires romains. Le tableau ci-dessous rappelle la valeur des lettres : I V X L C D M 1 5 10 5O 100 500 1000 D enissez une fonction romain : int -> string telle que (romain n) : retourne l ecriture en chires romains de n lorsque n appartient ` a lintervalle 1..3999, l` eve lexception (Invalid argument "romain") sinon. Exercice 34 (Cryptographie) Dans cet exercice, nous allons nous servir du module Big int de la librairie Num dont le manuel de r ef erence se trouve dans celui dOCaml 2 lignes en dessous de la standard library . Attention : si vous ne travaillez pas dans les salles machines de lUFR, Big int ne pourra pas fonctionner directement (si vous etes sur les machines de lUFR, tout fonctionnera). Il vous faudra alors eectuer les op erations suivantes pour pouvoir utiliser Big int :
page 38
2. Les fonctions
1. ouvrir une console et taper ocamlmktop -o mytop nums.cma 2. dans votre emacs, dans le menu Interactive mode , quand vous cliquez sur Run Caml Toplevel , en bas de votre fen etre, emacs vous demande en principe quel toplevel vous voulez lancer (par d efaut ocaml). Remplacer ocaml par ~/mytop. Vous aurez alors acc` es ` a Big int. Q 34.1 Ecrivez une fonction int_of_hexa_char : char -> int prenant un caract` ere repr esentant un chire en hexad ecimal et renvoyant lentier correspondant (si le caract` ere ne correspond pas ` a un chire hexad ecimal, la fonction doit lever une exception Big num que vous d enirez). Rappel sur les conversions hexad ecimal/d ecimal : hexad ecimal d ecimal hexad ecimal d ecimal hexad ecimal d ecimal hexad ecimal d ecimal 0 0 4 4 8 8 C 12 1 1 5 5 9 9 D 13 2 2 6 6 A 10 E 14 3 3 7 7 B 11 F 15 Q 34.2 Ecrivez une fonction big_num_of_hexa_string : string -> big_int qui prend en argument une cha ne de caract` eres repr esentant un nombre hexad ecimal et qui renvoie le big int correspondant. Indice : utilisez des fonctions du module Big int telles que big int of int, add big int et mult int big int.
page 39
Q 34.3 Si lon interpr` ete chaque caract` ere dune cha ne de caract` eres quelconque par son code ASCII, la cha ne peut etre elle-m eme interpr et ee comme un nombre : par exemple le code ASCII de A est 41 en hexad ecimal et celui de M est 4D, donc la cha ne MAMA peut repr esenter le nombre 4D414D41. Sachant que, dans le module Pervasives de la Core library la fonction int_of_char : char -> int renvoie le code ASCII dun caract` ere, ecrivez une fonction big_num_of_string : string -> big_int qui prend une cha ne telle que MAMA et qui renvoie le big int correspondant (ici 4D414D41). une fonction string_of_big_num : big_int -> string qui r ealise Q 34.4 Ecrivez lop eration inverse de la question pr ec edente, cest-` a-dire quelle prend un nombre tel que 4D414D41 et renvoie une cha ne telle que MAMA . Vous pourrez utiliser la fonction char_of_int : int -> char du module Pervasives qui transforme un code ASCII en le caract` ere correspondant. Q 34.5 Ecrivez une fonction power_mod : big_int -> big_int -> big_int -> big_int telle que (power mod x y n) renvoie le big int correspondant au nombre xy mod n. Le principe du calcul d erive de trois propri et es : 2. si y = z + t alors xy = xz xt ; 1. (x y ) mod n = ((x mod n) (y mod n)) mod n ;
page 40
2. Les fonctions
k i 2 , i i=0
mod n = x
i
{i:i =1} 2
Or la toute derni` ere expression est simple ` a calculer dun point de vue informatique car i i i+1 ere dutiliser lalgorithme suivant pour calculer (xy ) mod x2 = x22 = (x2 )2, ce qui sugg` n, pour x di erent de 0, ce que vous allez impl ementer : fonction power mod x y n = si y = 0 alors (xy ) mod n = 1 sinon soit z = y/2 et t = y mod 2 soit a = (x2 mod n)z mod n si t = 0 alors (xy ) mod n = a sinon (xy ) mod n = ax mod n nsi nsi
{i:i =1}
x2 mod n mod n.
mod n =
x
{i:i =1}
2i
mod n
page 41
Q 34.6 Soient les d eclarations suivantes : let p = big_num_of_hexa_string "E2EBF36A4802238953BED3D5FFD7D7E2" ^ "37CDCC27E5F5C2E5E066EDA49F831E03" and q = big_num_of_hexa_string "EBAF6FABD83502D0C6BCFDFB0B9E72962" ^ "CAEC24073FDE83D40D6DCDFB0687C43" and e = big_num_of_hexa_string "10001" and d = big_num_of_hexa_string "4016106CFCE0C5A8AD7B7E932B0655331E2290AACC196E4D" ^ "78C1F951BDAE5497AA5AEAE6F2EA16B35B88A07B3E13ED98" ^ "19BA8E3D33B760D9AF792D01D96F1E21";; let n = mult_big_int p q;; Ecrivez une fonction encrypt : string -> big_int qui prend une cha ne de caract` ere quelconque S , qui transforme S en un big int x via la fonction big num of string que vous avez ecrite pr ec edemment, et qui renvoie le big int xe mod n. Ecrivez une fonction decrypt : big_int -> string qui prend en argument un big int quelconque x, qui calcule xd mod n et qui renvoie la valeur retourn ee par votre fonction string of big num appliqu ee ` a ce nombre. Appliquez la fonction decrypt sur le r esultat renvoy e par lapplication de encrypt ` a une cha ne quelconque. Magique, non ? Vous retrouvez votre cha ne dorigine. F elicitations,
page 42
2. Les fonctions
vous venez de r ealiser un cryptosyst` eme RSA. Plus exactement, avec les nombres p et q de l enonc e, vous avez obtenu RSA 155. Lexplication de son fonctionnement se trouve ci-dessous. Explication du fonctionnement de lalgorithme : Lalgorithme propos e dans lexercice 34 est celui de RSA, lun des syst` emes de cryptographie les plus utilis es dans le monde. RSA lacronyme de Rivest, Shamir, Adlemann, ses concepteurs est un syst` eme de cl e publique/cl e priv ee. Lid ee consiste ` a utiliser deux principes simples de th eorie des nombres : 1. il est extr emement dicile de d ecomposer un grand nombre (ici n) en produit de nombres premiers (p et q ) ; par contre, connaissant des nombres premiers, il est tr` es facile de calculer leur produit ; 2. connaissant un grand nombre, il est extr emement dicile de calculer sa fonction dEuler, par contre, connaissant la d ecomposition dun nombre en facteurs premiers, il est tr` es facile de calculer sa fonction dEuler (la fonction dEuler dun nombre entier x, not ee habituellement (x), correspond au nombre de nombres, inf erieurs strictement ` a x, qui sont relativement premiers avec x, cest-` a-dire dont le PGCD avec x est egal ` a 1). Si x = pq , o` u p et q sont premiers, alors (x) = (p 1) (q 1). Lid ee de RSA est dutiliser les op erations faciles pour param etrer le syst` eme cryptographique et de ne laisser aux cryptanalystes (ceux qui veulent d ecrypter des messages qui ne
page 43
leur sont pas adress es) que les op erations extr emement complexes. RSA utilise la fonction dEuler par le biais de la formule suivante, due ` a Euler : pour tout nombre N strictement positif et tout nombre a relativement premier avec N , a(N ) 1 mod N , o` u mod repr esente lop erateur modulo . Ainsi, si lon trouve trois nombres d, e et N tels que ed 1 mod (N ), alors ed = k(N ) + 1 et donc, pour tout nombre a < N , aed a mod N = a. Le cryptage par RSA consiste simplement ` a calculer C = ae mod N , et le d ecryptage ` a calculer a = C d mod N = aed mod N pour des nombres d, e et N bien choisis. Dans RSA, le couple (N, e) constitue la cl e publique et d est la cl e priv ee, cest-` a-dire que (N, e) est connu de tout le monde mais seul le propri etaire du syst` eme cryptographique conna t d. Si quelquun essaye denvoyer un message a au propri etaire e du syst` eme, il pourra calculer C = a mod N puisque e et N sont connus de tout le monde. Par contre, comme seul le propri etaire conna t d, lui seul peut en th eorie calculer d C mod N = a. Mentionnons cependant que RSA 155 a et e cass e il y a quelques ann ees, cest-` a-dire que les nombres p et q ont pu etre retrouv es apr` es moult eorts ` a partir de N . Cependant cela ne remet pas en cause la validit e du syst` eme g en eral : simplement, maintenant, pour eviter que p et q puissent etre d ecouverts, les cl es sont plus longues (cest-` a-dire que p et q ont plus de bits).
page 44
page 45
Exercice 36 (Dossier m edical) Soit le type patient de d eclaration : type patient = {nom : string ; taille : float ; poids : float} ;; dont les el ements repr esentent un embryon de dossier m edical pour une personne. Ecrivez une implantation de la fonction anonyme telle que, lorsque p est un enregistrement de type patient, (anonyme p) retourne un nouvel enregistrement dont le champ nom ne contient plus que linitiale, en lettre majuscule, du nom de lenregistrement p et dont les champs taille et poids contiennent les m emes valeurs que les champs correspondants de p. Exercice 37 (Cercles color es) Soit le type cercle de d eclaration : type cercle = {rayon : int; mutable couleur : char};; dont les el ements repr esentent le rayon dun cercle et sa couleur. Q 37.1 D eclarez un cercle de rayon 11 et de couleur rouge (symbolis ee par le caract` ere r), un cercle de rayon 8 et de couleur verte (v), un troisi` eme cercle de rayon 3 et de couleur bleue (b) et un tableau contenant ces trois cercles.
page 46
Q 37.2 En utilisant un ltrage, ecrivez une fonction tous_rouges : cercle array -> cercle array telle que (tous rouges tab) change la couleur des cercles de tab qui ne sont pas rouges en rouge. Q 37.3 En utilisant un ltrage, ecrivez une fonction colorie : cercle array -> cercle array telle que (colorie tab) colorie un cercle en bleu sil a un rayon strictement inf erieur ` a 5, en vert sil a un rayon strictement sup erieur ` a 10, et en rouge sinon. Exercice 38 (Repr esentation dun point du plan dans un rep` ere cart esien) Q 38.1 (D eclaration dun type) D enissez un type point, enregistrement de champs x et y repr esentant respectivement labscisse et lordonn ee dun point du plan. Q 38.2 (Sym etrie par rapport ` a lorigine) Donnez la sp ecication et une d enition de la fonction sym O telle que (sym O p) retourne la repr esentation du point image du point de repr esentation p dans la sym etrie de centre O, origine du rep` ere cart esien. Q 38.3 (Sym etrie par rapport ` a laxe des ordonn ees) Donnez la sp ecication et une d enition de la fonction sym Oy telle que (sym Oy p)
page 47
retourne la repr esentation du point image du point de repr esentation p dans la sym etrie par rapport ` a laxe Oy du rep` ere cart esien.
3.2 Tableaux
Exercice 39 Q 39.1 Ecrivez une d enition de la fonction get : a array -> int -> a telle que (get tab i) retourne l el ement situ e` a lindice i du tableau tab. Q 39.2 Ecrivez une d enition de la fonction set : a array ->int -> a -> unit telle que (set tab i x) place l el ement x ` a lindice i dans le tableau tab. Exercice 40 (Tableaux dentiers) Ecrivez la fonction cree_tab : int -> int array telle que (cree tab n) cr ee un tableau de taille n et remplit ce tableau par les entiers de 1 ` a n.
page 48
Exercice 41 (Tableaux dentiers) la fonction concatene : int array -> int array -> int array Q 41.1 Ecrivez de telle sorte que (concatene t1 t2) retourne le tableau dentiers r esultant de la concat enation des tableaux dentiers t1 et t2. Q 41.2 Ecrivez la fonction f1 : int array -> int array telle que (f1 t) retourne le tableau contenant n fois chaque entier n de t. Par exemple, (f1 [|3 ;1 ;0 ;4|]) retourne [|3 ;3 ;3 ;1 ;4 ;4 ;4 ;4|]. Exercice 42 (Cha nes de caract` eres) Ecrivez une d enition de la fonction indice : char -> string -> int telle que : (indice c s) retourne la premi` ere position du caract` ere c dans la cha ne s ou 1 si le caract` ere c na pas doccurrence dans s. Exercice 43 (Cha nes de caract` eres) Etant donn e une cha ne s, on veut construire la cha ne s obtenue en repla cant tous les caract` eres de s par leur successeur modulo 256 dans le code ASCII. Donnez la sp ecication et une d enition de la fonction encode telle que (encode s)
page 49
retourne s. Exercice 44 (Cha nes de caract` eres) Etant donn e une cha ne s, on veut construire la cha ne s en ajoutant une espace derri` ere chaque point et chaque virgule de s sauf si le point ou la virgule appara t en dernier caract` ere de s. Par exemple si s vaut un,deux,trois. alors s vaut un, deux, trois. . Donnez la sp ecication ainsi quune d enition de la fonction ajoute espace telle que (ajoute espace s) retourne s. Exercice 45 (Manipulation de tableaux) une fonction permut : a array -> int -> int -> unit telle que Q 45.1 Ecrivez (permut t i j) permute les deux el ements du tableau t, dindices respectifs i et j. Q 45.2 Ecrivez une fonction find : (a -> a -> bool) -> a array -> int -> int de telle sorte que (find f t i) renvoie lindice j sup erieur ou egal ` a i dun el ement du tableau t tel que pour tout k i, (f t.(j ) t.(k )) = true. Pour comprendre ce que fait cette fonction, consid erez que f est egale ` a (<=) ou ` a (>=). Dans le premier cas, la fonction renvoie lindice de l el ement le plus petit dans la partie du tableau t commen cant ` a lindice i, et dans le second cas elle renvoie lindice de l el ement le plus grand.
page 50
une fonction tri : (a -> a -> bool) -> a array -> unit Q 45.3 Ecrivez triant les el ements dun tableau selon lalgorithme de tri par s election- echange. Ce dernier proc` ede en deux etapes pour placer chaque el ement a ` sa place d enitive : 1. la recherche de l el ement ` a placer ` a lendroit courant parmi lensemble des el ements non encore plac es ; 2. la permutation de cet el ement avec l el ement plac e actuellement ` a lendroit courant. Attention : on veut pouvoir sp ecier lors de lappel le crit` ere de tri, do` u le premier param` etre de la fonction. Exercice 46 (Repr esentation et manipulation de matrices) une fonction calculant le produit scalaire de deux vecteurs de taille n. Q 46.1 Ecrivez une fonction calculant le produit de deux matrices de taille n * n. Q 46.2 Ecrivez
page 51
page 52
une fonction qui retourne 0 si la troisi` eme composante dun triplet est Q 48.3 Ecrivez nulle, et le produit des deux premi` eres composantes sinon. Exercice 49 (Vous entrez dans la 3` eme dimension) Le but de cet exercice est de r ealiser une petite boite ` a outils (ie. un ensemble de fonctions) pour manipuler des vecteurs dans un espace r eel en 3 dimensions. Q 49.1 D enissez un type vecteur pour repr esenter un vecteur dans un espace ` a 3 dimensions. une fonction qui regarde si 2 vecteurs sont egaux. Q 49.2 Ecrivez une fonction qui additionne 2 vecteurs. Q 49.3 Ecrivez une fonction qui calcule le produit scalaire de deux vecteurs. Q 49.4 Ecrivez une fonction qui calcule le produit tensoriel (cest-` a-dire terme ` a terme) Q 49.5 Ecrivez de deux vecteurs. Dans les exercices suivants, on veut implanter une fonction calculant le quotient et le reste de la division euclidienne de deux entiers naturels. Plus pr ecis ement, on veut ecrire diverses d enitions dune fonction admettant comme param` etres un entier naturel a et et un entier
page 53
naturel non nul b et retournant le couple (q, r) tel que : a = bq + r avec 0 r < b. Exercice 50 (Version directe utilisant les op erateurs OCaml sur les entiers) une d enition de la fonction euclide de type int -> int -> int * int Q 50.1 Ecrivez telle que (euclide a b) retourne, lorsque a est un entier naturel et b un entier naturel non nul, le couple (q, r) o` u q est le quotient et r la reste de la division enti` ere de a par b. Q 50.2 Testez cette d enition. Q 50.3 Quel r esultat obtenez-vous si le param` etre b est nul ? Q 50.4 Essayez et analysez les r esultats obtenus lorsque a et b sont des entiers relatifs. Exercice 51 (Versions r ecursives) Dans la suite, on ne veut plus utiliser la division enti` ere par b (op erateurs (/) et (mod) avec b comme op erande droit). On supposera, sans v erication, que le param` etre a est un entier naturel et que le param` etre b est un entier naturel non nul.
page 54
Q 51.1 (Calcul r ecursif par soustraction du diviseur au dividende) Ecrivez une d enition r ecursive euclide1 fond ee sur la propri et e suivante : SI (a b) = bq + r avec 0 r < b ALORS a = b(q + 1) + r avec toujours 0 r < b. Dans quel cas doit-on arr eter la r ecursivit e? Testez cette d enition. Q 51.2 (Calcul r ecursif par division par deux du dividende) Ecrivez une d enition r ecursive euclide2 fond ee sur la propri et e suivante : SI (a/2) = bq + r avec 0 r < b ALORS en posant r1 = 2r si a est pair ou r1 = 2r + 1 si a est impair, on obtient a = b(2q ) + r1 avec 0 r1 < 2b et donc si r1 < b : a = b(2q ) + r1 avec 0 r1 < b ou si r1 b : a = b(2q + 1) + (r1 b) avec 0 (r1 b) < b. Dans quel cas peut-on arr eter la r ecursivit e? Dans quel cas doit-on arr eter la r ecursivit e? Testez cette d enition.
page 55
sera repr esent ee en OCaml de la mani` ere suivante : let m = [|[|1.0; 0.0; 0.0; 3.0|]; [|0.0; 0.0; 5.0; 0.0|]; [|0.0; 2.0; 0.0; 4.0|]|];; un d enition de la fonction ratio : float array -> float -> float Q 52.1 Ecrivez telle que (ratio mat r) retourne la proportion de r eel r apparaissant dans la matrice mat. Ainsi (ratio m 0.0) retournera 0.58333333333333337. Q 52.2 Pour etre consid er ee comme creuse, une matrice doit contenir une certaine proportion de 0.0 . Nous d enissons di erentes cat egories de matrices creuses :
page 56
Cat egorie 1 : les matrices pas creuses avec au plus 50% de 0.0 . Cat egorie 2 : les matrices peu creuses qui contiennent entre 50% et 70% de 0.0 . Cat egorie 3 : les matrices moyennement creuses qui contiennent entre 70% et 80% de 0.0 . Cat egorie 4 : les matrices franchement creuses qui contiennent entre 80% et 90% de 0.0 . Cat egorie 5 : les matrices totalement creuses avec au moins 90% de 0.0 . D enissez une structure permettant de d enir les intervalles associ es aux cat egories cidessus, puis ecrivez un d enition de la fonction categorie : float array -> int telle que (categorie mat) retourne la cat egorie de la matrice. Par exemple, categorie m retournera 2. Q 52.3 Il peut etre int eressant pour les analystes (les personnes devant expliquer le sens profond des donn ees collect ees et stock ees dans les matrices) de pouvoir masquer certaines valeurs. Pour cela, nous allons choisir pseudo-al eatoirement un el ement de la matrice dont la valeur nest pas egale ` a 0.0 an de la mettre ` a 0.0 . Nous choisissons de parcourir la matrice ligne apr` es ligne (en partant de la ligne dindice 0), jusqu` a trouver un el ement de valeur non egale ` a 0.0 . Q 52.3.1 On d enit le type : type indice = {mutable x:int; mutable y:int};;
page 57
pour repr esenter les indices de ligne et de colonne dune valeur non egale ` a 0.0 dans la matrice. Ecrivez une d enition de la fonction : element_non_nul : float array -> indice telle que (element_non_nul) retourne un enregistrement de indice. Ainsi, element non nul m renverra {x = 0 ; y = 0}. Si la matrice ne contient aucun el ement ` a 0, elle doit lever lexception Not found element. Q 52.3.2 Ecrivez une fonction : modif_matrice : float array -> int -> float array telle que modif matrice mat nb0 retourne la matrice mat avec nb0 el ements mis ` a 0.0 . une fonction : Q 52.4 Ecrivez modif_categorie : float array -> string -> float array telle que : (modif_categorie mat cat) modie la matrice mat, le nombre de fois n ecessaire pour que celle-ci passe de sa cat egorie initiale ` a la cat egorie sp eci ee par le param` etre s (sous r eserve que s sp ecie une cat egorie inf erieure ` a la cat egorie initiale de mat). Exercice 53 (Matrices creuses - episode II) Dans cet exercice, on veut stocker de mani` ere compacte des matrices creuses ` a deux dimensions (n p), cest-` a-dire des matrices contenant beaucoup de 0.0 . Comme nous
page 58
lavons pr ecis e auparavant, la matrice m ci-dessous : m= 1.0 0.0 0.0 3.0 0.0 0.0 5.0 0.0 0.0 2.0 0.0 4.0
peut etre repr esent ee en OCaml de la mani` ere suivante : let m = [|[|1.0; 0.0; 0.0; 3.0|]; [|0.0; 0.0; 5.0; 0.0|]; [|0.0; 2.0; 0.0; 4.0|]|];; Cependant, eectuer des op erations arithm etiques sur m telles que des produits matricesvecteurs, des additions de matrices, etc, conduirait ` a r ealiser un certain nombre dop erations inutiles (multiplications ou additions avec des 0). De plus, on utiliserait beaucoup de m emoire pour stocker peu dinformations. Pour pallier ces deux probl` emes, nous allons repr esenter dans cet exercice les matrices telles que m sous forme de listes de triplets (i, j, x) o` u i et j repr esentent les indices en ligne et en colonne des el ements de la matrice de valeurs x non nulles. Si lon pose que l el ement tout en haut ` a gauche de la matrice est dindice (0, 0), alors la matrice m ci-dessus peut etre d enie par la liste : [ (0,0,1.0); (0,3,3.0); (1,2,5.0); (2,1,2.0); (2,3,4.0) ];; Malheureusement, la liste des el ements non nuls seule ne permet pas de conna tre la taille de la matrice car les derni` eres lignes ou colonnes de celle-ci peuvent etre constitu ees uniquement de 0. Cela sugg` ere donc le type suivant pour repr esenter les matrices creuses :
page 59
type matrice = { rows : int; cols : int; elts : (int * int * float) list };; et la matrice m ci-dessus peut etre repr esent ee sans ambigu t e par : let m = {rows=3; cols=4; elts=[(0,0,1.0);(0,3,3.0);(1,2,5.0); (2,1,2.0);(2,3,4.0)]};; Q 53.1 On suppose connue une exception Dim error. Ecrivez une fonction matrice_of_array : float array array -> matrice de telle sorte que, pour toute matrice m stock ee sous forme de tableau ` a deux dimensions, lapplication (matrice of array m) renvoie l equivalent de m de type matrice (appliqu ee ` a la matrice m ci-dessus, la fonction renverrait donc m). Vous v erierez que le tableau m correspond bien ` a une matrice, cest-` a-dire que : il y a au moins une ligne et une colonne (un vecteur est une matrice d eg en er ee) ; toutes les lignes du tableau m ont le m eme nombre d el ements. Si les conditions ci-dessus ne sont pas v eri ees, votre fonction l` evera lexception Dim error. une fonction array_of_matrice : matrice -> float array array Q 53.2 Ecrivez telle que lapplication (array of matrice m) renvoie un tableau ` a deux dimensions
page 60
m.rowsm.cols correspondant ` a la matrice creuse m (dans lexemple ci-dessus, erieurs ou (array of matrice m) renverrait m). Si m.rows et/ou m.cols sont inf egaux ` a 0, ou bien si des el ements de m ne peuvent etre stock es dans le tableau de taille m.rowsm.cols, votre fonction doit lever lexception Dim error. une fonction add : matrice -> matrice -> matrice telle que (add Q 53.3 Ecrivez m1 m2) renvoie la somme des 2 matrices creuses m1 et m2. Par exemple si : m1 = alors m1 + m2 = et : let m1 = {rows=3; cols=4; elts=[(0,0,1.);(0,3,3.);(1,2,5.); (2,1,2.);(2,3,4.)]};; let m2 = {rows=3; cols=4; elts=[(0,0,3.);(0,3,(-3.));(1,1,2.); (1,2,2.);(2,1,(-2.))]};; let m12 = add m1 m2;; 1.0 0.0 0.0 3.0 0.0 0.0 5.0 0.0 0.0 2.0 0.0 4.0 et m2 = 3.0 0.0 0.0 3.0 0.0 2.0 2.0 0.0 0.0 2.0 0.0 0.0
4.0 0.0 0.0 0.0 0.0 2.0 7.0 0.0 0.0 0.0 0.0 4.0
page 61
alors : m12 : matrice = {rows=3; cols=4; elts=[(0,0,4.);(1,1,2.); (1,2,7.);(2,3,4.)]} Si les matrices m1 et m2 nont pas pr ecis ement la m eme dimension, votre fonction l` evera lexception Dim error.
page 62
4. Les listes
4 Les listes
4.1 Fonctions sur les listes retournant une valeur
Exercice 54 (Somme des el ements dune liste de r eels) Ecrivez une implantation de la fonction somme telle que (somme l) retourne la somme des r eels de la liste l. Exercice 55 (Moyenne des el ements dune liste de r eels) Ecrivez une implantation de la fonction moyenne telle que (moyenne l) retourne la moyenne des r eels de la liste l. On evitera de parcourir deux fois la liste. ement dune liste) Exercice 56 (El Ecrivez une d enition du pr edicat element tel que (element x l) retourne true si et seulement si x est un el ement de la liste l.
page 63
Exercice 57 (Indice de premi` ere occurrence dun el ement dans une liste) Ecrivez une implantation de la fonction indice telle que (indice x l) retourne lindice de la premi` ere occurrence de l el ement x dans la liste l ou l` eve lexception pr ed enie Not found si l el ement x na pas doccurrence dans l. Exercice 58 (1er indice dun el ement v eriant une propri et e) Plus g en eralement, ecrivez une implantation de la fonction pos telle que (pos p l) retourne lindice, dans la liste l, du premier el ement x de l tel que lapplication (p x) el ement de l ne retourne true ou l` eve lexception pr ed enie Not found lorsquaucun v erie le pr edicat p. Pouvez-vous donner une nouvelle d enition de indice ?
page 64
4. Les listes
page 65
l tels que lapplication (p x) retourne true. Exercice 62 (Suxe dune liste) Ecrivez limplantation dune fonction suffixe telle que (suffixe p l) retourne la queue de la liste l commen cant au premier el ement x de l tel que lapplication (p x) retourne true ou la liste vide lorsquaucun des el ements de l ne v erie le pr edicat p.
page 66
4. Les listes
page 67
entiers de la liste sont compris entre 1 et 9 (ce qui a le bon go ut d etre toujours vrai). une implantation de la fonction list telle que, lorsque k est un entier Q 63.3 Ecrivez strictement positif, (list k ) retourne la liste Lk . Exercice 64 Q 64.1 Ecrivez une fonction somme qui, etant donn e une liste de couples dentiers (x, y ), renvoie un couple contenant la somme des x dune part et la somme des y dautre part. Ainsi, (somme [(1,2) ; (3,4) ; (5,6)] renverra le couple (9,12) et somme [] renverra (0,0). une fonction somme2 qui, etant donn e une liste de listes ` a deux el ements Q 64.2 Ecrivez [x; y ], renvoie une liste contenant la somme des x dune part et la somme des y dautre part. Ainsi, (somme2 [[1 ;2] ; [3 ;4] ; [5 ;6]] renverra la liste [9 ;12] et somme2 [] renverra [0 ;0].
page 68
4. Les listes
Exercice 65 (Op erations sur les listes) Q 65.1 (Plus petit el ement dune liste) Ecrivez une d enition r ecursive de la fonction min telle que (min l) renvoie le plus petit el ement de la liste l ou l` eve lexception (Invalid argument "min") si l est la liste vide. Q 65.2 (Retournement dune liste (1) - pr eliminaire) Ecrivez une d enition de la fonction concatd telle que (concatd l x) renvoie la liste des el ements de l suivis de l el ement x en dernier. Par exemple (concatd [1 ; 2 ; 3] 4) renvoie [1 ; 2 ; 3 ; 4]. Q 65.3 (Retournement dune liste (1)) Ecrivez une d enition de la fonction miroir telle que (miroir l) renvoie la liste des el ements de l en ordre inverse. Q 65.4 (Retournement dune liste (2) - pr eliminaire) Ecrivez une fonction enation du miroir de la r ecursive mir acc telle que (mir acc acc l) renvoie la concat liste l et de la liste acc. Par exemple mir acc [4 ; 5 ; 6] [1 ; 2 ; 3] renvoie [3 ; 2 ; 1 ; 4 ; 5 ; 6]. Q 65.5 Ecrivez une nouvelle d enition de la fonction miroir utilisant la fonction mir acc.
page 69
Exercice 66 (Les listes dassociations) Une association est un couple compos e dune cl e et dune valeur. Notre objectif est de d enir une fonction assoc recherchant la valeur associ ee ` a une cl e dans une liste dassociations. Q 66.1 D enissez le type list assoc (les cl es et les valeurs peuvent etre a priori de nimporte quel type !). Ecrivez une valeur de ce type. Q 66.2 Ecrivez la fonction assoc prenant une cl e et une liste dassociations et retournant une valeur associ ee ` a la cl e dans la liste. La fonction l` evera lexception pr ed enie e est absente. Not found si la cl Q 66.3 Ecrivez ees ` a une cl e la fonction assoc all retournant toutes les valeurs associ donn ee. En cas dabsence, on continuera ` a lever lexception Not found. Exercice 67 (Les polyn omes) Dans cet exercice, les polyn omes a0 + a1x + a2x2 + . . . + anxn sont repr esent es par la liste de leurs coecients : [a0 ; a1 ; a2 ; ... ; an]. Tous les coecients ai sont de type float et le dernier coecient an est par hypoth` ese
page 70
4. Les listes
non nul. Le polyn ome nul est repr esent e par la liste vide []. Q 67.1 (Valeur dun polyn ome) Ecrivez une implantation de la fonction eval poly telle que (eval poly p x) retourne la valeur du polyn ome associ e` a la liste p en x. Q 67.2 (Ecriture dun polyn ome) Donnez une d enition de la fonction string of poly telle que (string of poly l) retourne l ecriture du polyn ome repr esent e par la liste l, ecriture ordonn ee suivant les puissances croissantes de la variable x (en bonus : avec un traitement particulier pour les coecients 0. et 1.). Par exemple : # # string_of_poly : string = "3. string_of_poly : string = "3. [3.;4.;5.];; + 4.x + 5.x^2" [3.;0.;1.];; + x^2"
Q 67.3 (Addition de deux polyn omes) Ecrivez une d enition de la fonction add poly telle que, lorsque l1 et l2 sont deux listes repr esentant respectivement deux polyn omes p1 et p2, (add poly l1 l2) retourne la liste repr esentant le polyn ome p1 + p2. Q 67.4 (Multiplication dun polyn ome par un scalaire) Ecrivez une d enition de la fonction mult telle que, lorsque l est une liste repr esentant le
page 71
polyn ome p, (mult u l) retourne la liste repr esentant le polyn ome r esultat de la multiplication du polyn ome p par le scalaire u de type float. Q 67.5 Ecrivez une d enition de la fonction mult x telle que, lorsque l est une liste esentant le repr esentant le polyn ome en x nomm e p, (mult x l) retourne la liste repr polyn ome p multipli e par sa variable x. Q 67.6 (Produit de deux polyn omes) Ecrivez une d enition de la fonction mult poly telle que, lorsque l1 et l2 sont deux listes repr esentant respectivement deux polyn omes p1 et p2, (mult poly l1 l2) retourne la liste repr esentant le produit des polyn omes p1 et p2. Q 67.7 (Polyn ome d eni par ses z eros) Ecrivez une d enition de la fonction poly 0 telle que, lorsque l est une liste [a1 ; a2 ; esentant le po... ; an] d el ements de type float, (poly 0 l) retourne la liste repr lyn ome en x : (x - a1)(x - a2)...(x - an). Exercice 68 (Les dominos) On repr esente un domino par un couple de type int * int. La valeur dun c ot e du domino correspond au nombre de points noirs grav es sur ce c ot e (de 0 ` a 6).
page 72
4. Les listes
Q 68.1 (Nombre de dominos) Quel est le nombre de pi` eces dun jeu de dominos ? D eclarez le nom nb dom li e` a cette constante. Q 68.2 (Lensemble des dominos) Ecrivez une d enition de la fonction create_doms : unit -> (int * int) array telle que lapplication (create doms ()) retourne un tableau contenant tous les dominos du jeu. e` a un tel tableau. D eclarez le nom les dominos li Q 68.3 (La pioche) ` un instant du jeu, un certain nombre de dominos ont d A ej` a et e tir es (distribu es ou pioch es), les autres restent sur la table, faces cach ees. Pour repr esenter cet etat, on d enit le type enregistrement suivant : type pioche = {doms : (int * int) array ; mutable nb : int}. etiquette Dans cet enregistrement, l etiquette doms m emorisera le tableau les dominos et l nb une r ef erence sur le nombre de dominos non encore tir es. Le tableau d etiquette doms reste une permutation de lensemble des dominos. Lordre des dominos dans ce tableau est tel que les dominos non tir es sont m emoris es dans les el ements dindice 0 ` a nb - 1 inclus, les dominos d ej` a tir es etant stock es dans les el ements dindice nb ` a nb doms - 1 inclus.
page 73
Q 68.3.1 (La pioche dans l etat initial) D eclarez lidentiant la pioche li e` a une valeur de type pioche repr esentant l etat du jeu lorsquaucun domino na encore et e tir e. Q 68.3.2 (La pioche vide) Ecrivez une d enition de la fonction est vide telle que (est vide p) retourne true si et seulement si p est une pioche o` u tous les dominos ont et e tir es. Q 68.3.3 (Tirage al eatoire dun domino de la pioche) Ecrivez une d enition de la fonction pioche telle que (pioche p) : l` eve lexception Failure "pioche" si la pioche est vide ou choisit al eatoirement un entier n compris entre 0 inclus et le nombre de dominos non tir es de la pioche p exclu, d ecr emente le nombre nb de dominos non tir es dans la pioche p, echange, dans le tableau p.doms, le domino d dindice n et le domino dindice nb et retourne le domino d tir e al eatoirement. Q 68.3.4 (R einitialisation dune pioche) Ecrivez une d enition de la fonction melange : pioche -> unit telle que (m elange p) modie la pioche p pour quelle repr esente une pioche initiale o` u aucun domino nest tir e.
page 74
4. Les listes
Q 68.3.5 (Utilisation de la pioche) Ecrivez une expression qui retourne la liste des tirages successifs de la pioche tant que celle-ci nest pas vide. R einitialisez la pioche. Q 68.4 (Distribution des dominos) On veut initialement distribuer al eatoirement 3 dominos a ` 4 joueurs. Q 68.4.1 Ecrivez une d enition de la fonction distribue telle que (distribue p) : eectue le m elange des dominos de la pioche p (aucun domino tir e) puis retourne un tableau de 4 listes de 3 dominos tir es au hasard dans la pioche p. Q 68.4.2 Appliquez la fonction distribue ` a la pioche. V eriez la valeur de la pioche.
page 75
5 Types somme
Exercice 69 (Simulation du type des bool eens avec des types sommes) Q 69.1 D enissez le type somme my booleen pour repr esenter les bool eens. Q 69.2 D enissez la fonction my not : my booleen -> my booleen an de retourner la valeur inverse du bool een donn ee en argument. Q 69.3 D enissez la fonction my and : my booleen -> my booleen qui retourne le et logique des deux arguments. Q 69.4 D enissez la fonction my or : my booleen -> my booleen qui retourne le ou logique des deux arguments. Exercice 70 (Jeu de cartes) ` laide de types sommes, d enissez un type pour repr esenter un jeu de carte. Q 70.1 A ` la belote, on compte les points de la mani` ere suivante : Q 70.2 A lAs vaut 11 points. le Roi vaut 4 points.
page 76
5. Types somme
la Dame vaut 3 points. le Valet vaut 20 points si sa couleur est la m eme que celle de latout. Sinon elle vaut 2. une simple carte num erot ee ` a 10 vaut 10 points. une simple carte num erot ee ` a 9 vaut 14 points si sa couleur est la m eme que celle de latout. Sinon elle vaut 0. les autres cartes valent z ero point. Ecrivez une fonction valeur belote : couleur -> carte -> int qui prend en param` etre la couleur de latout et une carte an de rendre la valeur de celle-ci selon les r` egles enonc ees plus haut. Exercice 71 (Simulation de listes avec des types sommes) Cet exercice a pour but de d enir des listes avec des types sommes r ecursifs. Q 71.1 D enissez le type a listS sous forme dun type somme r ecursif pour repr esenter le type des listes. Q 71.2 D enissez la fonction hd : a listS -> a qui retourne la t ete de la liste donn ee en argument. La fonction hd l` eve lexception Failure "hd" si la liste vide est donn ee en argument. Q 71.3 D enissez la fonction tl : a listS -> a listS qui retourne la liste donn ee en argument priv ee de son premier el ement. La fonction tl l` eve lexception Failure "tl" si la liste vide est donn ee en argument.
page 77
Q 71.4 D enissez la fonction length : a listS -> int qui retourne le nombre d el ements de la liste donn ee en argument. Q 71.5 D enissez la fonction nth : a listS -> int -> a telle que nth l n retourne le n-` eme el ement de la liste l. Le premier el ement de la liste est ` a la position 0. Si la liste l a une longueur inf erieure ` a n, alors on l` eve lexception Raise "nth". Si n est n egatif on l` eve lexception Invalid argument "List.nth". Q 71.6 D enissez la fonction rev : a listS -> a listS qui retourne la liste inverse de celle donn ee en argument. Q 71.7 D enissez la fonction append : a listS -> a listS -> a listS qui concat` ene les deux listes donn ees en argument. Exercice 72 (Nombres de Peano) Les entiers de Peano sont des repr esentions symboliques pour les nombres entiers. On les d enit de mani` ere r ecursive : Zero est un entier de Peano, si n est un entier de Peano, alors S (n) est aussi un entier de Peano. On appelle S (n) le successeur de lentier n. Et on appelle n le pr ed ecesseur de lentier S (n). Par exemple, les entiers de Peano Zero, S (Zero), S (S (Zero)), repr esentent respectivement les nombres 0, 1 et 2.
page 78
5. Types somme
Q 72.1 D enissez le type peano des nombres de Peano sous forme dun type somme r ecursif. Q 72.2 Ecrivez ne de la fonction to string : peano -> string qui retourne la cha caract` eres correspondant au nombre de Peano donn e en argument. la fonction int of peano : peano -> int qui convertit un nombre Q 72.3 Ecrivez de Peano en un entier. la fonction peano of int : int -> peano qui convertit un entier en Q 72.4 Ecrivez un nombre de Peano. Q 72.5 Ecrivez la fonction inc : peano -> peano qui retourne le successeur dun nombre de Peano. Q 72.6 Ecrivez la fonction dec : peano -> peano qui retourne le pr ed ecesseur dun nombre de Peano. Appliqu ee ` a Zero, la fonction dec l` evera lexception Failure "dec". une fonction add : peano -> peano -> peano qui retourne laddiQ 72.7 Ecrivez tion de deux nombres de Peano, nb1 et nb2. Par exemple add appliqu e aux nombres S(Zero) et S(S(Zero)), doit rendre le nombre S(S(S(Zero))). Indice : aidez-vous des propri et es suivantes : 0 + nb2 = nb2 nb1 + nb2 = (nb1 1) + (nb2 + 1)
page 79
une fonction mult : peano -> peano -> peano telle que mult nb c1 Q 72.8 Ecrivez esultat de la multiplication des deux entiers de Peano nb c1 et nb c2. nb c2 retourne le r Par exemple mult, appliqu ee aux entiers S(S(Zero)) et S(S(S(Zero))), doit rendre le nombre S(S(S(S(S(S(Zero)))))). Indice : aidez-vous des propri et es suivantes : 0 nb1 = 0 1 nb1 = nb1 nb1 nb2 = ((nb1 1) nb2) + nb2 Exercice 73 (Expressions alg ebriques) On veut repr esenter des expressions alg ebriques simples et constantes ` a laide des Sexpressions. Ces expressions sont d enies par : un entier est une expression, si e1 et e2 sont des expressions alors e1 + e2 et e1 e2 sont des expressions. Quant aux S-expressions, an de les repr esenter, on utilise le type OCaml suivant : type s_exp = Nil | N of int | Op of char | Cons of s_exp * s_exp ;;
page 80
5. Types somme
Q 73.1 (Expressions et S-expressions) Donnez des exemples de S-expressions repr esentant des expressions valides, suivant la d enition des expressions donn ees ci-dessus. Donnez des exemples de S-expressions syntaxiquement valides mais ne repr esentant pas une expression. Q 73.2 (Ecriture des S-expressions) Q 73.2.1 (Paires totalement parenth es ees) D enissez la fonction string of s exp telle que (string of s exp e) retourne la cha ne de caract` eres repr esentant la S-expression e avec les conventions suivantes : Nil est repr esent e par "()", les entiers par leur repr esentation d ecimale, les op erateurs par la cha ne ne contenant que leur caract` ere (+ ou *), les paires par les repr esentations des deux S-expressions s epar ees par une espace et plac ees entre parenth` eses : par exemple "(1 ())". Notes : La fonction Char.escaped : char -> string convertit un caract` ere vers le type des cha nes de caract` eres. Si lop erateur est autre que + ou * vous leverez lexception Invalid argument "expression invalide"
page 81
Q 73.3 (Evaluation des expressions) D enissez la fonction eval : s exp -> int telle que (eval se) : retourne la valeur de lexpression e repr esent ee par la S-expression se lorsque e est une expression valide ; l` eve lexception Failure appliqu ee ` a la cha ne de caract` eres "eval : " concat en ee avec l ecriture de la sous-expression non evaluable, lorsque la S-expression se ne repr esente pas une expression e valide. Testez soigneusement votre implantation. En particulier, v eriez l evaluation des S-expressions repr esentant les expressions (3 2) + 1 et 3 (2 + 1). Evaluez lexpression 3 2 + 2 5. Indication : pour ecrire les S-expressions repr esentant ces expressions, pensez ` a utiliser les d eclarations locales pour ecrire les sous-expressions. Exercice 74 (Expressions alg ebriques) Nous d enissons r ecursivement les expressions alg ebriques de la mani` ere suivante : un entier est une expression, si e1 et e2 sont des expressions alors e1 + e2 et e1 e2 sont des expressions.
Q 74.1 (Type des expressions) En vous aidant de la d enition r ecursive des expressions, d enissez le type somme exp correspondant. Q 74.2 (Exemples dexpressions) Donnez des exemples dexpressions ecrits en
page 82
5. Types somme
OCaml. Q 74.3 (Conversion en cha nes de caract` eres) D enissez la fonction string of exp telle que (string of exp e) retourne la cha ne de caract` eres repr esentant lexpression e avec les conventions suivantes : les entiers sont repr esent es par leur repr esentation d ecimale, les expressions de la forme e1 + e2 et de la forme e2 e2 seront ach ees respectivement par "(e1 + e2)" et "(e2 * e2)". Q 74.4 (Evaluation des expressions) D enissez la fonction eval : exp -> int telle que (eval se) retourne la valeur de lexpression se. Testez soigneusement votre implantation. En particulier, v eriez l evaluation des expressions repr esentant les expressions (3 2) + 1 et 3 (2 + 1). Evaluez lexpression 3 2 + 2 5. Indication : pour ecrire les expressions, pensez ` a utiliser les d eclarations locales pour ecrire les sous-expressions. Exercice 75 (Gestion dune base de donn ees dUE) On veut sauvegarder dans une m eme base de donn ees la liste des enseignants et des etudiants dune UE (pourquoi pas LI213 ?). Pour cela, nous allons utiliser les types suivants : (* charge indique, pour chaque enseignant, son statut *)
page 83
type charge = Charge_cours | Charge_TD | Charge_TP;; (* note permet de faire cohabiter des etudiants ayant des notes a un *) (* module avec dautres nen ayant pas encore *) type note = Aucun | Note of float;; (* les types ens et etud permettent de sauvegarder les differents *) (* intervenants dune UE donnee *) type ens = { ens_nom : string; (* nom de lenseignant *) ens_charge : charge (* statut de lenseignant pour une UE donnee *) };; type etud = { etud_nom : string; (* nom de letudiant *) etud_note : note (* note de letudiant pour une UE donnee *) };; type person = (* person permet de faire cohabiter dans une UE *) | Ens of ens (* des choux et des carottes, heu pardon, des *) | Etud of etud;; (* enseignants et des etudiants *) type ue = { ue_nom : string; (* nom long de lUE (Types et structures) *)
page 84
5. Types somme
ue_code : string; (* code en li (li213) *) ue_pers : person list (* liste des intervenants du module *) };; Q 75.1 D eclarez plusieurs variables repr esentant des etudiants et des enseignants de statuts di erents. D eclarez une UE contenant ces di erentes personnes. Q 75.2 Ecrivez une fonction find_etud : ue -> person list prenant en argument une UE et renvoyant la liste de ses etudiants. Q 75.3 Ecrivez une fonction : find_ens : ue -> person list * person list * person list prenant en argument une UE et renvoyant un triplet (x, y, z ) dont le premier el ement, x, est la liste de ses charg es de cours, le deuxi` eme, y , la liste de ses charg es de TD et, enn, le troisi` eme la liste de ses charg es de TP. une fonction affiche : ue -> unit prenant une UE en argument Q 75.4 Ecrivez et achant ` a l ecran la liste format ee de ses enseignants et de ses etudiants. En premier doivent appara tre les charg es de cours, puis ceux de TD, puis ceux de TP et enn les etudiants. Par exemple, on pourrait obtenir : charge de cours : Christophe Gonzales charge de TD ...: Alain David charge de TP ...: Olivier Spanjaard
page 85
etudiant .......: xxx1 etudiant .......: xxx2 etudiant .......: xxx3 Q 75.5 D eclarez une exception Pas_de_note, puis une fonction : affiche_moyenne : ue -> float renvoyant la moyenne des notes des etudiants ayant re cu des notes au module. Si aucun etudiant na re cu de note, la fonction l` evera lexception Pas_de_note. Par exemple, si xxx1 na re cu aucune note et si xxx2 et xxx3 ont re cu respectivement 18,5 et 15, la moyenne de li213 sera de (18, 5 + 15)/2 = 16, 75. Exercice 76 (Interpr etation dun chier HTML) Dans cet exercice, on veut elaborer un programme OCaml permettant dacher dans une console en mode texte le contenu dun chier HTML (en tous cas dune sous-partie du langage HTML). Pour cela, il nous faut tout dabord d ecrire le langage HTML. Voici la d enition que nous utiliserons (en notation BNF) : page ::= entete "<html>" head body "</html>" head ::= "<head>" headers "</head>" body ::= "<body>" tags "</body>"
page 86
5. Types somme
tags ::= string-character | "<h1>" tags "</h1>" | "<h2>" tags "</h2>" | "<p>" tags "</p>" | "<b>" tags "</b>" | "<i>" tags "</i>" | "<ol>" tags "</ol>" | "<ul>" tags "</ul>" | | | |
titre */ sous-titre */ paragraphe */ texte en gras */ texte en italique */ liste ordonn ee (num erot ee) */ liste non ordonn ee (des "-" ` a la place des nombres) */ "<li>" tags "</li>" /* item dans une liste <ul> ou <ol> */ "<br/>" /* retour ` a la ligne */ "<!--" tags "-->" /* commentaire (nappara^ t pas dans les browsers) */ "<center>" tags "</center>" /* centrage horizontal dun texte dans le browser */
/* /* /* /* /* /* /*
Le principe des pages ou` ebes est le suivant : les pages ou` ebes comportent un en-t ete, que nous ne d etaillerons pas ici mais qui contient des informations pour votre browser entre autres le titre ` a ecrire en haut de la fen etre du browser, le chier de style ` a utiliser pour param etrer la mise en page, etc , puis le texte ` a acher proprement dit entre les balises <body> et </body> . Ce texte contient en outre des instructions de mise en page. Par exemple, chaque fois que vous voulez rajouter un titre (en fait une section de type 1), vous ins erez dans votre source HTML une balise <h1> , le texte du titre, et vous
page 87
refermez le titre avec </h1> . De m eme, si vous voulez quun texte apparaisse en gras et en italique, vous ins erez <b><i> , le texte en question, puis </i></b> . Ainsi la page ou` ebe suivante correspondrait ` a une instanciation du langage d ecrit ci-dessus : <html> <head> <title> about bnf notation </title> </head> <body> <h1>what is BNF notation?</h1> <p><b>BNF</b> is an acronym for "Backus Naur Form". John Backus and Peter Naur introduced for the first time a formal notation to describe the syntax of a given language (This was for the description of the <b><i>ALGOL 60</i></b> language).</p> </body> </html> Nous voudrions, ` a lissue de cet exercice, acher ce type de page dans une console. Cela donnerait :
page 88
5. Types somme
what is BNF notation ? BNF is an acronym for "Backus Naur Form". John Backus and Peter Naur introduced for the first time a formal notation to describe the syntax of a given language (This was for the description of the ALGOL 60 language). Lexercice va donc consister ` a analyser les balises de pages comme celle ci-dessus, et ` a retranscrire ces derni` eres dans une console en mode texte. Q 76.1 Copiez le chier : /Infos/lmd/2008/licence/ue/li213-2008oct/ressources/html/html.ml dans votre r epertoire li213-2008oct, puis editez cette copie avec votre editeur xemacs. Inutile pour linstant de lire ce chier. Les seules informations importantes pour vous sont : 1. en d ebut de chier, le type somme html_tag qui repr esente le langage HTML ; 2. la fonction html_tag_of_file : string -> html_tag qui lit le chier HTML dont le nom est pass e en param` etre et qui renvoie la structure html tag correspondante (notons que lanalyse de pages ou` ebes eectu ee par cette fonction est assez sousoptimale. Il aurait et e beaucoup plus judicieux dutiliser ocamllex/ocamlyacc/camlp4 pour parser les pages. Cela dit, nous avons pr ef er e vous donner cette version sousoptimale de html tag of file car vous avez toutes les connaissances requises pour comprendre comment elle fonctionne). Le r epertoire /Infos/lmd/2008/licence/ue/li213-2008oct/ressources/html/
page 89
contient un certain nombre de pages ou` ebes exemple X Y .html, o` u X repr esente un num ero dexercice et Y un num ero dexemple. Testez la fonction html_tag_of_file avec les chiers HTML exemple 1 1.html, exemple 1 2.html et exemple 1 3.html. Q 76.2 Ecrivez deux fonctions mutuellement r ecursives, cest-` a-dire d enies avec let rec...and, get affichage liste : html tag list -> string et get_affichage_tag : html_tag -> string, dont la premi` ere prend en argument une liste de balises et qui renvoie la cha ne de caract` eres constitu ee en concat enant les cha nes renvoy ees par get affichage tag pour chacune des balises de la liste. Vous supposerez que la liste de html tag ne contient, pour linstant, que les balises BODY et TEXTE. De plus, get affichage tag ne renverra que la cha ne de caract` eres compos ee uniquement du texte contenu dans les balises TEXTE. Par exemple, (get affichage tag (BODY [TEXTE " Exercice 1 "])) renverra la cha ne " Exercice 1 ". Testez extensivement votre fonction. Testez-la aussi avec les chiers exemple 2 1.html et exemple 2 2.html. une fonction trim : string -> string qui prend en argument une Q 76.3 Ecrivez cha ne S et renvoie la cha ne S dans laquelle les espaces se trouvant en d ebut et en n de cha ne ont et e supprim ees. Par exemple, (trim " xxx ") renverra la cha ne "xxx". Q 76.4 (D ecoupage dune cha ne de caract` eres) une fonction decoupe_string : string -> string qui prend en Q 76.4.1 Ecrivez argument une cha ne S , qui la d ecoupe en morceaux de 80 caract` eres au maximum et qui
page 90
5. Types somme
renvoie la cha ne constitu ee par la concat enation de ces morceaux, ceux-ci etant s epar es ecouper une cha ne en lignes de 80 par des \n (decoupe string permet donc de d caract` eres). Q 76.4.2 Modiez la fonction decoupe_string de mani` ere ` a supprimer pour chaque morceau les espaces se trouvant au d ebut et ` a la n du morceau. Q 76.4.3 Modiez la fonction get affichage tag de fa con ` a ce que, dans les cha nes des caract` eres renvoy ees, les lignes ne d epassent pas 80 caract` eres (lorsquune ligne d epasse 80 caract` eres, elle est scind ee en plusieurs lignes). une fonction affiche page ouebe : string -> unit qui prend en Q 76.5 Ecrivez argument le nom dun chier HTML et qui ache ` a l ecran (via des print string peut etre) le texte de ce chier. Q 76.6 (Gestion des titres et sous-titres) Q 76.6.1 Modiez la fonction get affichage tag de fa con ` a g erer les balises H1. On veut que les achages des textes en H1 soient centr es sur un achage ` a 80 colonnes. De plus, on veut que les titres H1 soient s epar es du reste du texte en sautant une ligne avant le titre et en en sautant 2 apr` es. Testez avec le chier exemple 3 1.html. Par exemple, (get affichage tag (BODY [ H1 [TEXTE "titre"] ; TEXTE "texte" ; H1 [TEXTE "fin"]])) eectuera lachage suivant :
page 91
Q 76.6.2 Modiez la fonction get affichage tag de fa con ` a g erer les balises H2. Les sous-titres H2 se distinguent du reste du texte car ils sont pr ec ed es et suivis par une ligne vide. Testez avec le chier exemple 3 2.html. Q 76.7 Modiez la fonction get affichage tag de fa con ` a prendre en compte les balises B (texte en gras) et I (texte en italique). Comme vous ne savez pas g erer dans la console ce type dattribut, vous vous contenterez de retourner la cha ne correspondante comme si elle navait et e ni en gras ni en italique. Par exemple, (get affichage tag (BODY [ B [TEXTE "texte en gras," ; I [TEXTE "et en italique,"] ] ; TEXTE " et texte normal"])) renverra : texte en gras,et en italique,et texte normal Testez votre fonction avec le chier exemple 4 1.html.
page 92
5. Types somme
Q 76.8 Modiez la fonction get affichage tag de fa con ` a prendre en compte les balises P des paragraphes et BR des retours ` a la ligne. Q 76.9 Modiez la fonction get affichage tag de fa con ` a prendre en compte les balises COMMENT : comme ce sont des commentaires HTML, ils ne doivent pas appara tre dans les ne de sorties HTML et donc (get affichage tag (COMMENT liste)) renverra la cha caract` eres vide . G erez aussi les balises CENTER qui centrent un texte (sur un achage ` a 80 colonnes). Q 76.10 (pour samuser avec la console) Si lon ache les cha nes de caract` eres dans une console et non dans la fen etre xemacs, on peut am eliorer lachage en utilisant des s equences dinstructions sp eciques aux terminaux (cf. le man du terminfo et du termcap). Ces s equences commencent par \027[ et se terminent par m. Par exemple on peut avoir \027[05;30m. Entre le \027[ et le m, les instructions sont repr esent ees par des nombres comme indiqu es dans le tableau ci-dessous et sont s epar ees par des ;. Par exemple, \027[05;31m signie quil faut acher le texte en gras (05) et en rouge (31).
page 93
instruction 00 05 07 30 31 32 34 36
signication normal (non gras, non soulign e, en noir, etc) en gras en mode reverse vid eo en noir en rouge en vert en bleu fonc e en cyan
En utilisant ces s equences, faites en sorte que les titres H1 soient en reverse vid eo et en rouge, que les H2 soient en bleu fonc e et en gras, que les texte en gras apparaissent en gras ` a l ecran et que les textes en italique soient en vert. Q 76.11 G erer les balises OL, UL et LI. Une balise OL contient une liste ditems qui doivent etre num erot es tandis quune balise UL contient une liste ditems qui ne doivent pas l etre. Chaque item doit se trouver dans une balise LI. Ainsi, UL[ LI[TEXTE "item 1"] ; LI[ OL[ LI [TEXTE "item 2.1"] ; LI[TEXTE "item 2.2"]]] ; LI [TEXTE "item 3"]] correspondra ` a un achage tel que :
page 94
5. Types somme
- item 1 1. item 2.1 2. item 2.2 - item 3 Il nest pas trivial de g erer ces listes car i) tous les items sont des LI et on ne peut donc pas distinguer ` a la seule vue de la balise LI si lon est dans une liste num erot ee ou non ; ii) des listes peuvent etre imbriqu ees les unes dans les autres ; iii) des listes imbriqu ees peuvent etre de types OL/UL di erents. An de vous aider dans votre programmation, nous vous sugg erons donc de rajouter avant la fonction get affichage tag les d eclarations suivantes : type in_liste let ol_depth let ol_number let ul_depth let in_liste = = = = = IN_UL | IN_OL | OUT;; ref 0;; ref 0;; ref 0;; ref OUT;;
aLes variables ol depth et ul depth indiquent la profondeur des listes OL et UL, cest-` dire leur degr e dimbrication. Une profondeur de 1 indique que la liste nest pas imbriqu ee dans une autre, une profondeur de 2 quelle est imbriqu ee dans une seule autre liste, une profondeur de 3 quelle est imbriqu ee dans une liste elle-m eme imbriqu ee dans une liste, etc. Lorsquon ache une liste HTML, on indente toujours un peu la liste. La profondeur
page 95
vous indique donc de combien de caract` eres il faut indenter les items (utilisez 2 caract` eres ero du prochain item par niveau de profondeur). La variable ol number contient le num dune liste OL. Enn in liste sert ` a savoir dans quel type de liste on se trouve. Principe coit un OL ou un UL, elle met ` a de lalgorithme dachage : quand get affichage tag re jour la profondeur correspondante puis, pour chaque item de la liste pass ee en param` etre de OL, elle met ` a jour la variable in liste et, eventuellement ol number, puis elle r ecup` ere la cha ne de caract` ere correspondant ` a cet item et la concat` ene avec les cha nes obtenues avec les items suivants. Lorsque get affichage tag re coit un LI, elle utilise les variables in liste, ol depth, ul depth et ol number pour calculer comment litem doit sacher, puis elle g en` ere la cha ne de caract` eres correspondante.
page 96
5. Types somme
97
page 98
page 99
Fig. 1 Repr esentation dune liste simplement cha n ee. Chaque el ement de la liste correspond ` a une case elt1, elt2, etc. Les ` eches indiquent que, ` a partir dun el ement donn e de la liste, on peut atteindre le reste de la liste (symbolis e par la ` eche vers la droite). Ainsi dans une liste [ 1 ; 2 ; 3 ; 4 ; 5 ], ` a partir de l el ement 3 , un op erateur (tl) permet datteindre la liste [ 4 ; 5 ] . Dans cet exercice, on sint eresse ` a 5 op erations sur les listes : myempty : unit -> a liste renvoie une liste vide. myhd : a liste -> a renvoie le premier el ement de la liste ou l` eve lexception (Failure "hd") si la liste est vide. mytl : a liste -> a liste renvoie le reste de la liste ou l` eve lexception (Failure "tl") si la liste est vide.
page 100
mycons : a -> a liste -> a liste renvoie une liste dont la t ete est le premier param` etre et le reste le deuxi` eme param` etre. mylength : a liste -> int renvoie la longueur de la liste. Q 77.1 (listes OCaml) Q 77.1.1 Ecrivez une d enition des fonctions myempty, myhd, mytl, mycons et mylength pour les listes standard OCaml ` a partir des fonctions du module List (une ligne par fonction). Q 77.1.2 Ecrivez une autre d enition de la fonction mylength qui utilise uniquement la fonction mytl pour parcourir la liste. Vous saurez que vous etes arriv es en n de liste lorsque mytl l` evera une exception. Vous naurez alors qu` a rattraper celle-ci avec un try...with pour g erer le cas de la n de liste. Q 77.1.3 Ecrivez une fonction mymem : a -> a liste -> bool telle que mymem a l vaut true si et seulement si a est dans l. Cette fonction ne doit utiliser que les fonctions my* d enies plus haut. En TME, vous pourrez comparer cette fonction ` a la fonction List.mem de la biblioth` eque OCaml. une fonction myrev : a liste -> a liste qui retourne une liste. Q 77.1.4 Ecrivez Cette fonction ne doit utiliser que les fonctions my* d enies plus haut. En TME, vous pourrez comparer cette fonction ` a la fonction List.rev de la biblioth` eque OCaml. Q 77.1.5 Rappelez, en vous appuyant par exemple sur les fonctions d enies pr ec edemment,
page 101
les avantages et les inconv enients des listes cha n ees par rapport aux tableaux. Q 77.2 (Premi` ere version des listes) On consid` ere la d eclaration ci-dessous pour repr esenter des listes : chaque case est repr esent ee par un type a myelt et contient ` a la fois l el ement eltj et la suite de la liste (` eche vers la droite). Le type a myliste est un type somme permettant de m elanger la liste vide avec des listes non vides. Une liste vide est repr esent ee par Nil et une liste non vide par Elt case o` u case est de type a myelt. type a myelt = { elt : a; (* les el ements eltj *) next : a myliste (* la suite de la liste *) } and a myliste = | Nil (* la liste vide (fin de liste) *) | Elt of a myelt;; (* la t^ ete de la liste *) Par exemple, la liste de la gure 1 serait repr esent ee par lexpression suivante : Elt { elt = elt1; next = Elt { elt = elt2; next = Elt { elt = elt3; next = Nil }}};; une d enition de la fonction myempty pour le type a myliste, i.e. Q 77.2.1 Ecrivez une fonction de type unit -> a myliste qui renvoie une liste vide de type myliste.
page 102
une d enition de la fonction myhd pour le type a myliste, i.e. une Q 77.2.2 Ecrivez fonction de type a myliste -> a qui, si on lui passe en param` etre une liste vide (autrement dit Nil), l` eve une exception (Failure "hd"), et sinon renvoie la valeur stock ee dans la premi` ere case de la liste. Par exemple, (myhd (Elt {elt = elt1 ; next = Elt { elt = elt2 ; next = Nil}})) renverrait elt1 et (myhd Nil) l` everait lexception. Q 77.2.3 Ecrivez une d enition de la fonction mytl pour le type a myliste, i.e. une fonction de type a myliste -> a myliste qui, si on lui passe en param` etre une liste non vide, renvoie le reste de la liste, et si on lui passe un Nil, l` eve une exception Failure "tl". Ainsi, (mytl (Elt {elt = elt1 ; next = Elt { elt = elt2 ; next = Nil}})) renverrait Elt { elt = elt2 ; next = Nil}. Q 77.2.4 Ecrivez une d enition de la fonction mycons pour le type a myliste, i.e. une fonction de type a -> a myliste -> a myliste qui renvoie une liste dont la t ete est son premier param` etre et le reste le deuxi` eme param` etre. Ainsi (mycons elt1 (Elt { elt = elt2 ; next = Nil})) renverrait : Elt {elt = elt1 ; next = Elt { elt = elt2 ; next = Nil}}.
Q 77.2.5 V eriez que la d enition de la fonction mylength donn ee dans la question 77.1.2 est encore valide avec le type a myliste. Idem pour les fonctions mymem et myrev d enies dans la question 77.1. une fonction mysuppress : a myelt -> a mylist -> a mylist Q 77.2.6 Ecrivez
page 103
qui, etant donn e un el ement et une liste, retourne une nouvelle liste priv ee de l el ement. Cette fonction retournera la liste pass ee en param` etre si l el ement nest pas dans cette liste. Q 77.3 (Deuxi` eme version des listes) Dans cette question, on d enit un nouveau type pour repr esenter les listes : type a som_liste = | Nil (* la liste vide (fin de liste) *) | Cons of a * a som_liste;; (* la t^ ete de la liste * la suite *) Dans ce nouveau type, la liste de la gure 1 serait repr esent ee par lexpression suivante : Cons (elt1, Cons (elt2, Cons (elt3, Nil)));; Q 77.3.1 Ecrivez une d enition des fonctions : 1. myempty : unit -> a som_liste 2. myhd : a som_liste -> a 3. mytl : a som_liste -> a som_liste 4. mycons : a -> a som_liste -> a som_liste pour ce nouveau type. Q 77.3.2 V eriez que la d enition de la fonction mylength donn ee dans la question 77.1.2 est encore valide avec le type a som liste. Idem pour les fonctions mymem et myrev d enies dans la question 77.1.
page 104
Q 77.3.3 Remarque : regardez dans le manuel dOCaml (ou dans le cours) comment sont d enies les listes (le type a list). Quen concluez-vous sur limpl ementation standard des listes en OCaml par rapport aux deux versions que vous avez impl ement ees ? Q 77.4 (Autres fonctions sur les listes) Dans cette question, vous allez utiliser les fonctions ecrites dans lune ou lautre des questions pr ec edentes pour compl eter votre module de manipulation de listes. Bien entendu, toutes les fonctions que vous allez ecrire devront fonctionner sans avoir ` a apporter aucune modication avec les types a myliste et a myelt dune part et avec le type a som liste dautre part. Dans l enonc e, ` a titre indicatif, les signatures (les types) des fonctions sont d ecrites en utilisant a som liste. une d enition de la fonction mynth : a som_liste -> int -> a Q 77.4.1 Ecrivez qui, etant donn e une liste L et un entier n, renvoie l el ement ` a la ni` eme position dans L, etant entendu que la t ete dune liste est en position 0. Si l el ement ne peut etre trouv e parce que la liste est trop petite, la fonction doit lever une exception Failure "nth". Par exemple, (mynth 10 Cons (elt1, Cons (elt2, Cons (elt3, Nil)))) l` evera lexception tandis que (mynth 1 Cons (elt1, Cons (elt2, Cons (elt3, Nil)))) renverra elt2. Q 77.4.2 Ecrivez une fonction : myappend : a som_liste -> a som_liste -> a som_liste qui renvoie la concat enation des deux listes qui lui sont pass ees en argument. Ainsi, (myappend (Cons (elt1, Nil)) (Cons (elt2, Nil))) renverra :
page 105
Cons (elt1, Cons (elt2, Nil)). Q 77.4.3 Ecrivez une fonction : myrev_append : a som_liste -> a som_liste -> a som_liste enation de l1 et de telle que (myrev append l1 l2) renvoie la liste obtenue par concat l2, o` u l1 contient les m emes el ements que l1 mais dans lordre inverse. Par exemple, (myrev append (Cons (elt1, Cons (elt2, Nil))) (Cons (elt3, Nil))) renverrait Cons (elt2, Cons (elt1, Cons (elt3, Nil))). Q 77.4.4 Ecrivez une d enition de la fonction : myiter : (a -> b) -> a som_liste -> unit telle que (myiter f (Cons (a1, ..., Cons (an, Nil)))) applique la fonction f s equentiellement ` a a1, puis a2,. . .,an. En fait, cest equivalent ` a ecrire : begin f a1 ; f a2 ; ... ; f an ; () end. Q 77.4.5 Ecrivez une fonction : mymap : (a -> b) -> a som_liste -> b som_liste telle que : (mymap f (Cons (a1, ..., Cons (an, Nil)))) applique la fonction f s equentiellement ` a a1, puis a2,. . .,an et renvoie la liste Cons (f a1, ..., Cons (f an, Nil)) constitu ee par les valeurs retourn ees par f. Q 77.4.6 Ecrivez une fonction : myfold_left : (a -> b -> a) -> a -> b som_liste -> a qui r ealise le fold left du module List.
page 106
le fonction myexists : (a -> bool) -> a som_liste -> bool Q 77.4.7 Ecrivez et la fonction mymem : a -> a som_liste -> bool qui correspondent respectivement aux fonctions exists et mem du module List. Q 77.4.8 Ecrivez myfilter : (a -> bool) -> a som_liste -> a som_liste correspondant au filter du module List. Q 77.4.9 Ecrivez une d enition de la fonction : myliste_of_liste : a list -> a som_liste ecrirez bien s ur cette fonction qui traduit une liste OCaml en un a som liste. Vous de mani` ere ` a ce quelle soit ind ependante du type a som liste. Exercice 78 (Listes doublement cha n ees) Une liste doublement cha n ee peut etre repr esent ee par un sch ema comme celui ci-dessous :
elt1 elt2 elt3 ...... etlk
Fig. 2 Repr esentation dune liste doublement cha n ee. Chaque el ement de la liste correspond ` a une case elt1, elt2, etc. Les ` eches indiquent que, ` a partir dun el ement donn e de la liste, on peut atteindre son pr ed ecesseur (` eche vers la
page 107
gauche) et son successeur (` eche vers la droite). Ainsi dans une liste [1 ; 2 ; 3 ; 4], ` a partir de l el ement 3 , un op erateur permettrait datteindre l el ement 2 et un autre l el ement 4 . On consid` ere la d eclaration ci-dessous pour repr esenter des listes doublement cha n ees : chaque case contient ` a la fois l el ement eltj et les ` eches vers la gauche et vers la droite partant de cet el ement. type a elt = { elt : a; (* les el ements eltj *) mutable next : a clist; (* le pr ed ecesseur *) mutable prev : a clist (* le successeur *) } and a clist = | Nil (* la liste vide (fin de liste) *) | Elt of a elt;; (* la premi` ere case de la liste *) Par exemple, la liste de la gure 2 serait repr esent ee par case1 dans la d eclaration suivante : let rec case1 = Elt { and case2 = Elt { and case3 = Elt { and ............. and casek = Elt { elt = elt1 ; prev = Nil ; next = case2 } elt = elt2 ; prev = case1 ; next = case3 } elt = elt3 ; prev = case2 ; next = case4 } elt = eltk ; prev = casekmoins1 ; next = Nil };;
page 108
une d enition de la fonction head : a clist -> a qui, si on lui Q 78.1 Ecrivez passe en param` etre une liste cha n ee vide (autrement dit Nil), l` eve une exception Failure "head", et sinon renvoie la valeur stock ee dans la premi` ere case de la liste. Par exemple, (head case1) renverrait elt1 et (head Nil) l` everait lexception. De m eme, ecrivez une d enition dune fonction next : a clist -> a clist qui, si on lui passe en param` etre une case dune liste, renvoie la case suivante, et si on lui passe un Nil, l` eve une exception Failure "next". Ainsi, (next case2) renverrait case3. Enn, ecrivez une d enition dune fonction prev : a clist -> a clist qui renverrait l el ement pr ec edent dans la liste. Q 78.2 Ecrivez une d enition de la fonction empty : unit -> a clist qui renvoie une liste vide doublement cha n ee. Ecrivez une fonction is_empty : a clist -> bool qui renvoie un bool een indiquant si la liste est vide ou non. Q 78.3 Ecrivez une d enition dune fonction cons : a -> a clist -> a clist telle que (cons x case1) renvoie une nouvelle liste cha n ee dont le premier el ement est une case contenant x et la suite est la liste dont la t ete est case1. Attention ` a bien cha ner les el ements : ` a la n, vous devez obtenir la liste repr esent ee par la gure 3.
x elt1 elt2 elt3 ...... etlk
page 109
une d enition dune fonction create : a list -> a clist preQ 78.4 Ecrivez nant en param` etre une liste OCaml classique (comme celles que vous avez manipul ees dans les TD pr ec edents) et qui renvoie la liste doublement cha n ee correspondante. Q 78.5 Ecrivez une d enition dune fonction get_list : a clist -> a list qui prend en param` etre une liste doublement cha n ee et qui renvoie la liste simplement cha n ee correspondante. Essayez de faire en sorte que votre fonction ne d epende pas des types a elt et a clist. Indication : utilisez les fonctions head, next et is empty. Q 78.6 Ecrivez une d enition dune fonction : suppress : a elt -> a clist -> a clist telle que (suppress x liste) renvoie une liste doublement cha n ee ne contenant plus la case x. Id ee : il sut de recha ner la liste comme indiqu e dans la gure 4 (ci-apr` es). Comparez suppress et mysuppress (de la question 77.2.6). Exercice 79 (Listes circulaires) Nous allons illustrer dans cet exercice lutilisation de listes doublement cha n ees circulaires en simulant lenvoi de messages par des ordinateurs reli es dans un r eseau de type token ring. Dans un tel r eseau les ordinateurs (tout au moins les MSAU (multistation access units)) sont reli es les uns aux autres de mani` ere ` a former un anneau (cf. gure 5). Un jeton (le token) circule dans le r eseau. Seul un ordinateur poss edant le jeton peut envoyer des messages aux autres. Si un ordinateur re coit le jeton mais na rien ` a transmettre, il passe
page 110
avant dbut x elt1 elt2
elt1
elt2
elt1
elt2
elt2
elt1
fin
elt2
elt1
fin
Fig. 4 Recha nage pour un suppress de x. le jeton ` a lordinateur suivant. Quand un ordinateur veut envoyer un message ` a un autre ordinateur, il attend le jeton, le saisit, transmet son information et, lorsque cette derni` ere est arriv ee ` a destination, il passe le jeton ` a la station suivante, etc. On d enit le type machine pour symboliser lenvoi de message par un ordinateur : un ordinateur mac va envoyer un message via une fonction message. La probabilit e qu` a un instant t mac veuille transmettre un message est fournit par le champ proba.
page 111
Fig. 5 Un r eseau en token ring. type machine = { mac : string; (* nom de la machine *) proba : int; (* 100 * probabilit e davoir un message ` a transmettre *) message : string -> int -> unit; (* fonction qui transmet le message *) };; Q 79.1 D enissez une fonction message : string -> int -> unit qui prend en argument le nom dune machine X et une probabilit e p ( 100), et qui ache ` a l ecran le message emission de X avec une probabilit e de p% et ne fait rien avec une probabilit e de (100 p)%. Utilisez Random.int pour simuler la probabilit e. Cr eez trois ordinateurs de type machine ayant pour fonction denvoi de messages la fonction ci-dessus, et ayant des probabilit es di erentes.
page 112
Q 79.2 Une liste doublement cha n ee circulaire est une liste dont tous les el ements ont un pr ed ecesseur et un successeur, cf. la gure 6.
elt1
elt2
elt3
Fig. 6 Une liste doublement cha n ee circulaire. Dans la suite de lexercice, on reprend la structure de liste doublement cha n ee de lexercice pr ec edent. Ecrivez une d enition dune fonction circular_empty : unit -> a clist qui cr ee une liste circulaire vide. Ecrivez une fonction circular_cons : a -> a clist -> a clist telle que : el ement e ` a liste. Deux cas sont ` a envisager : (circular cons e liste) rajoute l 1. liste est vide. Dans ce cas il faut cr eer une liste ne comportant quune seule case contenant e et qui est elle-m eme son propre pr ed ecesseur et successeur. 2. liste nest pas vide. Dans ce cas, vous ins ererez e juste apr` es le premier el ement de liste. M eme si la liste est circulaire, dapr` es la d enition du type a clist, une a clist non vide, cest-` a-dire un Elt x, poss` ede un premier el ement : la case x. Cr eez une liste circulaire qui contient les 3 machines que vous aviez cr e ees ` a la question pr ec edente.
page 113
une fonction envois : int -> machine clist -> unit telle que Q 79.3 Ecrivez envois n liste simule n transmissions de jetons dans le token ring constitu e des machines de liste. Chaque fois quune machine poss` ede le jeton, elle lance sa fonction message avec son nom de machine et sa probabilit e. Exercice 80 (Crible dEratosth` ene) Q 80.1 Ecrivez une fonction cree_liste : int -> int list telle que (cree liste n) renvoie la liste des entiers de 1 ` a n si n est sup erieur ou egal ` a 1, et l` eve lexception Failure "erreur cree liste" sinon. une fonction crible : int -> int list telle que (crible n) renQ 80.2 Ecrivez voie la liste des nombres premiers entre 1 et n si n est sup erieur ou egal ` a 1, et l` eve lexception Failure "erreur crible" sinon. Principe du crible : pour tout i {2, . . . , n}, on supprime de la liste tous les multiples de i (except e i lui-m eme bien s ur).
page 114
Exercice 81 (Variations sur le triangle de Pascal) On consid` ere le triangle de Pascal : 1 1 1 1 2 1 1 3 3 1 1 4 6 4 1 ... On rappelle que, si lon nomme pi,j l el ement ` a la i` eme ligne, j ` eme colonne, et si les indices en ligne et en colonne commencent ` a 0, alors : j i, pi,j = 1 si j = i ou j = 0, pi1,j 1 + pi1,j sinon.
Q 81.1 On repr esente chaque ligne du triangle ci-dessus par la liste des entiers la consti tuant. Ecrivez une fonction ajout_ligne : int list -> int list qui, etant donn e une ligne du triangle de Pascal, renvoie la ligne suivante. une fonction triangle : int -> int list list telle que (triangle Q 81.2 Ecrivez n) renvoie le triangle de Pascal jusqu` a lindice i = n (autrement dit, il y a n + 1 lignes).
page 115
Celui-ci sera repr esent e de la mani` ere suivante : ` a chaque ligne correspondra une liste dentiers, et les lignes seront regroup ees au sein dune m eme liste : par exemple (triangle 4) renverra : [[1]; [1; 1]; [1; 2; 1]; [1; 3; 3; 1]; [1; 4; 6; 4; 1]] Q 81.3 Dans cette question, on repr esente des polyn omes ` a coecients entiers par la liste desdits coecients. Par exemple P (x) = 1 + 7x + 3x4 sera repr esent e par [1 ; 7 ; 0 ; 0 ; 3]. Ecrivez une fonction substr : int list -> int list -> int list qui, etant donn e deux polyn omes p1 et p2, renvoie le polyn ome p1 p2 (la liste de ses coecients).
Q 81.4 On rappelle que les coecients du polyn ome P (x) = (x + 1)k sont donn es par la ligne du triangle de Pascal dindex k (donc la k + 1` eme ligne puisque les indices du triangle commencent ` a 0). Cr eez un triangle de Pascal de 100 lignes puis ecrivez une fonction coeff : int -> int -> int list telle que (coeff k k) renvoie les coecients du polyn ome (x + 1)k (x + 1)k . Vous supposerez que k et k sont compris entre 2 et 99.
Q 81.5 On voit bien dans la fonction pr ec edente que la structure de donn ees utilis ee pour stocker le triangle de Pascal nest pas tr` es ecace pour le calcul de la fonction coeff car, e deectuer pour obtenir la liste des coecients de (x + 1)k et de (x + 1)k , on est oblig un parcours de liste (pour tomber sur les lignes correspondant ` a k et k ). Trouvez une structure de donn ees permettant un acc` es plus rapide ` a ces coecients. R eimpl ementez avec cette nouvelle structure la construction du triangle de Pascal et la fonction coeff.
page 116
` titre indicatif, lancez 10000 fois le calcul (coeff 99 98) avec votre premi` A ere structure de donn ees et avec la seconde et comparez les temps de r eponse. Pour cela, vous pouvez utiliser la commande gettimeofday : unit -> float du module Unix (pour pouvoir utiliser cette commande, il sut de faire un open Unix;; suivi dun #load "unix.cma";;).
page 117
page 118
push : a -> a mystack -> unit qui rajoute un el ement ` a une pile. pop : a mystack -> a qui d epile l el ement en haut de la pile (le dernier ins er e dans la pile) et le renvoie. Si la pile pass ee en argument est vide (avant d epilement), la fonction doit lever lexception Empty stack. top : a mystack -> a qui renvoie l el ement en haut de la pile sans d epiler celle-ci. Si la pile pass ee en argument est vide, la fonction doit lever lexception Empty stack. Q 82.2 Ecrivez les d enitions des fonctions : copy : a mystack -> a mystack qui renvoie une nouvelle pile renfermant les m emes el ements que celle pass ee en argument. length : a mystack -> int qui renvoie le nombre d el ements stock es dans la pile. iter : (a -> unit) -> a mystack -> unit telle que (iter f pile) applique la fonction f ` a chaque el ement de la pile (du dernier ins er e jusquau premier el ement ins er e). La pile elle-m eme reste inchang ee. Remarque : le type a mystack est en fait un type r ef erence, les fonctions ci-dessus se r e ecrivent facilement en utilisant le type ref. Il est possible aussi de g erer une pile en utilisant un tableau. La taille du tableau limite alors celle de la pile et n ecessite lintroduction oler les d ebordements de pile. dune nouvelle exception Full stack pour contr Q 82.3 D enissez un nouveau type a mystack2 en utilisant un enregistrement contenant un tableau et lindice de la derni` ere case occup ee dans la pile. Les el ements du tableau sont ceux de la pile, empil es successivement de la gauche vers la droite. Q 82.4 D enissez la fonction new stack qui prend un entier en entr ee ainsi quun el ement
page 119
quelconque du type a et construit une pile de cette taille. Q 82.5 R e ecrivez les d enitions des primitives de base create, is empty, clear, push, pop et top. Q 82.6 On d esire eviter que lajout dun el ement dans une pile provoque le d eclenchement de lexception Full stack. Ecrivez une fonction renew stack qui augmente la taille de la pile et red enissez la fonction push. Exercice 83 ( evaluation dune expression arithm etique) On consid` ere un type token pour repr esenter un nombre ou un op erateur arithm etique (+, ou ). Une expression arithm etique sera repr esent ee dans cet exercice par une liste de tokens. type token = | N of int | R of float | Op of char;; type expr = token list;; exception Expr_error;; Q 83.1 D enissez une variable de type expr repr esentant sous forme postx ee lexpression inxe 2 ((5.5 + 6.5) + (7 8)).
page 120
une fonction eval : expr -> float qui, etant donn e une expression Q 83.2 Ecrivez postx ee de type expr, renvoie le nombre r eel correspondant ` a la valeur de lexpression. Si celle-ci nest pas bien form ee, votre fonction doit lever lexception Expr error. Par exemple, 2 5 + nest pas bien form ee car il manque un nombre avant le ou le 2. Id ee : utiliser une pile pour les op erandes. On parcourt la liste de tokens repr esentant lexpression arithm etique. Chaque fois que lon rencontre un op erande, on lempile. Chaque fois que lon rencontre un op erateur, on d epile les deux derniers op erandes empil es, on eectue lop eration arithm etique et on empile le r esultat. Une fois lalgorithme termin e, la pile des op erandes contient un seul nombre : la valeur de lexpression. Q 83.3 D enissez une variable de type expr repr esentant sous forme inxe totalement parenth es ee lexpression inxe 2 ((5.5 + 6.5) + (7 8)). Q 83.4 Ecrivez une fonction eval2 : expr -> float qui, etant donn e une expression inxe totalement parenth es ee de type expr, renvoie le nombre r eel correspondant ` a la valeur de lexpression. Les parenth` eses sont consid er ees comme des op erateurs. Si lexpression nest pas bien form ee, votre fonction doit lever lexception Expr error. Id ee : utiliser une pile pour les op erandes et une pile pour les op erateurs. Chaque fois que lon rencontre un op erande, on lempile dans la pile des op erandes. Chaque fois que lon rencontre un op erateur di erent de ) , on lempile sur la pile des op erateurs. Lorsque lon rencontre une ) , on eectue toutes les op erations empil ees sur la pile des op erateurs et ce jusqu` a ce que lon atteigne une ( .
page 121
Exercice 84 (Pile dex ecution) Dans cet exercice, on veut simuler la pile dex ecution utilis ee lors des appels de fonctions dans vos programmes. Lorsque vous appelez une fonction, les param` etres pass es ` a celleci sont en principe d epos es sur la pile dex ecution. La fonction les r ecup` ere en d epilant cette derni` ere, ex ecute son code, puis d epose sa valeur de retour sur la pile. On peut alors r ecup erer cette valeur en d epilant ` a nouveau la pile dex ecution. Par exemple, lorsque vous ex ecutez let x = 3 + 5;;, la valeur 3 est empil ee, puis la valeur 5, la fonction (+) est alors ex ecut ee. Celle-ci d epile une premi` ere fois la pile dex ecution pour obtenir la valeur 5, puis une deuxi` eme fois pour r ecup erer le 3 (attention : on r ecup` ere les valeurs dans lordre inverse o` u ils ont et e d epos es). La fonction calcule alors 3 + 5 = 8 et elle empile la valeur 8 avant de se terminer. On peut alors cr eer la liaison entre la valeur 8 et lidentiant x simplement en d epilant la pile de mani` ere ` a r ecup erer le 8, puis en r ealisant eectivement laectation. An que votre pile dex ecution puisse contenir ` a la fois des entiers, des r eels et des cha nes de caract` eres, on supposera quelle contient des el ements du type somme suivant : type valeur = | N of int | R of float | S of string;; Q 84.1 Cr eez une pile que vous appellerez exec pile et une exception Value error,
page 122
puis ecrivez les fonctions suivantes : put_int_arg : int -> unit qui prend en argument un entier et qui lempile sur la pile exec pile. put_float_arg : float -> unit qui prend en argument un nombre r eel et qui lempile sur la pile exec pile. put_string_arg : string -> unit qui prend en argument une cha ne de caract` eres et qui empile celle-ci sur la pile exec pile. get_int_arg : unit -> int qui, si l el ement en haut de la pile exec pile est un entier, d epile celle-ci et le renvoie, et sinon l` eve lexception Value error. get_float_arg : unit -> float : idem mais pour les nombres r eels. get_string_arg : unit -> string : idem mais pour les cha nes de caract` eres. put_int_return : int -> unit qui empile sur la pile dex ecution exec pile la valeur de retour dune fonction ` a valeurs enti` eres. put_float_return : float -> unit qui empile sur la pile dex ecution exec pile la valeur de retour dune fonction ` a valeurs r eelles. put_string_return : string -> unit qui empile sur la pile dex ecution exec pile la valeur de retour dune fonction renvoyant des cha nes de caract` eres. get_int_return : unit -> int qui permet de r ecup erer la valeur de retour dune fonction si celle-ci est enti` ere et qui l` eve lexception Value error sinon. get_float_return : unit -> float : idem mais pour les nombres r eels. get_string_return : unit -> string : idem mais pour cha nes de caract` eres. une fonction f : unit -> unit qui simule en utilisant votre pile Q 84.2 Ecrivez
page 123
dex ecution les instructions suivantes : let f x y = (float_of_int x) *. y;; f 10 30.;; Q 84.3 Ecrivez en utilisant votre pile dex ecution une fonction fibo : unit -> unit qui simule Fibonnacci : let fibo n = let rec iter n = if n <= 1 then 1 else iter (n-1) + iter (n-2) in if n < 0 then failwith "fibo" else iter n;; Attention : il faut vraiment simuler les appels r ecursifs et non d er ecursiver le code ci-dessus. Pour voir l evolution de l etat de la pile, vous pouvez utiliser la primitive #trace sur les fonctions de la premi` ere question (#trace sutilise en tapant #trace fonction;; o` u fonction est le nom de la fonction dont on veut tracer lex ecution). Exercice 85 (Les tours de Hano ) Petit divertissement math ematique mis au point par Edouard Lucas en 1883 : au d epart,
page 124
on dispose de 3 piquets. Le premier porte n disques de tailles toutes di erentes et empil es du plus grand (en bas) au plus petit (en haut). Le probl` eme consiste ` a d eplacer tous ces disques jusquau 3` eme piquet sachant que lon respecte les r` egles suivantes : on ne d eplace quun disque ` a la fois ; on ne peut d eplacer quun disque se trouvant en haut dune pile ; aucun disque ne doit etre empil e sur un disque de diam` etre inf erieur. Q 85.1 An de di erencier les disques, nous les d esignerons par leur num ero, de 1 ` a n, sachant que plus le num ero est petit, plus le diam` etre du disque lest aussi. Cr eez un tableau contenant 3 piles dentiers symbolisant les 3 piquets, puis une fonction : initialise : int -> unit telle que (initialise n) remplit le premier piquet avec les n disques dispos es du plus grand en bas au plus petit en haut, et laisse les deux autres piquets vides. Q 85.2 Pour obtenir une solution du jeu, on peut observer que si lon veut d eplacer les n disques du piquet 1 vers le piquet 3, alors il sut de d eplacer les n 1 disques sur le dessus du piquet 1 vers le piquet 2, puis de d eplacer le disque se trouvant maintenant en haut du piquet 1 (cest donc le disque n) vers le piquet 3, et enn de d eplacer les n 1 disques sur le dessus du piquet 2 vers le piquet 3. La m eme mani` ere dop erer permettra de d eplacer les n 1 premiers disques de 2 vers 3. Plus g en eralement, on utilisera lalgorithme de d eplacement suivant : si lon veut d eplacer les p disques sur le dessus du piquet i vers le piquet j , et si lon appelle k le troisi` eme piquet, alors on commencera par d eplacer les p 1 disques sur le dessus du piquet i vers le piquet k , puis on d eplacera le disque se
page 125
trouvant maintenant en haut du piquet i vers j , et enn on d eplacera les p 1 disques sur le dessus de k vers j .
tat initial
tat intermdiaire
Ecrivez une fonction deplace : int -> int -> int -> unit telle que (deplace p i j) eectue selon lalgorithme d ecrit ci-dessus le d eplacement de p disques du piquet i vers le piquet j et qui ache ` a l ecran tous les d eplacements de disques eectu es. Vous pourrez supposer que ces d eplacements v erient les r` egles du jeu. une fonction hanoi : int -> unit telle que (hanoi n) initialise le Q 85.3 Ecrivez jeu en pla cant n disques sur le premier piquet et laisse vide les 2 autres, puis ache les d eplacements ` a eectuer pour faire passer tous les disques du piquet 1 au piquet 3.
page 126
page 127
Tout comme les piles, les les peuvent etre repr esent ees par un tableau. Q 86.2 D enissez un nouveau type a myqueue2 en utilisant un enregistrement contenant un tableau, lindice du premier el ement et lindice du dernier el ement de la le. Les el ements du tableau sont ceux de la le, rang es successivement de la gauche vers la droite. Q 86.3 D enissez la fonction new queue : unit -> a myqueue qui construit une le vide. Q 86.4 R e ecrivez les d enitions des primitives de base create, is empty, clear, push, pop et top. Exercice 87 (simulation dun pipe Unix) Dans cet exercice, on veut simuler une commande Unix similaire ` a: cat tme9.ml | sed s/^ *//g. Sous Unix, la commande cat ache sur la sortie standard le contenu dun chier. Le pipe (|) connecte la sortie standard de la commande ` a gauche du pipe sur lentr ee standard de la commande ` a droite du pipe. Ainsi, dans la commande ci-dessus, le contenu du chier tme9.ml est pass e en entr ee de la commande sed qui, gr ace au script s/^ *//g, lache tout en supprimant les espaces en d ebut de ligne. Apr` es le TME, vous pourrez regarder les mans de cat et de sed pour am eliorer votre culture Unixienne. Remarquons quici on aurait pu aussi bien utiliser la commande sed s/^ *//g tme9.ml.
page 128
une fonction skip_spaces : string -> string telle que : Q 87.1 Ecrivez (skip spaces str) renvoie une cha ne de caract` eres identique ` a str ` a ceci pr` es que les espaces en d ebut de ligne ont et e supprim ees. une fonction f : string -> string Queue.t -> unit telle que (f Q 87.2 Ecrivez filename queue) lit un chier dont le nom est filename et qui empile chaque ligne lue dans la le queue. Pour cela, utilisez les fonctions suivantes du module Pervasives de la Core library : open_in : string -> in_channel qui permet douvrir en lecture un chier. close_in : in_channel -> unit qui permet de fermer un chier ouvert en lecture. input_line : in_channel -> string qui permet de lire une ligne dun chier. Chaque nouvel appel ` a input line lit une nouvelle ligne du chier. une fonction g : string Queue.t -> unit qui d ele lensemble des Q 87.3 Ecrivez cha nes de la le pass ee en argument et qui, pour chaque cha ne, supprime les espaces en d ebut de ligne et ache le r esultat ` a l ecran. Lapplication de la fonction f puis de la fonction g sur la m eme le simule un pipe Unix (` a ceci pr` es que la fonction f se termine avant que la fonction g ne soit lanc ee alors que, sous Unix, les deux fonctions sex ecutent en concurrence).
page 129
page 130
egalite : ab -> ab -> bool qui teste l egalit e de ces deux arbres. une fonction somme : ab -> int qui, etant donn e un arbre de type Q 89.2 Ecrivez ab, renvoie la somme des el ements de cet arbre. Q 89.3 Ecrivez une fonction miroir : ab -> ab qui, etant donn e un arbre de type ab, renvoie limage miroir de cet arbre. Le miroir dun arbre consiste ` a inverser les ls gauches et les ls droits de larbre. Q 89.4 Le Strahler dun arbre binaire dentiers est un nombre qui se d enit de la fa con suivante : 1. le Strahler de larbre vide vaut 0, 2. le Strahler dun arbre non vide est egal : (a) ` a 1 + le Strahler dun des sous-arbres si les Strahlers des sous-arbres gauche et droit sont egaux, (b) au max des deux Strahlers sils sont di erents. Ecrivez une fonction strahler : ab -> int qui, etant donn e un arbre de type ab, renvoie le Strahler de cet arbre.
page 131
Exercice 90 (Codage de Human) Lalgorithme de Human est tr` es utilis e en compression de donn ees et, depuis son d eveloppement en 1952, il a suscit e beaucoup de recherches. Il sert de base ` a de nombreux programmes. JPEG et MP3 sen servent par exemple dans une de leurs etapes de compression. Lalgorithme consiste : 1. ` a dresser une liste des symboles (caract` eres) apparaissant dans le texte ` a compresser, cette liste etant tri ee par ordre d ecroissant de fr equence dapparition des symboles dans le texte. 2. ` a construire de la mani` ere suivante un arbre dans lequel chaque symbole se trouve sur une feuille : (i) on part dun arbre vide ; (ii) on prend les deux symboles de la liste ayant les plus petites fr equences, appelons-les ai et aj , et on les enl` eve de la liste ; (iii) on cr ee un symbole repr esentant la r eunion des deux choisis, appelons-le aij , et on le rajoute ` a la liste ; (iv) on rajoute alors ` a larbre un arbre binaire constitu e dune racine, aij , et de deux feuilles, ai et aj ; (v) on it` ere ` a partir de l etape (ii) jusqu` a ce quil ne reste plus quun seul symbole. 3. ` a parcourir larbre ainsi cr e e an de d eterminer le codage de chaque symbole de lalphabet. Exemple : consid erons cinq symboles, a1, a2, a3, a4 et a5 apparaissant dans un texte avec
page 132
Lalgorithme de Human eectue alors les op erations suivantes : 1. a4 est combin e avec a5 car ce sont les caract` eres ayant les plus petites fr equences dapparition. Leur combinaison forme alors un nouveau symbole que nous appellerons a45 et dont la fr equence dapparition dans le texte est 0, 1 + 0, 1 = 0, 2. On cr e e un arbre binaire ayant pour racine a45 et comme feuilles a4 et a5. 2. On a maintenant 3 symboles avec les probabilit es 0,2 : a2, a3 et a45. On doit en 1 combiner deux, peu importe lesquels . On va s electionner arbitrairement les symboles a3 et a45. Ceux-ci en forment donc un nouveau, que nous appellerons a345 et dont la fr equence dapparition est 0, 2 + 0, 2 = 0, 4. 3. On a maintenant deux symboles avec des fr equences de 0,4 : a1 et a345, plus un symbole, a2, avec une fr equence de 0,2. On doit donc combiner a2 avec, au choix, a1 ou a345. Choisissons de combiner a2 et a345. On obtient le symbole a2345 dont la fr equence est 0,6. 4. Enn, il ne reste plus que deux symboles, a1 et a2345. On les combine pour obtenir ` cette a12345 dont la fr equence dapparition est 1. A etape, larbre d eterminant les
En fait, lordre peut etre important pour certaines applications. Cela dit, quels que soient les deux symboles que lon combine, la taille du ux de sortie sera toujours la m eme.
1
page 133
codes des symboles est construit : les symboles dorigine sont les feuilles et chaque combinaison repr esente un noeud de larbre :
a1
0,4
a1 a12345
1
1 1 1 1 0 0 0 0
a2
0,2
a2 a3 a4 a5
a3
0,2
a2345
0,6
a4
0,1
a345 a45
0,2 0,4
a5
0,1
` a chaque noeud de larbre, on code lune des deux ar etes sortantes (une des ar etes sur la gure ` a droite ci-dessus) avec un 1 et lautre avec un 0. 5. Pour obtenir le codage dun symbole, il sut de partir du noeud-symbole ayant une fr equence de 1 (autrement dit, la racine de larbre), et de parcourir larbre jusqu` a ce quon atteigne le symbole d esir e. Au fur et ` a mesure du cheminement, on note les 0/1 des arcs parcourus. Ceux-ci forment le code correspondant au symbole. Ainsi, le code de a3 sera obtenu en partant de a12345, en allant sur la branche vers a2345 (on
page 134
obtient le premier bit du code : 0), puis en allant vers a345 (bit 0), puis en allant vers a3 (bit 1). Le code de a3 sera donc 001. Les arbres ci-dessus nous donnent donc les codes suivants : a1 1 a2 01 a3 001 a4 0001 a5 0000.
Notons que lon aurait pu obtenir dautres codes si lon avait fait dautres choix de combinaisons. Par exemple, si lon avait combin e a4 et a5, puis a2 et a3, puis a1 et a45, puis a145 et a23, on aurait obtenu larbre suivant :
a1
0,4
a1 a23
0,4
1 1 1 0 0 1 0 0
a2
0,2
a2 a12345 a145
0,6 1
a3
0,2
a3 a4 a5
a4
0,1
a45
0,2
a5
0,1
page 135
Quoi quil en soit, les chiers de sortie auront la m eme taille. Pour montrer cela, il sut de calculer lesp erance de gain (en bits/octet) des deux codages : E (code 1) = 0, 4 1 + 0, 2 2 + 0, 2 3 + 0, 1 4 + 0, 1 4 = 2, 2, E (code 2) = 0, 4 2 + 0, 2 2 + 0, 2 2 + 0, 1 3 + 0, 1 3 = 2, 2. En moyenne, un octet du chier de d epart sera donc cod e en sortie sur 2,2 bits. En fait, cette egalit e des taux de compression nest pas surprenante puisque ce qui importe dans lalgorithme, ce nest pas vraiment le symbole quon code, mais sa fr equence dapparition. Q 90.1 Ecrivez une fonction frequence : string -> int array telle que : (frequence str) renvoie un tableau de 256 entiers dans lequel chaque case contient le nombre doccurrences dans str du caract` ere dont le code ASCII est lindex de la case. Par exemple, (frequence "aabd") renverrait un tableau tab dans lequel toutes les cases valent 0 sauf tab.(97) qui vaudrait 2 car cela repr esente le caract` ere a , tab.(98) qui vaudrait 1 et tab.(100) qui vaudrait 1. Q 90.2 Ecrivez une fonction insert ordonnee telle que : a ll et renvoie (insert ordonnee (car,nb occ) ll) rajoute le couple (car,nb occ) ` le r esultat. Vous supposerez quavant linsertion ll est tri ee par ordre croissant du nombre doccurrences (2` eme el ement des couples). Vous ferez en sorte dins erer (car,nb occ) de mani` ere ` a ce que la nouvelle liste ainsi cr e ee soit encore tri ee par ordre croissant du nombre doccurrences. Indiquez le type de votre fonction.
page 136
une fonction : Q 90.3 Ecrivez cree_liste_ordonnee : int array -> (char * int) list prenant en argument un tableau g en er e par la fonction frequence et renvoyant la liste des couples (caract` ere,nombre doccurrences) pour lesquels le nombre doccurrence est non nul. La liste doit etre tri ee par ordre croissant du nombre doccurrence. Q 90.4 soit le type : type huffman_tree = Nil | Elt of huffman_tree * char * huffman_tree;; permettant de repr esenter les arbres de Human. Ecrivez une fonction transfo : (char * b) list -> (huffman_tree * b) list de telle sorte que (transfo liste) renvoie une liste dans laquelle chaque couple (car,nb occ) de liste a et e transform e en un couple (arb,nb occ) o` u arb est un arbre de Human contenant un seul noeud : car. Q 90.5 Ecrivez une fonction : cree_huffman : (huffman_tree * int) list -> huffman_tree qui, etant donn e une liste de couples (arb,nb occ) darbres de Human et de nombres doccurrences, renvoie larbre de Human obtenu ` a lissue de lalgorithme de Human d ecrit plus haut. Q 90.6 Ecrivez une fonction cree code : huffman_tree -> (char * string) list qui, etant donn e un arbre de Human, renvoie la liste des codes associ es ` a chaque feuille de larbre. Vous pourrez associer un 0 ` a chaque branche gauche et un 1 ` a chaque branche droite de larbre.
page 137
une fonction : Q 90.7 Ecrivez cree_tableau_code : (char * string) list -> string array qui, etant donn e une liste dassociation (caract` ere, code de Human) renvoie un tableau de 256 el ements dans lequel chaque case contient le code de Human du caract` ere dont le code ASCII est lindex de la case. une fonction encode : string -> string qui renvoie la cha ne comQ 90.8 Ecrivez press ee par Human, cest-` a-dire la cha ne obtenue en rempla cant chaque caract` ere par son code de Human. une fonction taux_compression : string -> float qui calcule le Q 90.9 Ecrivez taux de compression obtenu par Human. Celui-ci est donn e par la formule : taux de compression = 1 taille du chier de sortie . taille du chier dentr ee
Exercice 91 (D ecomposition de Shannon) On consid` ere dans cet exercice des fonctions bool eennes f : Bn B, o` u B = {0, 1}. Par exemple, f1 = (a b c) (a b c) (a b c) (a b c) (a b c) (a b c)
page 138
est une fonction bool eenne des variables a, b, c. On dira que deux fonctions sont egales si, pour toutes les valeurs de lunion de leurs variables, elles produisent le m eme r esultat. Ainsi f2 = (b c) b est egale ` a f1 car les tables de v erit e de ces deux fonctions sont : a 0 0 0 0 1 1 1 1 b 0 0 1 1 0 0 1 1 c 0 1 0 1 0 1 0 1 f 0 1 1 1 0 1 1 1
Soit f : Bn B une fonction bool eenne sur un ensemble de variables x1, . . . , xn. On d enit les cofacteurs de f de la mani` ere suivante : cof (f, xi, 0) = f (x1, . . . , xi1, 0, xi+1, . . . , xn) et cof (f, xi, 1) = f (x1, . . . , xi1, 1, xi+1, . . . , xn). Le th eor` eme de Shannon arme quil existe une unique d ecomposition de f suivant ses cofacteurs : f = (xi cof (f, xi, 1)) (xi cof (f, xi, 0)).
page 139
Les feuilles de cet arbre contiennent la valeur prise par la fonction pour les valeurs de leurs di erents anc etres. Cet arbre peut donc etre vu comme une repr esentation de la table de v erit e ci-dessus. Q 91.1 Pour exprimer une fonction bool eenne, on utilise le type suivant : type bexpr = | TRUE | FALSE | B of string (* variable bool eenne *) | NOT of bexpr | OR of bexpr * bexpr | AND of bexpr * bexpr;;
page 140
D eclarez une variable f1 de type bexpr repr esentant la fonction b c. Faites de m eme pour f 2 = (a b c) (a b c) et pour f 3 = (b c) b.
Q 91.2 Pour repr esenter les arbres de Shannon, on utilise le type suivant : type btree = | Nil (* arbre vide *) | Leaf of int (* une feuille contenant la valeur de la fonction f *) | Node of btree * string * btree (* une variable avec ses 2 sous-arbres cofacteurs *) Ecrivez une fonction cree_var : bexpr -> string list qui, etant donn e un arbre de Shannon, renvoie la liste de toutes ses variables. Attention : une m eme variable ne doit appara tre quune seule fois dans la liste retourn ee. Q 91.3 Ecrivez une fonction cof : string -> bexpr -> bexpr -> bexpr telle que (cof xi valeur bexpr) renvoie le cofacteur de bexpr obtenu pour xi = valeur. Ce cofacteur correspond tout simplement ` a la simplication maximale de lexpression bexpr sachant que xi = valeur. Par exemple, si bexpr = (b c) b, alors (cof b 0 bexpr) correspond ` a (f alse c) f alse = true c = c, la fonction renverra alors lexpression c. Q 91.4 Ecrivez une fonction cree_shannon : string list -> bexpr -> btree qui, etant donn e une expression bool eenne et une liste de variables, cr ee larbre de Shannon repr esentant lexpression bool eenne et dont lensemble des noeuds forment, de la racine vers les feuilles, la liste de variables pass ee en argument.
page 141
une fonction compare : bexpr -> bexpr -> bool qui, etant donn e Q 91.5 Ecrivez deux fonctions bool eennes f1 et f2, renvoie un bool een indiquant si ces deux fonctions sont egales. Pour cela, votre fonction commence par r ecup erer lunion de lensemble des variables impliqu ees dans f1 et f2. Puis elle cr ee les arbres de Shannon de f1 et f2. Enn, elle parcourt les deux arbres pour voir si ceux-ci ont des valeurs identiques ` a leurs feuilles. Le cas ech eant, les fonctions sont egales.
page 142
Implantation : On d enit le type OCaml suivant pour repr esenter une une arborescence binaire : type a noeud = { mutable elt : a; mutable sag : a ab; mutable sad : a ab; mutable parent : a ab } and a ab = Nil | V of a noeud ;; et le type OCaml suivant pour repr esenter une arborescence binaire de recherche : type a abr = {inf : a -> a -> bool ; ab : a ab} ;; Exercice 92 (Cr eation dune arborescence binaire de recherche vide) Donnez une d enition de la fonction vide : (a -> a -> bool) -> a abr telle que (vide rel), lorsque rel est une relation dordre sur le type des etiquettes, retourne la repr esentation dune arborescence de recherche vide.
page 143
Exercice 93 (Insertion dans une arborescence binaire de recherche) Donnez une d enition de la fonction ins : a -> a abr -> a abr telle que (ins e a) retourne une arborescence binaire de recherche contenant toutes les etiquettes de larborescence binaire de recherche a et l etiquette e ins er ee en feuille. Exercice 94 (Recherche dans une arborescence binaire de recherche) Donnez une d enition de la fonction member : a -> a abr -> bool telle que (member x a) retourne true si et seulement si l el ement x est egal ` a une etiquette de larborescence binaire de recherche a. Exercice 95 (Liste des etiquettes en ordre inxe) Donnez une d enition de la fonction to_list : a abr -> a list telle que (to list a) retourne la liste des etiquettes de larborescence binaire de recherche a, liste ordonn ee suivant le parcours inxe de larborescence.
page 144
Exercice 96 (Essais) Q 96.1 D eclarez un tableau v de 20 el ements contenant, en ordre croissant, les entiers de 0 ` a 19. Q 96.2 Modiez le tableau v pour obtenir une permutation par tirage al eatoire de tous ses el ements. Q 96.3 Construisez une arborescence binaire de recherche a ` a partir du tableau v permut e. Q 96.4 D eclarez la liste l r esultant de lapplication (to list a). Exercice 97 (Suppression dun el ement) Nous travaillons temporairement sur le champ ab dune arborescence binaire de recherche. Q 97.1 (Plus grand el ement) Donnez une d enition de la fonction max : a ab -> a telle que (max a.ab) retourne la plus grande etiquette de larborescence binaire de recherche a ou l` eve lexception Invalid argument "max" si larbre a.ab est vide. Q 97.2 (Suppression du plus grand el ement) Donnez une d enition de la fonction sauf_max : a ab -> a ab telle que (sauf max
page 145
a.ab) retourne larbre a.ab amput e de sa plus grande etiquette ou l` eve une exception a bien recha ner larInvalid argument "sauf max" si larbre a.ab est vide. Attention ` borescence. En particulier, noubliez pas de mettre ` a jour les champs parent. Q 97.3 (Les deux r esultats en un seul parcours) En vous aidant des d enitions pr ec edentes, donnez une d enition directe de la fonction max_saufMax : a ab -> a * a ab telle que (max saufMax a.ab) retourne le doublet : plus grande etiquette de larbre a.ab, arbre a.ab amput e de sa plus grande etiquette ou l` eve lexception Invalid argument "max saufMax" si larbre a.ab est vide. Q 97.4 (Suppression de l etiquette ` a la racine) Pour supprimer l etiquette en racine dun arbre a.ab dune arborescence binaire de recherche a non vide, il sut de faire remonter la plus grande etiquette de son sous-arbre gauche si elle existe ` a la racine (ou la plus petite etiquette de son sous-arbre droit). Donnez une d enition de la fonction sauf_rac : a ab -> a ab telle que (sauf rac a.ab) retourne larbre dune arborescence binaire de recherche contenant toutes les etiquettes de a sauf celle ` a la racine de a ou l` eve lexception Invalid argument "sauf rac" si larbre a.ab est vide. Q 97.5 (Suppression dune etiquette) Pour cette etape nale, on travaille ` a nouveau sur une arborescence binaire de recherche. Donnez une d enition de la fonction sauf_elem : a -> a abr -> a abr telle que
page 146
(sauf elem x a) retourne une arborescence binaire de recherche issue de a par suppresetiquette nexiste sion dune etiquette egale ` a x ou l` eve lexception Not found si une telle pas dans a. Exercice 98 (Calcul du successeur) Q 98.1 Donnez une d enition de la fonction min : a ab -> a noeud qui, etant donn e une arborescence binaire de recherche a, renvoie le noeud dont l etiquette est minimale par rapport ` a la relation dordre R. Q 98.2 Donnez une d enition de la fonction : successeur : a noeud -> a abr -> a noeud telle que (successeur x a) renvoie le noeud ayant la plus petite etiquette sup erieure ou egale (au sens de R) ` a celle de x. On rappelle que si x a un sous-arbre droit, alors le successeur correspond au min de ce sous-arbre, et sinon il correspond au premier anc etre que lon rencontre en remontant dun ls gauche vers son parent (cf. le cours). Exercice 99 (Calcul du pr ed ecesseur) Par sym etrie, donnez une d enition des fonctions : max : a ab -> a noeud et predecesseur : a noeud -> a abr -> a noeud.
page 147
Exercice 100 (Autre algorithme de suppression) Comme on la vu en cours, on peut r ealiser la suppression dun noeud x dans une arborescence de recherche a en envisageant 3 cas : le noeud x na ni ls gauche ni ls droit : on peut alors lenlever de larbre sans autre modication, cf. la gure (a). le noeud x na quun seul ls : on relie alors ce ls avec le parent de x (si celui-ci existe bien s ur). Cf. la gure (b). le noeud x a un ls gauche et un ls droit : soit y le successeur de x. On remplace x par y et le ls droit de y, sil existe, est reli e au ls gauche du parent de y. Cf. la gure (c). Donnez une d enition de la fonction sauf_elem : a -> a abr -> a abr qui impl emente cet algorithme.
page 148
15 5 3 10 6 7 15 5 3 10 6 7 12 13 12 13 x
page 149
page 150
Exercice 102 (Arborescence et syst` eme de chiers) On repr esente un syst` eme de chiers (imaginez par exemple celui de Linux) par une arborescence. Les chiers sont les feuilles de larborescence et les r epertoires sont les noeuds internes. En OCaml nous allons repr esenter le syst` eme de chiers ` a laide du type : type sysfs = | Nil (* arbre vide *) | Arbre of string * sysfs list;; (* un noeud et la liste de ses enfants *) Q 102.1 D enissez la fonction find_in_liste : string -> sysfs list -> sysfs de telle sorte que (find in liste x liste) renvoie larborescence dont la racine a pour nom x si celle-ci existe ou bien l` eve lexception Not found si la racine daucune arborescence nest egale ` a x. Q 102.2 Dans cette question, on veut savoir si un chier ou un r epertoire donn e existe. On suppose que le nom de ce dernier est d ecoup e en unit es repr esentant chacune un nom de r epertoire ou de chier. Par exemple /usr/bin/emacs est d ecoup e en ["/" ; "usr" ; "bin" ; "emacs"]. Pour savoir si ce chier existe, il sut de parcourir larborescence du syst` eme de chiers et v erier si la racine de cette derni` ere est egale ` a "/", puis sil existe une sous-arborescence de "/" egale ` a "usr", puis une sous-arborescence de "usr" egale ` a "bin" et ainsi de suite.
page 151
D enissez la fonction exists : string list -> sysfs -> bool qui recherche si un chier dont le nom est pass e sous forme de liste existe dans le syst` eme de chiers pass e en deuxi` eme argument. An dutiliser au maximum la fonction find in liste et eviter de faire un traitement sp ecial pour "/", vous pourrez avantageusement rechercher votre chier non pas dans sysfs mais dans (Arbre ("", [sysfs])). Dans ce cas, chaque el ement de la liste pass ee en premier argument doit etre recherch ee dans la liste des descendants de la racine courante de larborescence. Q 102.3 D enissez la fonction create_sysfs : string list -> sysfs qui, etant donn e une liste repr esentant le nom dun chier, renvoie une arborescence constitu ee uniquement par ce chier. Ainsi, (create sysfs ["toto" ; "titi" ; "emacs"]) cr eera une arborescence dont la racine est "toto", celle-ci ayant un seul ls, "titi", lui-m eme ayant pour seul ls "emacs". Q 102.4 D enissez la fonction : find_sauf_liste : string -> sysfs list -> sysfs * sysfs list telle que (find sauf liste x liste) renvoie le couple (y,z) o` u y est l el ement de liste dont la racine est x et z est egale ` a liste priv ee de y. Si x ne correspond ` a aucune racine des arborescences de liste alors la fonction doit lever lexception Not found. Q 102.5 D enissez la fonction add : string list -> sysfs -> sysfs qui, etant donn e un chier dont le nom est pass e sous forme dune liste L en premier argument, et etant donn e un syst` eme de chiers S , renvoie un nouveau syst` eme dans lequel le nouveau chier a et e ins er e. Id ee : parcourir le syst` eme de chiers S tant quil existe dans ce dernier
page 152
des noms de r epertoires correspondant aux noms de L. Quand on arrive sur un nom qui nexiste pas, ce nom et tous les noms suivants dans L doivent former une nouvelle sousarborescence. On la cr ee alors en utilisant la fonction create sysfs. Exercice 103 (Recherche dans un graphe de jeu) Dans cet exercice, on veut cr eer un programme capable de jouer tout seul au tic-tac-toe. Ce jeu se joue ` a 2. Appelons MAX et MIN les deux joueurs et supposons que MAX joue en premier et quil marque des croix et MIN des ronds. On peut repr esenter toutes les s equences de coups possibles jou es successivement par MAX et MIN gr ace ` a une arborescence : la racine correspond ` a lespace de jeu avant que MAX ne joue. Lors de son premier coup, MAX doit placer une croix sur cet espace. Les ls de MAX correspondent alors aux espaces obtenus apr` es les placements possibles de cette croix. Ensuite MIN joue. On peut alors rajouter de nouveaux ls correspondant aux espaces apr` es placement de la croix de MAX et du rond de MIN, etc. On obtient alors un graphe de jeu dont les feuilles, si lon d eveloppe tout larbre, sont lensemble des possibilit es de remplir lespace avec des croix et des ronds, cf la gure ci-dessous.
page 153
.........
croix place par MAX
......... ....................
rond plac par MIN
Dans cette arborescence il existe des branches qui semblent plus favorables que dautres pour que MAX gagne la partie. Le but de lexercice consiste donc ` a essayer de d eterminer quelles sont ces branches et ` a faire en sorte que MAX les suive. Si, pour une conguration donn ee, on pouvait conna tre le nombre de parties possibles gagnantes, nulles ou perdantes pour MAX issues de cette conguration, il surait de choisir la branche maximisant le nombre de parties gagnantes. Malheureusement, dune mani` ere g en erale, larborescence de jeu est souvent trop grande pour que lon puisse conna tre ces nombres avec exactitude. En revanche on peut les estimer, cette estimation etant de plus en plus pr ecise au fur et ` a mesure que lon se rapproche de la n de la partie. Supposons donc que lon ait ` a notre disposition une fonction f ` a valeurs r eelles evaluant, pour chaque conguration possible du jeu, les chances de succ` es de MAX. Alors, pour le premier coup de MAX, il sut de choisir
page 154
la branche qui maximise f . Cela dit, comme la fonction nest pas tr` es pr ecise, on a int er et ` a regarder un peu plus loin dans le jeu : regardons 2 coups, un par MAX et lautre par MIN. Une fois le coup de MAX choisi, MIN va essayer de minimiser f . Par cons equent, le choix optimal pour MAX consiste ` a choisir la branche qui maximise le min de f trouv e dans chaque sous-arborescence. En g en eralisant, ` a chaque niveau darborescence, on gardera uniquement la branche qui maximise ou minimise (suivant que cest MAX ou MIN qui joue) la fonction f sur lensemble des ls du niveau. Q 103.1 On d enit le type suivant pour g erer lespace de jeu : type tictactoe = { taille : int; (* nombre de lignes-colonnes de lespace de jeu *) mat : int array array };; (* matrice carr ee de lespace de jeu contenant des 1 = croix, 2 = rond, 0 = vide *) D enissez une fonction make : int -> tictactoe cr eant un nouvel espace de jeu vierge de la taille pass ee en param` etre. D enissez une fonction set : tictactoe -> int -> int -> int -> unit de telle sorte que (set t nb joueur i j) place une croix ou un rond dans la case (i, j ) du tic-tac-toe suivant que nb joueur est le joueur 1 (MAX) ou le joueur 2 (MIN). D enissez une fonction unset : tictactoe -> int -> int -> int -> unit telle ee pr ec edemment par que (unset t nb joueur i j) rend vierge la case (i, j ) occup le joueur nb joueur. Q 103.2 On d enit la fonction f de la mani` ere suivante : si p est une conguration de
page 155
lespace de jeu, alors : f (p) = taille taille si p est une victoire pour MAX. f (p) = taille taille si p est une victoire pour MIN. f (p) = (nombre de rang ees, colonnes ou diagonales compl` etes qui sont toujours ouvertes pour MAX, cest-` a-dire que MAX pourrait remplir enti` erement avec des croix) - (nombre de rang ees, colonnes ou diagonales compl` etes qui sont toujours ouvertes pour MIN). Ainsi, la conguration ci-dessous a pour valeur f (p) = 6 4 = 2. D enissez la fonction calc non victoire : tictactoe -> int -> int telle que (calc non victoire t nb joueur) renvoie le nombre de rang ees, colonnes ou diagonales compl` etes qui sont toujours ouvertes pour le joueur nb joueur. Algorithme : parcourir toutes les lignes, puis toutes les colonnes puis les 2 diagonales et comptabiliser celles que le joueur pourrait remplir enti` erement. D enissez la fonction check_victoire : tictactoe -> int -> bool telle que (check victoire t nb joueur) renvoie un bool een indiquant si le joueur nb joueur a gagn e la partie. D enissez la fonction calc_score : tictactoe -> int renvoyant le score f correspondant ` a l etat du jeu pass e en param` etre. Q 103.3 D enissez deux fonctions mutuellement r ecursives : max_suivants : tictactoe -> int -> int * int * int et
page 156
min_suivants : tictactoe -> int -> int * int * int telles que (max suivants tic prof) (resp. (min suivants tic prof)) renvoie un triplet contenant les coordonn ees de la prochaine croix (resp. du prochain rond) ` a placer sur lespace de jeu, ainsi que la valeur de l evaluation de f pour ce choix. Le param` etre prof correspond ` a la profondeur maximale de sous-arborescence que lon sautorise ` a parcourir ; arriv e` a ce niveau darborescence, on calcule f avec les fonctions de la question pr ec edente. Id ee de lalgorithme pour max suivants : si lon est arriv e` a une profondeur de prof, on ecup` ere la liste, pour toutes renvoie le triplet ((-1),(-1),calc score tic) sinon on r les croix possibles, des triplets (coordonn ees de la croix, evaluation de f ). Comme on nest pas arriv e` a la profondeur requise, on doit donc prendre pour evaluation le min de ce que MIN va joueur, autrement dit, la valeur du min suivants tic (prof - 1). Une fois la liste constitu ee, il sut de renvoyer le triplet maximisant l evaluation de f . Si la liste est vide, cela signie que lon est en n de partie, on renvoie donc ((-1),(-1),calc score tic), les valeurs n egatives des coordonn ees de la croix indiquant que lon ne peut plus placer de croix. Lalgorithme pour min suivants est similaire. Q 103.4 D enissez jeu : int -> int -> unit prenant en premier param` etre la taille de lespace de jeu et en deuxi` eme la profondeur maximale darborescences ` a examiner. La fonction jeu lance alors le jeu, demande ` a lutilisateur (MIN) de rentrer les coordonn ees dun rond (utiliser la fonction read int), met ` a jour lespace de jeu, lance la fonction max suivants pour d eterminer le meilleur placement de croix pour MAX, eectue ce placement, lache ` a l ecran puis reboucle sur la demande dun rond ` a lutilisateur. Le jeu se termine soit quand lun des deux joueurs a gagn e soit quand toutes les cases de lespace
page 157
page 158
1
(a) arborescence
Fig. 8 Achage dune arborescence binaire. Q 104.1 Ecrivez une fonction aff : string -> (a -> string) -> a ab -> unit telle que (aff gauche f ab) ache larbre ab comme indiqu e dans la gure 8 mais avec chaque ligne (except e peut- etre la premi` ere) pr ec ed ee de la cha ne gauche. Comme on consid` ere des a ab arborescences, on ne peut savoir a priori comment acher les etiquettes des noeuds, cest pourquoi on doit passer en 2` eme argument de aff une fonc-
page 159
tion f qui renvoie la cha ne de caract` eres ` a acher pour chaque etiquette. Id ee : acher l etiquette du noeud courant puis, si la sous-arborescence gauche est non vide, acher une ligne contenant gauche puis | , une autre ligne contenant gauche et +-- , et r eappeler la fonction avec la sous-arborescence gauche et une valeur de gauche appropri ee. Faire de m eme avec la sous-arborescence droite. Par exemple : let rec x1 = V { elt=1; sag=x2; and x2 = V { elt=0; sag=Nil; and x3 = V { elt=5; sag=x4; and x4 = V { elt=2; sag=Nil; and x5 = V { elt=4; sag=Nil; in aff "toto" string_of_int x1;; provoquerait lachage suivant : 1 toto| toto+--0 toto| toto+--5 toto | toto +--2 toto | toto +--4 sad=x3; sad=Nil; sad=x5; sad=Nil; sad=Nil; parent=Nil} parent=x1} parent=x1} parent=x3} parent=x3}
page 160
une fonction affiche : a abr -> (a -> string) -> unit preQ 104.2 Ecrivez nant en param` etre un arbre binaire de recherche et une fonction transformant ses etiquettes en cha nes de caract` eres, et achant larbre comme indiqu e dans la gure 8. Exercice 105 (Equilibrage darborescence binaire de recherche) On d enit le type somme : type sens_sa = Gauche | Droite;; Q 105.1 Ecrivez une fonction : reparent : a ab -> a noeud -> sens_sa -> unit de telle sorte que (reparent ab noeud sens) rajoute ab comme enfant de noeud. Le param` etre sens indique sil faut le rajouter comme sous-arborescence gauche ou droite. Vous supposerez que noeud na pas denfant l` a o` u ab est rajout e. En revanche, avant lajout, ab peut avoir un parent et il convient de mettre ` a jour proprement les cha nages entre parents et enfants. Q 105.2 On d enit lexception suivante : exception Rot_error;; Ecrivez une fonction rotation_droite : a ab -> a ab eectuant une rotation ` a droite de larborescence pass ee en argument. Ce type de rotation est illustr e sur la gure 9. Bien entendu, cette rotation na de sens que si larbre contient au moins les noeuds p et q , dans le cas contraire votre fonction l` evera donc lexception Rot error.
page 161
Fig. 9 Les rotations droite et gauche. Q 105.3 Ecrivez de m eme une fonction rotation_gauche : a ab -> a ab. une fonction hauteur : a ab -> int qui renvoie la hauteur dune Q 105.4 Ecrivez arborescence binaire (une arborescence vide aura pour hauteur 1 et une arborescence contenant un seul noeud une hauteur de 0). Ecrivez (ecacement) une fonction hauteur_sa : a noeud -> int * int * int qui, etant donn e une arborescence non vide, renvoie un triplet compos e de la hauteur de larborescence, de la hauteur de sa sous-arborescence gauche et de sa sous-arborescence droite. une fonction ins_avl : a -> a abr -> a abr r ealisant linserQ 105.5 Ecrivez tion dun el ement dans un arbre binaire de recherche AVL. On rappelle quil sagit dins erer l el ement dans larborescence en utilisant la fonction ins du TD 10, puis de r e equilibrer
page 162
larborescence. Pour cela, on applique lalgorithme suivant : Soient A larborescence apr` es insertion, et G et D ses sous-arborescences gauche et droite. Soit h() la fonction renvoyant la hauteur dune arborescence. Trois cas doivent etre consid er es : Si |h(G) h(D)| < 2 alors larborescence A est AVL. Si h(G) h(D) = 2 alors soient g et d les sous-arborescences gauche et droite de G. Si h(g ) < h(d) alors on eectue une rotation gauche de G. Dans tous les cas, on eectue une rotation droite de A. Si h(G) h(D) = 2 alors soient g et d les sous-arborescences gauche et droite de D. Si h(d) < h(g ) alors on eectue une rotation droite de D. Dans tous les cas, on eectue une rotation gauche de A.
page 163
8.5 Tas
Exercice 106 (Tas et Heapsort) Dans cet exercice, un tas (heap en anglais) est une arborescence binaire, construite sur un ensemble E muni dune relation dordre R, ayant les deux propri et es suivantes : 1. tous les niveaux sont enti` erement remplis ` a lexception, peut- etre, du dernier niveau, et ce dernier niveau est rempli ` a gauche . 2. pour tout noeud X et tout ls Y de X , on a X R Y . La propri et e num ero 1, qui nest pas requise habituellement, est impos ee ici an de pouvoir repr esenter les tas par des tableaux. Par exemple, la gure 10 est un tas pour la relation . Notez la di erence entre un tas et une arborescence binaire de recherche : dans un tas, on a X R Y pour tout descendant Y de X , alors que dans une arborescence binaire de recherche on a X R Y pour tout Y dans un sous-arbre droit de X et Y R X pour tout Y dans un sous-arbre gauche de X . En principe, on stocke les tas sous forme de tableaux, par exemple celui de la gure 10 peut etre repr esent e par : 16 14 10 8 7 9 3 2 4 1 Le tableau est rempli en balayant larborescence du haut vers le bas et de gauche ` a droite. Si la racine de larborescence est stock ee ` a lindex 0 du tableau, alors tout noeud dindex i
page 164
Fig. 10 Un tas pour la relation . du tableau a pour ls gauche le noeud dindex 2 i + 1 et pour ls droit le noeud dindex 1 2 i + 2. De m eme, tout noeud dindex i a pour parent le noeud dindex i 2 (si cette quantit e est positive ou nulle bien entendu). Dans cet exercice, on se propose de manipuler des tas dentiers munis de la relation en utilisant le type suivant : type heap = { mutable elts : int array; (* les noeuds du tas *) mutable nb_elts : int; (* nombre d el ements du tas *) };; Q 106.1 On dispose dune exception Heap error. D enissez les fonctions : left : heap -> int -> int qui, etant donn e un tas et un indice i dans le tableau du tas (on rappelle que la racine a pour indice 0), renvoie lindice du ls gauche du noeud dindice i si celui-ci existe et l` eve lexception Heap error sinon.
page 165
right : heap -> int -> int qui eectue la m eme op eration mais avec le ls droit. parent : heap -> int -> int qui est similaire mais renvoie lindice du parent si celui-ci existe. Q 106.2 (Propri et e du tas) Dans cette question, on consid` ere une arborescence binaire dont on sait que les sousarborescences droite et gauche de la racine sont des tas. On veut la transformer de mani` ere ` a ce quelle soit elle-m eme un tas. Si la racine, appelons la X , est sup erieure ` a ses enfants, alors on a bien un tas. Sinon, soit Y le plus grand de ses enfants. Echangeons X et Y . Dans ce cas, si la sous-arborescence de racine X est un tas, toute larborescence en est aussi un. Il sut donc de recommencer lop eration avec la sous-arborescence de racine X , et ainsi de suite jusqu` a ce que lon ait un tas ou que lon atteigne une feuille (une feuille etant bien evidemment un tas). Par exemple, si lon applique cet algorithme sur la sous-arborescence de racine 4 de la gure 11(a), on saper coit que cette derni` ere nest pas un tas puisque 4 est inf erieur ` a ses enfants. On echange donc 4 avec le plus grand de ses enfants (ici 14). On na toujours pas un tas puisque, maintenant, 4 a pour enfant 8. On echange donc 4 et 8. 4 est maintenant une feuille, on a bien un tas. Ecrivez une fonction heapify : heap -> int -> unit qui, etant donn e un tas et lindex dun noeud X , r ealise lalgorithme ci-dessus sur la sous-arborescence de racine X . Important pour la suite : utilisez les fonctions left et right mais surtout pas Array.length.
page 166
16 4 14 2 8 1 (a) change de 4 et 14 7 9 10 3
Fig. 11 Restauration de la propri et e de tas. Q 106.3 (cr eation du tas) Ecrivez une fonction build_heap : int array -> heap qui, etant donn e un tableau dentiers dont les el ements sont dans nimporte quel ordre, renvoie un tas constitu e de ces el ements. Pour cela, on remarquera que, si ce tableau repr esentait une arborescence binaire alors les feuilles seraient des tas. Pour transformer tout le tableau en tas, il sut donc de remonter des feuilles vers la racine et dappeler la fonction heapify sur tous les noeuds rencontr es (en fait, on peut remarquer quil sut dappliquer heapify sur tous les 1 el ements dindex n ` a 0, o` u n est le nombre d el ements du tableau). 2 Q 106.4 (heapsort) Le heapsort est un algorithme de tri classique. Imaginons que nous voulions trier un tableau par ordre croissant. Si lon a constitu e un tas ` a partir de ce tableau, alors la racine du tas est
page 167
le dernier el ement du tableau tri e. Appelons A le tableau du tas et n le nombre d el ements dans le tas. Echangeons le dernier el ement de A avec la racine X du tas et diminuons la valeur de n dune unit e. Dans ce cas, les n (nouvelle valeur) premiers el ements de A forment un nouvel arbre binaire qui ne contient plus X . Comme celui-ci nest plus forc ement un tas, on applique heapify sur cet arbre de mani` ere ` a obtenir ` a nouveau un tas et on peut recommencer lop eration. Lorsquil ne reste plus quun seul el ement dans le tas, le tableau A contient lensemble des el ements du tableau dorigine tri es par ordre croissant. D enissez la fonction heapsort : int array -> int array qui impl emente lalgorithme ci-dessus. Exercice 107 (Files avec priorit e) Dans cet exercice, on reprend la structure de tas vu ` a lexercice 106. On veut g erer une le avec priorit e (permettant par exemple de g erer di erents process travaillant en concurrence). Dans une telle le, on veut pouvoir ajouter des el ements ` a la le et extraire celui ayant la plus grande priorit e. Q 107.1 D enissez la fonction extract_max : heap -> int qui, etant donn e un tas, renvoie l el ement maximal de ce tas et le supprime du tas. Id ee : echanger la racine du tas avec le dernier el ement du tas. Si le tas est vide, la fonction doit lever lexception Heap error. Q 107.2 D enissez une fonction empty : unit -> heap qui renvoie un tas vide, puis
page 168
une fonction heap_insert : heap -> int -> unit qui rajoute lentier pass e en deuxi` eme argument, appelons-le X , au tas A pass e en premier. Pour cela, il sut de rajouter l el ement juste apr` es le dernier el ement du tas, cest-` a-dire que X devient maintenant une feuille de A. Si le parent de X est sup erieur ` a X , on a bien ` a nouveau un tas. Sinon, on echange X avec son parent et on recommence les echanges jusqu` a ce que lon soit remont e ` a la racine ou bien que X ait un parent sup erieur ` a lui. Si le tableau contenant A est d ej` a plein appelons n sa taille on cr ee un nouveau tableau de taille 2 n + 1, dont on copie dans les n premi` eres cases le tableau A et auquel on rajoute X .
page 169
9 Tables de hachage
Exercice 108 (Comparaison de di erents types de tables) On consid` ere lensemble de 13 mots dont les valeurs hach ees par une fonction de hachage f sont d ecrites ci-dessous : mot valeur hach ee (en hexad ecimal) 01 le FF2E 02 cours 178DD38 03 de 75EA33 04 types 35CE5 05 et 9AA8BF1 06 structures 2738 07 est A4C74 08 absolument 1CA4C74 09 g enial 14D26 10 jadore 5A38 11 faire 1BAE5 12 ses 65B4EE5 13 TD/TME 8C74 Pour chaque type de table de hachage ci-dessous, indiquez ce que lon obtiendrait si lon
page 170
9. Tables de hachage
partait dune table vide de taille 16 et que lon ins erait dans lordre tous les mots ci-dessus avec une fonction de hachage f (k ) = k mod 16. 1. Table de hachage avec r esolution des collision par cha nage, 2. Table de hachage avec adressage ouvert et probing lin eaire, 2 i + i2 . 3. Table de hachage avec adressage ouvert et probing quadratique h(k ) = f (k ) + 2 Pour les adressages ouverts, calculez le nombre de probes ` a eectuer en moyenne pour obtenir un el ement donn e dans la table. D eduisez-en le meilleur des deux probings. Exercice 109 (fonction de hachage) On consid` ere lensemble de couples (cl e,valeur) suivant : mot cl e (en d ecimal) 01 le 123 02 cours 22 03 de 88 04 types 33 05 et 4 06 structures 28 07 est 73 08 absolument 7 09 g enial 15
page 171
Q 109.1 Calculez les valeurs hach ees des cl es obtenues pour chaque couple par les fonctions ci-dessous : let f1 x = x ; ; let f2 x = 10 * x ; ; let f3 x = 2 * x ; ; let rec f4 x = if x = 0 then 0 else 8 * f4 (x / 10) + x mod 10 ; ; Q 109.2 Supposons que lon veuille ins erer les mots ci-dessus dans une table de hachage de longueur 10. On veut hacher les cl es des mots en utilisant la fonction f (x) = g (x) mod 10, o` u g {f1,f2,f3,f4}. Quelle est le meilleur choix pour g ? Expliquez pourquoi. Exercice 110 (Implantation) Dans cet exercice, on veut impl ementer une table de hachage avec r esolution des collisions par cha nage (listes cha n ees de couples (cl e,valeur)) et fonction de hachage multiplicative. Pour la suite de lexercice, on supposera que le tableau contenant les listes cha n ees d el ements a une taille correspondant ` a une puissance de 2 (ceci an dobtenir un algorithme rapide, comme nous lavons vu en cours). On d enit les types et exceptions suivants : type hash_func = int -> int;;
page 172
9. Tables de hachage
type a hash_table = { mutable size : int; (* taille de la table *) mutable hash : hash_func; (* fonction de hachage *) mutable tab : (int * a) list array (* tableau des listes cha^ n ees: int = cl e, a = valeur *) };; exception HashTableError of string;; (* message derreur *) On veut impl ementer une fonction de hachage h(k ) du type : h(k ) = M ((k A) mod 1), o` u M repr esente la taille de la table de hachage (une puissance de 2, M = 2m), A 0, 618 est le nombre dor, et (k A) mod 1 signie la partie d ecimale de (k A). Soit B un entier tel que A B 2n, pour un entier n > 0. Alors k A k B 2n. Il est facile de montrer que les n derniers bits de cette expression correspondent ` a la partie d ecimale de k A. Si ET repr esente un et logique , ((k B ) ET (2n 1)) 2n permet donc dobtenir la partie d ecimale de k A. Puisque h(k ) sobtient en multipliant cette partie d ecimale par M = 2m, h(k ) = ((k B )ET (2n 1)) 2mn.
page 173
En OCaml, le ET logique sappelle land. De plus, le calcul dune puissance de 2 peut etre eectu e par des d ecalages de bits gr ace aux fonctions lsl (d ecalage ` a gauche) et lsr (d ecalage ` a droite). Ainsi, 2k est egal ` a 1 lsl k pour k positif. Dans la suite, on supposera que n = 15 (donc 2n 1 = 32767) et que m < n. Pour n = 15, B = 20252. De plus, 2mn sobtient en eectuant n m d ecalages vers la droite (lsr). Q 110.1 Ecrivez une fonction make_hash_func : int -> int -> int telle que make hash func m renvoie la fonction h() pour une table de hachage de longueur m. Vous v erierez que m < n et que m > 2. Dans le cas contraire, vous l` everez une exception HashTableError. Indice : si vous avez obtenu la bonne fonction h(), pour m = 10, vous devriez avoir : h(1) = 632 h(2) = 241 h(10) = 184 h(100) = 823 h(531) = 184 h(1573) = 184 h(1052) = 184. Q 110.2 Ecrivez une fonction log_size : int -> int telle que log size size renvoie le nombre de bits n ecessaires pour stocker lentier size. Ainsi log size 1024 ou log size 1000 renverraient 10. une fonction make hash table : int -> a hash_table telle que Q 110.3 Ecrivez make hash table size renvoie une table de hachage vide de taille M , la plus petite puissance de 2 sup erieure ou egale ` a size.
page 174
9. Tables de hachage
une fonction find_elt : a hash_table -> int -> a telle que Q 110.4 Ecrivez find elt table k renvoie la valeur de l el ement de cl e k si celui-ci existe et l` eve une exception Not found sinon. Vous supposerez quil y a au plus un el ement par cl e. une fonction insert : a hash_table -> int -> a -> unit Q 110.5 Ecrivez telle que insert table k v rajoute l el ement de cl e k et de valeur v ` a la table de hachage pass ee en premier argument si la cl e k nexiste pas d ej` a dans la table, et l` eve une exception HashTableError sinon. Q 110.6 Ecrivez une fonction display_float_table : float hash_table -> unit prenant en argument une table de hachage dont les valeurs sont des float et achant le contenu de celle-ci. Par exemple, une table contenant les couples (1052,5.5), (1573,2.5), (531,3.5) acherait la cha ne de caract` eres : [ (1052,2.500000) (1573,2.500000) (531,2.500000) ]. Q 110.7 Ecrivez une fonction delete : a hash_table -> int -> unit telle que delete table k supprime l el ement de cl e k si celui-ci existe et l` eve une exception HashTableError sinon. Exercice 111 (Dictionnaire) Dans cet exercice, on se propose de comparer la gestion dun dictionnaire par liste cha n ee et par table de hachage. Le but est de voir ` a quel point lutilisation dune table de hachage acc el` ere les recherches dans le dictionnaire. Ceci justie lemploi des tables dans des logiciels
page 175
tels que les compilateurs. Pour cet exercice, on se dote dune exception Dico_error. Q 111.1 Ecrivez une fonction create_dico_list : int -> (int * string) list de telle sorte que create dico list m renvoie une liste dassociations contenant des couples (nombre sous forme dentier, nombre sous forme de cha ne de caract` ere), pour tous les nombres de 0 ` a m. Lordre de ces couples dans la liste na aucune importance. Ecrivez de m eme une fonction create_dico_hash : int -> string hash_table de ee une table de hachage de taille m (cf. lexercice telle sorte que create dico hash m cr pr ec edent) et la remplit avec des cha nes de caract` eres correspondant ` a tous les nombres de 0 ` a m. Les cl es de ces cha nes sont les nombres eux-m emes. Q 111.2 Ecrivez une fonction get_element_list : (a * b) list -> a -> b de telle sorte que get element list liste nb renvoie la cha ne de caract` eres correspondant au nombre nb si celle-ci appartient ` a liste, et l` eve une exception Dico error sinon. De m eme, ecrivez une fonction get_element_hash : a hash_table -> int -> a r ealisant la m eme op eration dans une table de hachage. Q 111.3 On veut maintenant comparer la vitesse de recherche dinformations dans une liste et dans une table de hachage. Pour cela, vous allez utiliser la fonction gettimeofday () qui renvoie le nombre de secondes ecoul ees depuis le 1er janvier 1970. Cette fonction n ecessite le chargement du module Unix : #load "unix.cma";; open Unix;;
page 176
9. Tables de hachage
Ecrivez une fonction time_search_list : int -> float telle que time search list m cr ee une liste de couples de taille m en utilisant la fonction create dico list et renvoie le temps pass e` a rechercher les cha nes correspondant ` a m nombres tir es au hasard entre 0 et m (utilisez la fonction int du module Random ` a cet eet). Faites de m eme avec la fonction time_search_hash : int -> float pour les tables de hachage. Comparez les temps obtenus et exclamez-vous y a pas photo ! .