L'idée de la récursivité est simple : une fonction s'appelle elle-même pour résoudre un problème en le divisant en sous-problèmes plus petits. À chaque étape, elle traite une partie du problème, jusqu'à atteindre un cas de base simple à résoudre.
Est-ce qu'appeler une fonction encore et encore est toujours efficace ? Si le problème devient trop grand ou mal divisé, est-ce que cette approche risque de créer plus de complexité que de simplicité ?
A copier dans le cahier.
Une fonction est :
for
, while
) pour répéter un bloc de code.
A copier dans le cahier.
Une fonction récursive est une fonction qui s'appelle elle-même dans son corps. Elle doit avoir deux composants principaux :
La fonction factorielle est définie par : \( n! = n \times (n-1) \times (n-2) \times ... \times 2 \times 1 \).
Par définition, \( 0! = 1 \).
facto_recur(n)
de manière récursive.facto_itera(n)
de manière itérative.Exemples :
>>> facto_recur(5)
120
>>> facto_recur(0)
1
>>> facto_itera(5)
120
Tests :
Affichage :
Console:
La suite de Fibonacci est définie ainsi :
Les deux premiers termes sont égaux à 1 et chaque terme suivant est la somme des deux termes précédents.
On définit la fonction fibo
telle que :
fibo(1)
renvoie 1fibo(2)
renvoie 1fibo(3)
renvoie 2fibo(4)
renvoie 3fibo_recur(n)
de manière récursive.fibo_itera(n)
de manière itérative.Tests :
Affichage :
Console:
compte_voyelle_recur(texte)
qui retourne le nombre de voyelles dans texte
(version récursive).compte_voyelle_itera(texte)
qui retourne le nombre de voyelles dans texte
(version itérative).On considère les voyelles : a, e, i, o, u, y (minuscules et majuscules).
Tests :
Affichage :
Console:
On considère des lapins ayant les propriétés suivantes :
Exemple d’évolution (nombre de lapins adultes, adolescents et bébés) :
Mois | 0 | 1 | 2 | 3 | 4 | 5 | 6 |
---|---|---|---|---|---|---|---|
adultes=2 adolescents=0 bébés=0 |
adultes=2 adolescents=0 bébés=2 |
adultes=2 adolescents=2 bébés=2 |
adultes=4 adolescents=2 bébés=2 |
adultes=6 adolescents=2 bébés=4 |
adultes=8 adolescents=4 bébés=6 |
adultes=12 adolescents=6 bébés=8 |
lapin_recur
qui retourne le nombre de lapins en fonction du mois. La
progammation doit être récursive.lapin_itera
qui retourne le nombre de lapins en fonction du mois. La
progammation doit être itérative.Tests :
Affichage :
Console:
En mathématiques, on considère les coefficients binomiaux \(\begin{pmatrix} n\\p\end{pmatrix}\) avec \(n\) et \(p\) appartenant à \(\mathbb{N}\), \(1 \leq n\) et \(0 \leq p \leq n\).
Nous pouvons les construire de deux façons:
Nous possédons la formule suivante : \(\begin{pmatrix} n\\p\end{pmatrix}=\frac{n!}{p!(n-p)!}\)
Ainsi:
coeff_binom_recur(n,p)
grâce aux conditions de récurrence.coeff_binom_itera(n,p)
grâce à la dernière formule.Tests :
# Tests
Affichage :
Console:
Le but de cet exercice est d’écrire une fonction récursive traduire_romain
qui prend en paramètre
une chaîne de caractères, non vide, représentant un nombre écrit en chiffres romains et qui renvoie son écriture
décimale.
Les chiffres romains considérés sont : I, V, X, L, C, D et M. Ils représentent respectivement les nombres 1, 5, 10, 50, 100, 500, et 1000 en base dix.
On dispose d’un dictionnaire romains
dont les clés sont les caractères apparaissant dans l’écriture
en chiffres romains et les valeurs sont les nombres entiers associés en écriture décimale :
romains = {"I":1, "V":5, "X":10, "L":50, "C":100, "D":500, "M":1000}
Le code de la fonction traduire_romain
fournie repose sur le principe suivant :
Ainsi, XIV correspond au nombre 10 + 5 - 1 puisque :
On rappelle que pour priver une chaîne de caractères de son premier caractère, on utilisera l’instruction :
nom_de_variable[1:]
Par exemple, si la variable mot contient la chaîne "CDI"
, mot[1:]
renvoie
"DI"
.
Compléter le code de la fonction traduire_romain
et le tester.
Exemples :
>>> traduire_romain("XIV")
14
>>>traduire_romain("CXLII")
142
>>> traduire_romain("MMXXIII")
2023
Tests :
# Tests
Affichage :
Console:
Une utilisation "classique" de « diviser pour régner » est son utilisation sur les listes et avec une récurrence.
Soit tab
un tableau non vide d'entiers triés dans l'ordre croissant et n
un entier.
La fonction chercher
ci-dessous doit renvoyer un indice où la valeur n
apparaît dans tab
si cette valeur y figure et None
sinon.
Les paramètres de la fonction sont :
tab
, le tableau dans lequel s'effectue la recherchen
, l'entier à chercher dans le tableaui
, l'indice de début de la partie du tableau où s'effectue la recherchej
, l'indice de fin de la partie du tableau où s'effectue la rechercheL’algorithme demandé est une recherche dichotomique récursive.
Exemples :
>>> chercher([1, 5, 6, 6, 9, 12], 7, 0, 10)
>>> chercher([1, 5, 6, 6, 9, 12], 7, 0, 5)
>>> chercher([1, 5, 6, 6, 9, 12], 9, 0, 5)
4
>>> chercher([1, 5, 6, 6, 9, 12], 6, 0, 5)
2
Tests :
Affichage :
Console:
On s’intéresse à un algorithme récursif qui permet de rendre la monnaie à partir d’une liste donnée de valeurs de pièces et de billets.
Le système monétaire est : [100, 50, 20, 10, 5, 2, 1]
(disponibles en quantité illimitée).
On cherche à donner la liste des valeurs à rendre pour une somme donnée a_rendre
, en partant d’un indice rang
dans cette liste (glouton : on prend la plus grande valeur possible à partir de rang
).
Compléter la fonction rendu_glouton(a_rendre, rang)
récursive.
Exemples attendus :
>>> rendu_glouton(67, 0)
[50, 10, 5, 2]
>>> rendu_glouton(291, 0)
[100, 100, 50, 20, 20, 1]
>>> rendu_glouton(291, 1) # sans billets de 100
[50, 50, 50, 50, 50, 20, 20, 1]
Tests :
Affichage :
Console:
On considère des tableaux de nombres dont tous les éléments sont présents exactement trois fois à la suite, sauf un élément qui est présent une unique fois et que l'on appelle « l'intrus ». Voici quelques exemples :
tab_a = [3, 3, 3, 9, 9, 9, 1, 1, 1, 7, 2, 2, 2, 4, 4, 4, 8, 8, 8, 5, 5, 5]
#l'intrus est 7
tab_b = [8, 5, 5, 5, 9, 9, 9, 18, 18, 18, 3, 3, 3]
#l'intrus est 8
tab_c = [5, 5, 5, 1, 1, 1, 0, 0, 0, 6, 6, 6, 3, 8, 8, 8]
#l'intrus est 3
On remarque qu'avec de tels tableaux :
Ce que l'on peut observer ci-dessous en observant les valeurs des paires de voisins
marquées par des caractères ^
:
[3, 3, 3, 9, 9, 9, 1, 1, 1, 7, 2, 2, 2, 4, 4, 4, 8, 8, 8, 5, 5, 5]
^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^
0 3 6 9 12 15 18 21
Dans des listes comme celles ci-dessus, un algorithme récursif pour trouver l'intrus
consiste alors à choisir un indice i
multiple de 3 situé approximativement au milieu
des indices parmi lesquels se trouve l'intrus.
Puis, en fonction des valeurs de l'élément d'indice i
et de son voisin de droite, à
appliquer récursivement l'algorithme à la moitié droite ou à la moitié gauche des
indices parmi lesquels se trouve l'intrus.
Par exemple, si on s’intéresse à l’indice 12, on voit les valeurs 2 et 4 qui sont différentes : l’intrus est donc à gauche de l’indice 12 (indice 12 compris).
En revanche, si on s’intéresse à l’indice 3, on voit les valeurs 9 et 9 qui sont identiques : l’intrus est donc à droite des indices 3-4-5, donc à partir de l’indice 6.
Compléter la fonction récursive trouver_intrus
qui met
en œuvre cet algorithme.
Exemples :
>>> trouver_intrus([3, 3, 3, 9, 9, 9, 1, 1, 1, 7, 2, 2, 2, 4, 4, 4, 8, 8, 8, 5, 5, 5], 0, 21)
7
>>> trouver_intrus([8, 5, 5, 5, 9, 9, 9, 18, 18, 18, 3, 3, 3],0, 12)
8
>>> trouver_intrus([5, 5, 5, 1, 1, 1, 0, 0, 0, 6, 6, 6, 3, 8, 8, 8], 0, 15)
3
Tests :
# Tests
Affichage :
Console: