Correction Code nécessaire à la compilation : let bs ="\\" let nl = "\n" ;; let appliquer = List.map ;; (* affichage d'un noeud *)



Documents pareils
Problème : Calcul d'échéanciers de prêt bancaire (15 pt)

Recherche dans un tableau

chapitre 4 Nombres de Catalan

# let rec concat l1 l2 = match l1 with [] -> l2 x::l 1 -> x::(concat l 1 l2);; val concat : a list -> a list -> a list = <fun>

Vers l'ordinateur quantique

length : A N add : Z Z Z (n 1, n 2 ) n 1 + n 2

Cours 1 : La compilation

Feuille TD n 1 Exercices d algorithmique éléments de correction

Projet d informatique M1BI : Compression et décompression de texte. 1 Généralités sur la compression/décompression de texte

Plan. Exemple: Application bancaire. Introduction. OCL Object Constraint Language Le langage de contraintes d'uml

Les structures de données. Rajae El Ouazzani

Date : Tangram en carré page

Arbres binaires de recherche

Algorithmes d'apprentissage

Travaux pratiques. Compression en codage de Huffman Organisation d un projet de programmation

Représentation d un entier en base b

Pour signifier qu'une classe fille hérite d'une classe mère, on utilise le mot clé extends class fille extends mère

Rappel. Analyse de Données Structurées - Cours 12. Un langage avec des déclaration locales. Exemple d'un programme

Présentation du langage et premières fonctions

TP n 2 Concepts de la programmation Objets Master 1 mention IL, semestre 2 Le type Abstrait Pile

BACCALAUREAT GENERAL MATHÉMATIQUES

Initiation à l algorithmique

INF 232: Langages et Automates. Travaux Dirigés. Université Joseph Fourier, Université Grenoble 1 Licence Sciences et Technologies

Raisonnement par récurrence Suites numériques

INF601 : Algorithme et Structure de données

t 100. = 8 ; le pourcentage de réduction est : 8 % 1 t Le pourcentage d'évolution (appelé aussi taux d'évolution) est le nombre :

"! "#$ $ $ ""! %#& """! '& ( ")! )*+

Algorithmes de recherche

Application 1- VBA : Test de comportements d'investissements

I. Introduction aux fonctions : les fonctions standards

Plan du cours : Zippers. Des fonctions sur les listes avec position. Des fonctions sur les listes avec position

Algorithmique et Programmation, IMA

1. Structure d'un programme FORTRAN 95

PROBLEMES D'ORDONNANCEMENT AVEC RESSOURCES

RapidMiner. Data Mining. 1 Introduction. 2 Prise en main. Master Maths Finances 2010/ Présentation. 1.2 Ressources

Conception de circuits numériques et architecture des ordinateurs

V- Manipulations de nombres en binaire

Initiation à la programmation en Python

Chapitre 11. Séries de Fourier. Nous supposons connues les formules donnant les coefficients de Fourier d une fonction 2 - périodique :

Chap 4: Analyse syntaxique. Prof. M.D. RAHMANI Compilation SMI- S5 2013/14 1

Les arbres binaires de recherche

Cours d initiation à la programmation en C++ Johann Cuenin

Peut-on tout programmer?

«Aucune investigation humaine ne peut être qualifiée de science véritable si elle ne peut être démontrée mathématiquement.

Exo7. Calculs de déterminants. Fiche corrigée par Arnaud Bodin. Exercice 1 Calculer les déterminants des matrices suivantes : Exercice 2.

Compléments de documentation Scilab : affichage de texte et formatage de nombres

Prénom : Matricule : Sigle et titre du cours Groupe Trimestre INF1101 Algorithmes et structures de données Tous H2004. Loc Jeudi 29/4/2004

Couples de variables aléatoires discrètes

Programmation C++ (débutant)/instructions for, while et do...while

Complexité. Licence Informatique - Semestre 2 - Algorithmique et Programmation

Éléments d informatique Cours 3 La programmation structurée en langage C L instruction de contrôle if

CH.6 Propriétés des langages non contextuels

3. SPÉCIFICATIONS DU LOGICIEL. de l'expression des besoins à la conception. Spécifications fonctionnelles Analyse fonctionnelle et méthodes

Chapitre 4 Pierre, papier, ciseaux

Analyse tarifaire en ligne (TAO) de l'omc

Corrigé des TD 1 à 5

Découverte du tableur CellSheet

Vérification de programmes et de preuves Première partie. décrire des algorithmes

Resolution limit in community detection

Manuel M O D U L E D I M P O R T A T I O N

MODE D'EMPLOI DE LA CALCULATRICE POUR LES COURTS SÉJOURS DANS L'ESPACE SCHENGEN

Licence Bio Informatique Année Premiers pas. Exercice 1 Hello World parce qu il faut bien commencer par quelque chose...

INITIATION AU LANGAGE C SUR PIC DE MICROSHIP

SOMMAIRE. Travailler avec les requêtes... 3

Exercices du Cours de la programmation linéaire donné par le Dr. Ali DERBALA

Plus courts chemins, programmation dynamique

TP3 : Manipulation et implantation de systèmes de fichiers 1

INSERER DES OBJETS - LE RUBAN INSERTION... 3 TABLEAUX

2. RAPPEL DES TECHNIQUES DE CALCUL DANS R

Année Universitaire 2009/2010 Session 2 de Printemps

MIS 102 Initiation à l Informatique

L'instruction if permet d'exécuter des instructions différentes selon qu'une condition est vraie ou fausse. Sa forme de base est la suivante:

LE PROBLEME DU PLUS COURT CHEMIN

Ordonnancement. N: nains de jardin. X: peinture extérieure. E: électricité T: toit. M: murs. F: fondations CHAPTER 1

1 Définition et Appel d une fonction. V. Phan Luong. Cours 4 : Fonctions

Traitement de texte : Quelques rappels de quelques notions de base

Cours Informatique Master STEP

EXCEL PERFECTIONNEMENT SERVICE INFORMATIQUE. Version /11/05

Cours de Programmation 2

Suivant les langages de programmation, modules plus avancés : modules imbriqués modules paramétrés par des modules (foncteurs)

LibreOffice Calc : introduction aux tableaux croisés dynamiques

Centre CPGE TSI - Safi 2010/2011. Algorithmique et programmation :

Formats d images. 1 Introduction

Université Paris-Dauphine DUMI2E 1ère année, Applications

Simulation de variables aléatoires

Manuel Utilisateur. Module CAISSE

Durée de L épreuve : 2 heures. Barème : Exercice n 4 : 1 ) 1 point 2 ) 2 points 3 ) 1 point

Logique binaire. Aujourd'hui, l'algèbre de Boole trouve de nombreuses applications en informatique et dans la conception des circuits électroniques.

Seconde et première Exercices de révision sur les probabilités Corrigé

modules & compilation

Gestion mémoire et Représentation intermédiaire

Les chaînes de caractères

Chapitre 10. Les interfaces Comparable et Comparator 1

Solutions du chapitre 4

Géométrie dans l espace Produit scalaire et équations

Définitions. Numéro à préciser. (Durée : )

Système binaire. Algèbre booléenne

Axiomatique de N, construction de Z

Introduction. I Étude rapide du réseau - Apprentissage. II Application à la reconnaissance des notes.

Chapitre 7. Récurrences

Transcription:

Correction Code nécessaire à la compilation : let bs ="\\" let nl = "\n" let appliquer = List.map (* affichage d'un noeud *) let (noeud_vers_ch : int -> string) = function n -> "fib(" ^ (string_of_int n) ^ ")" Étude expérimentale de la complexité de la fonction de Fibonacci (24 pt) L'objectif de ce problème est d'étudier le nombre d'appels récursifs eectués lors du calcul des nombres de Fibonacci. C'est un exemple classique qui montre qu'une fonction mal écrite peu engendrer un nombre gigantesque d'appels récursifs inutiles. Pour le voir, nous allons demander à la fonction de Fibonacci de construire l'arbre de ses appels récursifs. Dans la seconde partie du problème nous acherons cet arbre et dans la troisième partie nous écrirons une version plus ecace de la fonction de Fibonacci. Première partie du problème (8 pt) 1 Commençons par dénir la fonction de Fibonacci Q1. (1 pt) Donnez la réalisation de la fonction b qui prend en paramètre un entier n et retourne le n ieme nombre de Fibonacci. Prol b : N N Sémantique : b(n) est le n ieme terme de la suite de Fibonacci (u n ) n N dénie par u 0 = 1 u 1 = 1 u n = u n 1 + u n 2 Dénition récursive de la fonction par des équations (1) b( 0 ) = 1 (2) b( 1 ) = 1 (3) b( n ) = b(n 1) + b(n 2) pour n 2

Correction let rec (fib : int -> int) = function 0 -> 1 1 -> 1 n -> fib(n-1) + fib(n-2) Q2. (1 pt) Rédigez la preuve de terminaison de la fonction b. TERMINAISON preuve : (i) On dénit la fonction Mesure ( n ) def = n Justions que la mesure choisie retourne des valeurs dans N: n N (ii) Montrons que la mesure décroit strictement à chaque appel récursif. Pour (ii), on repère les équations qui comportent des appels récursifs et on prouve la décroissance de la mesure pour chaque appel récursif. Rédigez la preuve de terminaison ici (2) b(n) appelle b(n 1) Mesure (n) = n? < Mesure (n 1) ok < = n 1 (2) b(n) appelle aussi b(n 2) Mesure (n) = n? < Mesure (n 2) ok < = n 2 Q3. (.75 pt) Indiquez les appels récursifs engendrés par b(4) sous la forme d'un arbre. Utilisez l'espace libre pour prolonger les branches de l'arbre si nécessaire. b(5) appelle appelle b(4) b(3) appelle appelle appelle appelle b(3) b(2) b(2) b(1)

2 Dénition de l'arbre des appels récursifs Les appels récursifs engendrés par b(x) pour x 2 seront représentés sous la forme d'un arbre ar(ag, x, ad) où ar signigie Appel Récursif le n ud x indique qu'il s'agit du calcul de b(x) et qu'il a nécessité les appels récursifs rangés dans les arbres ag et ad ag est l'arbre des appels récursifs engendrés par b( x 1 ) ad est l'arbre des appels récursifs engendrés par b( x 2 ) Q4. (0.5 pt) Complétez les remarques précédentes et suivantes, ainsi que la dénition du type Abar (Arbre Binaire d'appels Récursifs). L'arbre des appels récursifs de la fonction de Fibonacci est un arbre binaire puisque la fonction fait deux appels récursifs. Lorsque le calcul de b(x) n'engendre pas d'appel récursif son arbre d'appel est représenté par rd(x) où rd signie Résultat Direct et x indique qu'il s'agit du calcul de b(x). Q5. (1 pt) Donnez la représentation à l'aide des constructeurs rd et ar de l'arbre d'appels de b(0) : rd(0) l'arbre d'appels de b(2) : ar( 2, rd(0) ) puis complétez la dénition de Abar. rd(1), DÉFINITION MATHÉMATIQUE D'UN ENSEMBLE déf Abar = { av(x) x {0, 1} } { ar(ag, x, ad) x N, ag, ad Abar } DÉFINITION INFORMATIQUE D'UN TYPE type nat = int (* >=0 *) type abar = Av RD of nat AR of abar * nat * abar Q6. (1.5 pt) Complétez la dénition de la fonction calcul-de-b qui calcule le terme de la suite de Fibonacci et construit simultanément l'arbre des appels récursifs de la fonction b. Prol calcul-de-b : N N Abar Sémantique : calcul-de-b(n) est un couple constitué du n ieme nombre de Fibonacci et de l'arbre des appels récursifs engendrés par le calcul de u n. Exemples 1. calcul-de-b(0) = ( (1, rd(0) ) 2. calcul-de-b(1) = ( (1, rd(1) )

3. calcul-de-b(2) = ( 2, ar(rd(1), 2, rd(0)) ) let rec (calcul_de_fib : int -> int * abar) = function 0 -> (1, RD(0) ) 1 -> (1, RD(1)) n -> let (r1,a1) = calcul_de_fib(n-1) and (r2,a2) = calcul_de_fib(n-2) in (r1+r2, AR(a1, n, a2) ) 3 Étude de l'arbre des appels récursifs On dispose maintenant d'une fonction calcul-de-b qui construit l'arbre d'appels récursifs de b. On aimerait par exemple compter le nombre de fois où le calcul de b(x) a demandé de calculer b(k). Pour cela on a besoin de compter le nombre d'apparitions d'un n ud dans un Abar. Q7. (1.5 pt) Complétez la fonction nb-occ qui compte le nombre d'apparitions du n ud k dans un Abar. Prol nb-occ : Z Abar N Sémantique : nb-occ(k, a) est le nombre d'occurences du n ud k dans l'arbre d'appel a Dénition récursive de la fonction par des équations (1) nb-occ( k, rd(n) ) = 0 si n k (1 ) nb-occ( k, rd(n) ) = 1 si n = k (2) nb-occ( k, ar(ag, n, ad) ) = nb-occ(k, ag) + nb-occ(k, ad) si n k (2 ) nb-occ( k, ar(ag, n, ad) ) = 1 + nb-occ(k, ag) + nb-occ(k, ad) si n = k bonus de 0.25 pour la factorisation du if ou pour une solution qui rend 1 sans appel récursif dans le cas AR(ag,n,ad) où n=k let rec (nb_occ : int * abar -> nat) = function (k,a) -> match a with Av -> 0 RD(n) -> if n=k then 1 else 0 AR(ag,n,ad) ->

(if n=k then 1 else 0) + nb_occ (k,ag) + nb_occ (k,ad)

Q8. (0.75 pt) a) À l'aide des fonctions calcul-de-b et nb-occ, donnez l'expression Ocaml qui permet de connaître le nombre de fois qu'est demandé le calcul de b(1) dans le calcul de b(121). let (_,a) = calcul_de_fib(121) in nb_occ(1,a) Le tableau suivant donne en fonction de n le nombre d'appels à b(1) dans le calcul de b(n). b) Complétez les premières cases du tableau nombre d'appels à b(1) dans le calcul de b(n) n 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 n 15 20 21 22 23 24 25 26 27 nombre d'appels à b(1) dans le calcul de b(n) 610 6765 10946 17711 28657 46368 75025 121393 196418

Seconde partie du problème (12 pt) 4 Achage de l'arbre des appels récursifs L'objectif de cette partie est de réaliser une fonction d'achage d'un arbre d'appel sous la forme suivante, avec les valeurs des appels à la place des (-). Notre objectif est d'acher un arbre fib(_) / \ fib(_) fib(_) / \ / \ fib(_) fib(_) fib(_) fib(_) / \ / \ / \ fib(_) fib(_) fib(_) fib(_) fib(_) fib(_) / \ fib(_) fib(_) ar(ag, n, ad) sous la forme fib(n) / \ ag ad et d'appliquer le même principe au sous-arbre gauche ag et au sous-arbre droit ad. Pour obtenir ce résultat nous devrons 1. transformer le sous-arbre ag en colonne de ligne colg 2. placer le symbole / centré au dessus de cette colonne colg 3. transformer le sous-arbre ad en colonne de ligne cold 4. placer le symbole \ centré au dessus de cette colonne cold 5. coller les colonnes obtenues aux étapes 2 et 4 (opération notée sur le schéma) 6. placer le titre fib(n) centré au dessous des deux colonnes collées an d'obtenir la colonne correspondant à l'arbre ar(ag, n, ad). Le principe de transformation d'un arbre en colonne est résumé par le schéma ci-après : (les êches indiquent que le titre doit être centré). "fib(n)" "/" sous arbre gauche } {{ } colg "\" sous arbre droit } {{ } cold Pour mettre en uvre ce principe nous allons dénir un type Colonne et des opérations de manipulations des colonnes. On décide représenter une colonne de ligne

"abcdefgh" "ijklmnop" "qrstuvwx" "yz" par une séquence de chaîne de caractère [ "abcdefgh" ; "ijklmnop" ; "qrstuvwx" ; "yz" ] Q9. (0.5 pt) Complétez la dénition du type Colonne. DÉFINITION MATHÉMATIQUE D'UN ENSEMBLE déf Colonne = Séq (Chaîne) DÉFINITION INFORMATIQUE D'UN TYPE type colonne = string list et indiquez l'opérateur qui permet d'ajouter une ligne au dessus d'une colonne :: Justiez votre réponse : ajouter une ligne en haut d'une colonne c'est ajouter une chaîne de caractère à gauche d'une séquence Q10. (1 pt) Utilisez l'opérateur Ocaml ( ˆ ) : Chaîne Chaîne Chaîne pour réaliser la fonction espace spéciée ainsi : Prol espace : Z Chaîne Sémantique : espace(n) est la chaînes de caractère consitutée de n espaces. Propriété n 0, espace(n) = "" Correction Dénition récursive de la fonction par des équations (1) espace( n ) = "" si n 0 (2) espace( n ) = " " ˆ espace(n 1) si n > 0 let rec (espace : int -> string) = function n -> if (n<=0) then "" else " " ^ (espace (n-1)) Q11. (1 pt) Utilisez la fonction length prédénie en Ocaml pour réaliser la fonction largeur. Prol length : Chaîne Séq (Élt) N Sémantique : length(ch) est la longueur de la chaîne ch, c'est-à-dire le nombre de caractères qu'elle contient. Notez que la fonction length s'applique aussi bien aux chaînes de caractère qu'aux séquences.

Prol largeur : Colonne N Sémantique : largeur(col) est la largeur de la colonne. Précisons que les lignes de la colonne n'ont pas nécessairement la même longueur. Algorithme : La largeur d'une colonne est la longueur de sa ligne la plus longue. Dénition récursive de la fonction par des équations (1) largeur( [ ] ) = 0 (2) largeur( ch :: s ) = max(length(ch), largeur(s)) ou bien length(ch) si length(ch) > largeur(s) largeur(s) sinon Correction let rec (largeur : colonne -> int) = function [] -> 0 ch::s -> max (String.length ch) (largeur s) Q12. (1 pt) Complétez la réalisation de la fonction titrer qui permet de placer un titre centré au sommet d'une colonne. Prol titrer : Chaîne Colonne Colonne Sémantique : titrer(titre, col) place le titre centré au haut de la colonne. Exemple titrer "titre", "abcdefghijklmnopqrs" "abcdefghijklmnopqrs" "abcdefghijklmnopqrs" "abcdef" = " titre" "abcdefghijklmnopqrs" "abcdefghijklmnopqrs" "abcdefghijklmnopqrs" "abcdef" Algorithme : Notons lc la largeur de la colonne et lt la taille du titre alors le nombre ne d'espaces qu'on doit ajouter à gauche du titre est : ne = lc lt 2 let (titrer : string * colonne -> colonne) = function (titre,col) -> let lc = largeur col in let lt = String.length titre in let ne = (lc - lt)/2 in ((espace ne) ^ titre) :: col

Q13. (0.5 pt) Donnez la réalisation en Ocaml de la fonction compléter-chaine. Prol compléter-chaine : N Chaîne Chaîne Sémantique : compléter-chaine(l, ch) est une chaîne de caractère de taille l constituée de ch suivie d'espaces Exemples 1. compléter-chaine(5, "ab") = "ab " 2. compléter-chaine(5, "abcde") = "abcde" 3. compléter-chaine(5, "") = " " let (completer_chaine : nat * string -> string) = function (larg,ch) -> let lch = (String.length ch) in ch ^ (espace (larg-lch)) Q14. (1 pt) Complétez la spécication de la fonction appliquer. Prol appliquer : (T 1 T 2 ) Séq (T 1 ) Séq ( T 2 ) Sémantique : appliquer f [e 1 ; e 2 ;... ; e n ] = [f(e 1 ) ; f(e 2 ) ;... ; f(e n )] Exemples On rappelle que (f unction x e) est une fonction qui à x associe la valeur de l'expression e. 1. appliquer (function x 2 x + 1) [0; 1; 2; 3] = [1 ; 3 ; 5 ; 7] 2. appliquer (f unction x (x, x x) ) [0; 3; 2; 5; 1] = [ (0, 0) ; (3, 9) ; (2, 4) ; (5, 25) ; (1, 1) ] 3. appliquer (f unction (x, y) y) [ (0, 0); (3, 9), (2, 4); (5, 25); (1, 1) ] = [0; 9; 4; 25; 1] Ajuster une colonne en ajoutant des espaces en n de lignes On appelle colonne ajustée une colonne dont toutes les lignes ont la même taille. On dénit ColonneAjustée comme l'ensemble des couples constitués d'une colonne et de sa largeur.

Q15. (0.25 pt) Complétez la déntion de type. DÉFINITION MATHÉMATIQUE D'UN ENSEMBLE déf ColonneAjustée = Colonne N DÉFINITION INFORMATIQUE D'UN TYPE type colonne_ajustée = colonne * nat Q16. (1.25 pt) Utilisez les fonctions appliquer et compléter-chaine pour réaliser en Ocaml la fonction ajuster-colonne qui complète les lignes d'une colonne par des espaces en n de ligne an que toutes les lignes aient la même taille. Prol ajuster-colonne : Colonne ColonneAjustée Sémantique : ajuster-colonne(col) est la colonne ajustée correspondant à col Exemple ajuster-colonne "abcdef" "abc" "abcdefgh" = "abcdef " "abc " "abcdefgh", 8 "a" "a " Algorithme : On rappelle qu'une colonne est une séquence de chaîne de caractère et qu'on peut donc utiliser la fonction appliquer avec les colonnes. let (ajuster_colonne : colonne -> colonne_ajustée) = function col -> let l = largeur col in let colaj = appliquer (fun ch -> completer_chaine (l,ch)) col in (colaj, l) Q17. (1.5 pt) Complétez la réalisation de la fonction coller qui prend en paramètre deux colonnes déjà ajustées et qui les colle ligne à ligne. Vous pouvez évidemment utiliser des fonctions écrites précédemment. Prol coller : ColonneAjustée ColonneAjustée Colonne Sémantique : coller(caj 1, caj 2 ) est la colonne ajustée obtenue en collant ligne par ligne la colonne ajustée caj 1 à la colonne ajustée caj 2. Précisons que les colonnes sont ajustées, par contre elles n'ont pas nécessairement le même nombre de ligne.

Exemples Vous remarquerez dans les exemples que les deux colonnes doivent être séparées par un espace. 1. coller 2. coller (( "abcdef" "abcdef" "ab " ( ( "abcdef" "ab ", 6 ), ( ) (, 6, "gh " "ghij" "ghi " "ligne 1" "ligne 2" "ligne 3", 4 )), 7 )) = "abcdef gh " "abcdef ghij" "ab ghi " = "abcdef ligne 1" "ab ligne 2" " ligne 3" Dénition récursive de la fonction par des équations (1) coller( ( [ ], l 1 ), ( [ ], l 2 ) ) = [ ] (2) coller( (ch 1 :: s 1, l 1 ), (ch 2 :: s 2, l 2 ) ) = (ch 1 ˆ " " ˆ ch 2 ) :: coller((s 1, l 1 ), (s 2, l 2 )) (3) coller( ([ ], l 1 ), (ch 2 :: s 2, l 2 ) ) = (espace(l 1 ) ˆ " " ˆ ch 2 ) :: coller(([ ], l 1 ), (s 2, l 2 )) (4) coller( (ch 1 :: s 1, l 1 ), (ch 2 :: s 2, l 2 ) ) = (ch 1 ˆ " " ˆ espace(l 2 )) :: coller((s 1, l 1 ), ([ ], l 2 )) Correction let rec (coller : colonne_ajustée * colonne_ajustée -> colonne) = function ((col1,l1),(col2,l2)) -> match (col1,col2) with ([],[]) -> [] (ch1::s1, ch2::s2) -> (ch1 ^ " " ^ ch2) :: (coller ((s1,l1),(s2,l2))) ([],ch2::s2) -> ((espace l1) ^ " " ^ ch2) :: (coller (([],l1),(s2,l2))) (ch1::s1,[]) -> (ch1 ^ " " ^ (espace l2)) :: (coller ((s1,l1),([],l2))) Q18. (0.5 pt) Complétez la réalisation Ocaml de la fonction coller-colonne. Prol coller-colonne : Colonne Colonne Colonne Sémantique : coller-colonne(col 1, col 2 ) est la colonne obtenue en collant les colonnes col 1 et col 2 après ajustement. Exemple coller-colonne ( "abcdef" "ab ", "ligne 1" "ligne 2" "ligne 3" ) = "abcdef ligne 1" "ab ligne 2" " ligne 3"

let (coller_colonne : colonne * colonne -> colonne) = function (col1,col2) -> coller (ajuster_colonne col1, ajuster_colonne col2) On dispose maintenant de toutes les fonctions nécessaires pour réaliser la fonction arbre-vers-colonne qui applique le principe présenté en Section?? pour transformer un arbre d'appel en colonne. Q19. (1.5 pt) Utilisez les fonctions des questions précédentes pour réaliser la fonction arbre-vers-colonne. Prol arbre-vers-colonne : Abar Colonne Sémantique : arbre-vers-colonne(a) est la colonne correspondant à l'arbre a construite selon le principe de la Section??. Dénition récursive de la fonction par des équations (1) arbre-vers-colonne( rd(n) ) = [titre] où titre = "fib(" ˆ string-of-int(n) ˆ ")" (2) arbre-vers-colonne( ar(ag, n, ad) ) = titrer( titre, coller-colonne(colg, cold) ) où colg = titrer( "/", arbre-vers-colonne(ag) ) où cold = titrer( "\\", arbre-vers-colonne(ag) ) où titre = "fib(" ˆ string-of-int(n) ˆ ")" Correction let rec (arbre_vers_colonne : abar -> colonne) = function RD(n) -> [ noeud_vers_ch n ] AR(ag,n,ad) -> let colg = arbre_vers_colonne ag in let cold = arbre_vers_colonne ad in let colgt = titrer ("/",colg) in let coldt = titrer (bs,cold) in let colgd = coller_colonne (colgt, coldt) in titrer (noeud_vers_ch n, colgd) Q20. (0.75 pt) Complétez la réalisation Ocaml de la fonction colonne-vers-chaîne.

Prol colonne-vers-chaîne : Colonne Chaîne Sémantique : colonne-vers-chaîne(col) est la chaîne de caractère construite par concaténation des lignes de la colonne en introduisant un saut de ligne entre les lignes. Algorithme : On obtient un saut de lignes en ajoutant le caractère \n en n de ligne. let rec (colonne_vers_chaine : colonne -> string) = function [] -> "" ch::s -> ch ^ nl ^ (colonne_vers_chaine s) Q21. (1 pt) Dénissez une fonction qui transforme un arbre en chaîne de caractère et donnez ensuite l'expression Ocaml qui permet d'acher à l'écran la chaîne de caractère qui correspond à l'arbre des appels de b(121). Prol arbre-vers-chaîne : Abar Chaîne Sémantique : arbre-vers-chaîne(a) est la chaînes de caractère correspondant à la mise en colonne de l'arbre a let rec (arbre_vers_chaine : abar -> string) = function a -> colonne_vers_chaine (arbre_vers_colonne a) (* let (r,a) = calcul_de_fib(121) in print_string (arbre_vers_chaine(a)) *)

Troisième partie du problème (4 pt) 5 Compter les appels engendrés par b(n) sans construire l'arbre d'appels L'arbre des appels est très utile pour comprendre comment se déroule l'évaluation de la fonction b ; en revanche il n'est pas nécessaire si on souhaite juste compter le nombre total d'appels récursifs engendrés par b(n). Pour eectuer ce décompte nous allons dénir la fonction nb-total-appel-de-b. Q22. (1.5 pt) Complétez la dénition de la fonction nb-total-appel-de-b. Prol nb-total-appel-de-b : N N N Sémantique : nb-total-appel-de-b(n) = (u n, nb) où u n est le n ieme terme de la suite de Fibonacci et nb le nombre total d'appels engendrés par l'appel à b(n) Dénition récursive de la fonction par des équations (1) nb-total-appel-de-b( 0 ) = (1, 1) (2) nb-total-appel-de-b( 0 ) = (1, 1) (3) nb-total-appel-de-b( 0 ) = (u n 1 + u n 2, nb 1 + nb 2 ) si où (u n 1, nb 1 ) = nb-total-appel-de-b(n 1) où (u n 2, nb 2 ) = nb-total-appel-de-b(n 2) n 2 Correction let rec (nb_appel_de_fib : nat -> nat * nat) = function 0 -> (1,1) 1 -> (1,1) n -> let (u_n_1, nb1) = nb_appel_de_fib(n-1) in let (u_n_2, nb2) = nb_appel_de_fib(n-2) in (u_n_2 + u_n_1, nb1 + nb_2) Coïncidence : D'après les équations récursives que pouvez-vous dire du nombre d'appels qu'engendre l'appel b(n)? Justiez votre réponse : C'est exactement le nombre de Fibonnacci puisque la fonction nb-total-appel-de-b retourne un couple dont les deux membres sont égaux d'après les équations). 6 Une version plus ecace de Fibonacci Q23. (2.5 pt) Complétez la dénition de la fonction b2 qui calcule les termes de la suite de Fibonacci sans faire de double appel récursif et montrez la terminaison de la fonction b2.

Prol b2 : N N N Sémantique : b2(n) = (u n, u n+1 ) où u n et u n+1 sont les n ieme et n + 1 ieme termes de la suite de Fibonacci. Dénition récursive de la fonction par des équations (1) b2(0) = (1, 1) (2) b2(n) = (u n, u n + u n 1 ) où (u n 1, u n ) = b2(n 1) let rec (fib2 : int -> int * int) = function 0 -> (1,1) n -> let (u_n_1,u_n) = fib2(n-1) in (u_n, u_n + u_n_1) TERMINAISON On dénit la fonction Mesure ( n ) def = n preuve : (i) Justions que la mesure choisie retourne des valeurs dans N: n N (ii) Montrons que la mesure décroit strictement à chaque appel récursif. Pour (ii), on repère les équations qui comportent des appels récursifs et on prouve la décroissance de la mesure pour chaque appel récursif. (2) f ib2(n) appelle f ib2(n 1) Mesure (n) = n? < Mesure (n 1) ok < = n 1