Vous êtes sur la page 1sur 4

1ère année 2021-2022

TD6

1 Récursivité simple
1. Puissance d’un nombre, version naive
xn = x × xn−1 et x0 = 1, pour n ≥ 0.
Ecrire une fonction récursive qui calcule et retourne la puissance d’un nombre
2. Puissance d’un nombre, version récursive rapide
(
x2p = (xp )2
(1)
x2p+1 = x × (xp )2

Ecrire une fonction récursive qui calcule et retourne la puissance d’un nombre
3. Renverser un tableau :
Ecrire une fonction récursive qui inverse l’ordre des éléments d’un tableau de nombres dont les
indices sont compris entre 0 et n-1. Pour voir cette fonction de manière recursive, on échange le
premier et le dernier nombre, puis on inverse l’ordre des éléments d’un tableau de nombres dont
les indices sont compris entre 1 et n-2.
4. Palindrome :
Ecrire une fonction récursive qui détermine si une chaı̂ne de caractères est un palindrome par la
méthode suivante : un mot est un palindrome si sa première lettre est identique à sa dernière et si
la sous chaı̂ne 2..n-1 est un palindrome

2 Récursivité multiple
5. Cnp :
Ecrire une fonction récursive qui calcule et retourne la combinaison de p éléments parmi n en
remarquant que :
n−1
 n n−1
Cp = Cp−1 + Cp

Cn = 1 (2)
 0
Cnn = 1

3 Récursivité imbriquée
6. Ackerman : La fonction d’Ackerman est un exemple de récursivité imbriquée. Elle est définie de
la manière suivante : 
n + 1 si m = 0

A(m, n) = A(m − 1, 1) si m > 0 et n = 0 (3)

A(m − 1, A(m, n − 1)) sinon

Ecrire une fonction récursive qui calcule et retourne la fonction d’Ackerman


Cette fonction croit très rapidement (voir table ??)et effectue un grand nombre d’appels récursifs.
Elle devient rapidement non calculable par une procédure naive. Par exemple, pour calculer acker-
man(4,1), il faut 2862984010 appels récursifs.

1
Table 1 – Valeurs de la fonction d’Ackerman

A(m,n) 0 1 2 3 4 5 6 7 8 9 10 11 12
0 1 2 3 4 5 6 7 8 9 10 11 12 13
1 2 3 4 5 6 7 8 9 10 11 12 13 14
2 3 5 7 9 11 13 15 17 19 21 23 25 27
3 5 13 29 61 125 253 509 1021 2045 4093 8189 16381 32765
4 13 65533 A(4,2)

4 Récursivité croisée
7. Fonctions numériques : Soient les 2 fonctions définies de la manière suivante :
a n + bn

a = 4 a
0 n+1 =
p 2
b0 = 5 bn+1 = an .bn

Ecrire 2 fonctions récursives qui calculent et retournent les valeurs des suites an et bn pour un
nombre n donné. Ces deux suites convergent vers la même valeur 4.48605716057520531592.

5 Récursivité et backtraking
8. Anagrammes
Les anagrammes d’un mot sont les mots qui sont formés avec les mêmes lettres, mais dans un ordre
différents. Par exemple, retine est un anagramme de entier, tout comme entrie (qui n’a aucune
signification).

Algorithm 1 Anagrammes de mot depuis la lettre d’indice n


1: if n est l’indice de la derniere lettre du mot then
2: Afficher le mot complet, c’est un annagramme
3: else
4: for i = n jusqu’a l’indice de la derniere lettre du mot do
5: Permuter la lettre d’indice n et celle d’indice i
6: Calculer les anagrammes du mot depuis l’indice n + 1
7: /*
8: La ligne suivante remet le mot avec la configuration avant l’echange entre n et i
9: C’est la notion de baktrack : on a examine ou calcule l’anagramme en echangeant n et i
10: Pour faire la meme chose avec la lettre i + 1, il faut remettre en place la lettre n
11: */
12: Permuter la lettre d’indice n et celle d’indice i
13: end for
14: end if

Ecrire une fonction récursive qui affiche tous les anagrammes d’un mot passé en paramètres, en
utilisant l’algorithme ??. Le prototype de la fonction sera au choix :
void strAnagramrec(char* mot, char* pointeursurlalettreaechanger) ; void strAnagramrec(char* mot, int
indice) ;
9. Les 8 reines
Comment placer 8 reines sur un échiquier sans qu’elles soient en prises ?
Ecrire une fonction réalisant l’algorithme ??. On supposera que la fonction qui teste si la position
line,col est possible est déjà écrite et que son prototype est ;
int isQueenPossible(char** reines, int size, int line, int col);

2
Algorithm 2 Placer la k ieme reine sur un echiquier de n cases
1: if k ≥ n then
2: On a place les n reines, c’est gagne,
3: Retourner 1
4: else
5: for i = 0 jusqu’a n − 1 do
6: if la position i,k est possible sur l’echiquier then
7: Mettre la reine en position i,k
8: /*
9: On cherche maintenant a positionner les autres reines, en commencant par la k+1
10: */
11: if Placer la k + 1ieme reine sur un echiquier de n cases == 1 then
12: C’est reussi, retourner 1
13: else
14: /*
15: La ligne suivante remet l’echiquier avec la configuration avant l’essai de la reine k en i,k
16: C’est la notion de baktrack : on restaure l’etat de l’echiquier comme avant l’essai
17: */
18: Supprimer la reine en position i,k
19: end if
20: end if
21: end for
22: end if

6 Plus difficile : récursivité sans paramètre de contrôle


Dans les problèmes précédents, la récursivité est contrôlée par un paramètre qui décroit (ou croit
selon le cas), ce qui permet d’arrêter les appels récursifs de manière certaine.
Dans certains problèmes, en particulier de jeu, on explore de manière récursive des solutions poten-
tielles, mais sans paramètre de contrôle. Le principe est le même, on considère un mouvement possible
qui donne une solution partielle, et on regarde si ce mouvement amène à une solution par un appel
récursif. Si ce n’est pas le cas, on annule ce mouvement et on cherche un autre mouvement.
Il faut cependant prendre garde à ne pas retomber plusieurs fois sur la même solution partielle : dans
ce cas, il y a un risque de boucle infinie entre les différentes solutions partielles. On stocke les solutions
partielles déjà examinées auparavant.
10. Les Monstres et les globes
Il y a trois monstres et trois globes, chacun de trois tailles différentes (petit, moyen, grand). Au
départ, les globes sont répartis aléatoirement entre les monstres. Le but est que chaque monstre
porte le globe correspondant à sa taille.
Les globes sont transférés entre les monstres en respectant les trois règles suivantes :
(a) un seul globe peut être transféré à la fois,
(b) si un monstre détient plus d’un globe, seul le plus grand peut être transféré,
(c) un globe ne peut pas être transféré à un monstre détenant un globe plus grand

Représentation des monstres et des globes


Une solution pour représenter monstres et globes est d’utiliser une matrice d’octets valant 1 ou 0.
Les lignes sont les indices des monstres (0 pour petit, 1 pour le moyen et 2 pour le grand). Les
colonnes correspondent à la taille des globes (0 pour petit, 1 pour le moyen et 2 pour le grand).
La valeur 1 à l’indice i,j signifie que le monstre i porte le globe j. Une situation est donc donnée
par cette matrice dont 3 éléments sur 3 lignes différentes valent 1, les autres valant 0. La situation
gagnante est donnée par la diagonale à 1.

Tableau des configurations déjà examinées

3
Dans un cadre général, on utiliserait ici soit une table de hachage, soit une liste, structure que nous
verrons au deuxième semestre. Dans ce cas qui nous intéresse, une configuration contient au plus 9
bits d’informations : présence ou absence d’un globe pour chaque monstre. On peut donc coder une
configuration avec un entier sur 9 bits : 3 bits pour le monstre 0 (présence ou absence des globes
0,1,2), 3 bits pour le monstre 1, 3 bits pour le monstre 2. Ainsi, l’entier en base 2 0b001100010
indique le petit montre 0 porte le grand globe 2, le moyen monstre 1 porte le petit globe 0 et le
grand monstre 2 porte le globe 1.
Un tableau d’octet 1 dont les indices sont au moins sur 9 bits suffit donc à stocker toutes les confi-
gurations possibles, et sera alors utilisé pour conserver toutes les configurations deja examinées
pendant la recherche. La fonction int monsterToIndex(char monster[][NUMBER]) ci dessous calcule l’en-
tier correspondant à la configuration monster.

int monsterToIndex(char monster[][NUMBER]) { int i,j,s=0;


for (i=0; i<NUMBER;i++)
for(j=0;j<NUMBER; j++) {
s<<=1;
s |= monster[i][j];
}
return s;
}

Algorithm 3 Positionner les globes sur les monstres : tableau des monstres, tableau des situations deja
vues
1: if chaque monstre porte son globe then
2: /* C’est gagne, */
3: Retourner 1
4: else
5: if le tableau des monstres a deja ete examine then
6: /* C’est pas gagne, on a deja vu ce cas */
7: Retourner 0
8: else
9: Mettre le tableau des monstres dans le tableau des situations deja vues
10: for toutes les paires i,j de monstres do
11: if le monstre i peut donner son globe au monstre j then
12: Effectuer le mouvement de globe entre i et j
13: /* Il faut maintenant continuer recursivement a deplacer les globes */
14: if positionner les globes sur les bons monstres == 1 then
15: /* C’est reussi, */
16: Afficher le mouvement
17: retourner 1
18: else
19: /*
20: La ligne suivante restaure la configuration des monsters
21: On annule le mouvement précédent de i vers j
22: */
23: Remettre le globe du monstre j au monstre i
24: /* et on passe a la paire i,j suivante */
25: end if
26: end if
27: end for
28: end if
29: end if

1. En réalité, on pourrait utiliser 1 seul bit pour indiquer que la configuration est vue et stocker 8 configurations sur un
octet

Vous aimerez peut-être aussi