Univ. Lille1 - Licence Informatique 2ème année 2013-2014 Algorithmes et Programmation Impérative 2 Récursivité 1 Exercices 1.1 Généralités sur les algorithmes récursifs Exercice 2-1 Que calcule fact ? Question 1 Voici quelques lignes de code : let fact n = 1 let fact n = if n = 0 then 1 else n * (fact (n - 1)) Quelle est la valeur de fact 10 ? Plus généralement de fact n où n désigne un entier quelconque ? Question 2 Voici maintenant une autre déclaration de la fonction fact : let rec fact n = if n = 0 then 1 else n * fact n - 1 Que donne le calcule de fact 1 ? Exercice 2-2 Que calculent les fonctions pair et impair ? Voici la déclaration en Caml de deux fonctions : let rec pair n = if n = 0 then true else not (impair n) and impair n = if n = 0 then false else not (pair n) Question 1 Que pensez-vous des expressions calculées par chacune des deux fonctions dans les deux cas de base et récursif ? Question 2 Tracez le calcul de l'expression pair 1. Exercice 2-3 Encore la fonction pair Voici la déclaration en Caml de la fonction pair : let rec pair n = if n = 0 then true else pair (n - 2) 1 Que pensez-vous de cette fonction ? Exercice 2-4 La fonction de Mc Carthy Voici la déclaration en Caml d'une fonction récursive : let rec mccarthy n = if n > 100 then n - 10 else mccarthy (mccarthy (n + 11)) Question 1 Si n est un entier strictement supérieur à 100, quelle est la valeur de mccarthy n ? Question 2 Et pour 90 ≤ n ≤ 100 ? Question 3 Et pour n ≤ 100 quelconque ? 1.2 Algorithmes récursifs sur les nombres Exercice 2-5 Somme de deux entiers Question 1 Proposez un algorithme récursif de calcul de la somme de deux entiers naturels a et b en supposant que les seules opérations de base dont vous disposez sont l'ajout de 1 à un entier a : a + 1 le retrait de 1 à un entier a : a − 1 et les comparaisons à 0 d'un entier a : a = 0, a > 0 et a < 0. Question 2 Comment étendre cette fonction aux entiers de signe quelconque ? Exercice 2-6 Produit de deux entiers Question 1 Proposez un algorithme récursif de calcul du produit de deux entiers naturels a et b en supposant que les seules opérations de base dont vous disposez sont la somme de deux entiers a et b : a + b le retrait de 1 à un entier a : a − 1 et la comparaison à 0 d'un entier a : a = 0. Exercice 2-7 Puissance entière d'un nombre réel Question 1 Proposez un algorithme récursif de calcul de la puissance n-ième (n ∈ N) d'un nombre réel a en supposant que les seules opérations de base dont vous disposez sont le produit de deux réels a et b : a × b le retrait de 1 à un entier a : a − 1 et la comparaison à 0 d'un entier a : a = 0. Exercice 2-8 Algorithme d'Euclide L'algorithme d'Euclide permet de calculer le pgcd de deux nombres entiers, c'estàdire le plus grand entier positif divisant ces deux nombres, par des divisions successives. Voici le déroulement de cet algorithme pour le calcul du pgcd de a = 119 et b = 544 119 544 119 68 51 = = = = = 544 119 68 51 17 × × × × × 2 0 + 4 + 1 + 1 + 3 + 119 68 51 17 0 Le pgcd de 119 et 544 est le dernier reste non nul, c'estàdire 17. Le pgcd n'est pas déni lorsque les deux nombres sont nuls. Question 1 Exprimez de manière récursive cet algorithme. Vous pourrez supposer que les deux entiers a et b sont positifs ou nuls, et que l'un au moins de ces deux entiers n'est pas nul. Question 2 Codez cet algorithme en Caml en utilisant l'opérateur modulo. Question 3 En sachant qu'en Caml l'expression a mod b a une valeur ayant le même signe que a, quelle est la valeur de l'expression pgcd 119 (-544) ? Question 4 Modiez la programmation de votre fonction pgcd pour que les valeurs qu'elle renvoie soient toujours positives. Exercice 2-9 Coecient binomial n n! Les coecients binomiaux sont dénis pour les entiers naturels n ≥ p ≥ 0 par = . p p!(n − p)! Une relation de récurrence valable pour n > p > 0 est n+1 n n = + p+1 p p+1 Question 1 Réalisez une fonction eectuant un calcul récursif des coecients binomiaux qui n'utilise que l'addition des entiers. Question 2 Tracez le calcul du coecient binomial pour n = 5 et p = 2. 1.3 Algorithmes récursifs sur les chaînes de caractères Palindromes Un palindrome est un mot dont les lettres lues de gauche à droite sont les mêmes que celles Exercice 2-10 lues de droite à gauche. Les mots radar, elle, été, ici sont des palindromes. Question 1 Réalisez un prédicat qui teste si un mot est un palindrome. Pour cela vous pourrez utiliser la fonction String.sub de type string → int → int → string qui permet d'extraire une sous-chaîne d'une chaîne (premier paramètre) à partir d'un indice (second paramètre) et d'une certaine longueur (troisième paramètre). Exercice 2-11 Occurrences dans une chaîne Question 1 Réalisez une fonction nb_occurrences de type string → char → int qui renvoie le nombre d'occurrences du caractère (second paramètre) dans la chaîne (premier paramètre). Par exemple # # - nb_occurrences "abcdebdb" ’z’ ;; : int = 0 nb_occurrences "abcdebdb" ’b’ ;; : int = 3 3 Vous pourrez utiliser avec prot la fonction String.sub Question 2 Réalisez maintenant une fonction indice de type string → char → int qui renvoie l'indice de la première occurence du caractère (second paramètre) dans la chaîne (premier paramètre) si le caractère est eectivement présent, et qui déclenche une exception Failure "indice caractere non trouve" : dans le cas contraire. Cette fonction indice est une fonction qui fait partie du module String sous le nom index. Une solution possible pour cette question est donc let indice = String.index mais ce n'est évidemment pas ce qui est attendu. De plus, lorsque le caractère n'est pas présent dans la chaîne, la fonction String.index déclenche l'exception Not_found. Exercice 2-12 Permutations des caractères Dans cette exercice, on appelle d'une chaîne de caractères s toute chaîne de même longueur que s contenant les mêmes caractères que s. Par exemple, la chaîne eadbc est une permutation de la chaîne abcde. Si la chaîne s a tous ses caractères distincts, il existe |s|! permutations de s. On suppose dans la suite que s est une chaîne ayant tous ses caractères distincts. On suppose numérotées de 0 à |s|!−1 les permutations de s rangées dans l'ordre lexicographique. Par exemple, la chaîne eadbc est la permutation numéro 100 de la chaîne abcde. Réalisez un programme qui donne la permutation numéro n d'une chaîne s. (Vous pourrez supposer que les caractères de la chaîne s sont de gauche à droite dans l'ordre lexicographique. Si ce n'est pas le cas, l'ordre lexicographique des permutations sera induit par l'ordre des caractères dans s.) permutation Exercice 2-13 Évaluation d'expressions arithmétiques simples Dans cet exercice on considère des chaînes de caractères décrivant des sommes de nombres entiers naturels. Ces chaînes ne comprennent que des chires (caractères ’0’, ’1’, . . . , ’9’) et le symboles usuel de l'addition ’+’. Ces chaînes représentent donc soit un entier naturel, soit une somme d'entiers naturels. On suppose de plus que cette chaîne est bien formée, c'estàdire qu'elle représente eectivement une somme d'entiers. On s'interdit donc des chaînes de la forme "", "12+", "+12", "12++12", . . . Question 1 Réalisez la fonction evalue_somme de type string → int qui renvoie l'entier égal à la somme représentée par la chaîne passée en paramètre. Par exemple # # # # - evalue_somme : int = 123 evalue_somme : int = 138 evalue_somme : int = 139 evalue_somme : int = 2139 "123" ;; "123+15" ;; "123+15+1" ;; "123+15+1+2000" ;; 4 Vous pourrez utiliser avec prot les fonctions String.sub (cf exercice 10), String.index (cf exercice 11) et int_of_string. 1.4 Algorithmes récursifs géométriques Exercice 2-14 Tracer un segment En informatique graphique, tous les points ont des coordonnées entières. Soit donc deux points A de coordonnées (xA , yA ) et B de coordonnées (xB , yB ). Proposez un algorithme récursif pour tracer à l'écran le segment [A, B]. La commande primitive que vous utiliserez est la commande plot x y qui dessine le pixel de coordonnées (x, y). 1.5 Algorithmes récursifs sur les tableaux Exercice 2-15 Somme des éléments d'un tableau Donnez une version récursive du calcul de la somme des éléments d'un tableau d'entiers. Exercice 2-16 Inversion Donnez un algorithme récursif de l'inversion de l'ordre des éléments d'un tableau. 5