Favicon
NSI Terminale

Connexion élèves

Choisir le(s) module(s) à installer :

Correction : principes de la récursivité

La fonction mystère


def f(a, n):
	if n == 0:
		return 0 
	return a + f(a, n-1)
			

Cas de base : lignes 3 et 4

Cas général : ligne 5

La fonction prend 2 paramètres, a et n. Le premier n'est jamais modifié, le deuxième diminue de 1 à chaque appel récursif.

→ exemple pour a = 2 et n = 3 :

Tracé fonction mystère

→ la fonction fait donc le produit de a par n.

Fonction puissance

Version itérative


def puissance(y:int, x: int)->int:
	p = 1
	for i in range(x):
		p = p * y
	return p
			

Version récursive

Cas général

Prenons l'exemple de x = 4 ( et y n'importe quelle valeur ) :

Donc : yx = y * yx-1, soit : puissance(y, x) = y * puissance(y, x - 1)

Cas de base

On arrête la récursion quand x == 0, et on renvoie alors 1.

(Remarque : pour "économiser" un appel récursif, on peut aussi prendre comme cas de base : quand x == 1, renvoyer y...)

Fonction complète


def puis_recurs(y: int, x: int)->int:
	if x == 0 : 
		return 1
	else:
		return y * puis_recurs(y, x-1)
			

Construire une chaîne

Cas général

Prenons par exemple i = 1 et n = 5 : la chaîne renvoyée par la fonction devra donc être "12345"

On en déduit donc que pour toute valeur de i : chaine(i, n) = i + chaine(i+1, n)

Cas de base

Quand i == n, on renvoie le dernier nombre à concaténer, à savoir n ( ou i, ils sont alors égaux 😏 )

Fonction complète


def chaine(i: int, n: int)->str:
	if i == n:
		return str(i)  # attention au transtypage indispensable int -> str !
	else:
		return str(i) + chaine(i+1, n)	
			

Caractère dans une chaîne

Cas général :

Ici, il faut voir que l'on va se contenter de "parcourir" la chaîne caractère après caractère depuis le premier : pour cela, on appelle la fonction en lui passant comme paramètre à chaque appel récursif, la chaîne, le caractère à rechercher et un troisième paramètre servant de "pointeur d'index" qui sera incrémenté à chaque appel récursif ( ceci jouant donc le rôle d'une itération du type : for caractere in chaine ).

Un caractère se trouve dans la chaîne, si il est à l'indice n OU dans la suite de la chaîne, donc :

est_dans(n) = chaine[n] == car or est_dans(n+1)

Cas de base :

On parcourt la chaîne caractère après caractère; en arrivant au dernier caractère, on renvoie simplement le résultat de l'expression booléenne chaine[n] == car, qui évalue si le dernier caractère est celui recherché; plus besoin alors d'appel récursif...

→ fonction complète :

	
def est_dans(ch: str, car: str, n = 0)->bool:         # n = index du caractère "en cours", initialisé à 0 par défaut
    if n == len(ch)-1:                                # cas de base : on est arrivé au dernier caractère ( attention à l'indice de celui-ci ! )
        return ch[n] == car                           # le dernier caractère est celui recherché ?
    else:
        return est_dans(ch ,car, n+1) or ch[n] == car # cas général : appel récursif en incrémentant 'n' de 1 à chaque appel
        

Vous seriez peut-être tentés d'écrire à la dernière ligne :

	
........
    else:
        est_dans(ch ,car, n+1) or ch[n] == car # pas de 'return'...
        		

Qu'est-ce que cela renvoie ? Comment expliquez-vous ça ?? Faites la trace des appels récursifs et des résultats renvoyés...

Remarque importante

On remarque que le cas de base correspond au cas général sans l'appel récursif de la fonction.

D'où l'importance de chercher d'abord le cas général d'une récursion, puis ensuite réfléchir au cas de base.