ajout de tous les cours et TP préparés cet été
This commit is contained in:
97
Recursivité/Corrigé_Exercices.md
Normal file
97
Recursivité/Corrigé_Exercices.md
Normal file
@@ -0,0 +1,97 @@
|
||||
# Corrigé des exercices de révision sur la récursivité
|
||||
|
||||
## Exercice 1 : Exponentiation rapide
|
||||
|
||||
**Rappel :** On souhaite calculer `a^n` avec les relations de récurrence suivantes :
|
||||
- `a^0 = 1`
|
||||
- Si `n` est pair : `a^n = (a * a)^(n / 2)`
|
||||
- Sinon : `a^n = a * (a * a)^((n - 1) / 2)`
|
||||
|
||||
1. Version récursive
|
||||
|
||||
```python
|
||||
def exponentiation_rapide_recursive(a, n):
|
||||
if n == 0:
|
||||
return 1 # Cas de base
|
||||
elif n % 2 == 0:
|
||||
return exponentiation_rapide_recursive(a * a, n // 2)
|
||||
else:
|
||||
return a * exponentiation_rapide_recursive(a * a, (n - 1) // 2)
|
||||
|
||||
# Exemple de test
|
||||
print(exponentiation_rapide_recursive(2, 10)) # Renvoie 1024
|
||||
```
|
||||
|
||||
2. Version itérative
|
||||
|
||||
```python
|
||||
def exponentiation_rapide_iterative(a, n):
|
||||
result = 1
|
||||
while n > 0:
|
||||
if n % 2 == 1: # Si n est impair
|
||||
result *= a
|
||||
a *= a
|
||||
n //= 2 # Diviser n par 2
|
||||
return result
|
||||
|
||||
# Exemple de test
|
||||
print(exponentiation_rapide_iterative(2, 10)) # Renvoie 1024
|
||||
```
|
||||
|
||||
|
||||
|
||||
-------
|
||||
|
||||
**Exercice 2 : Génération d’une liste décroissante**
|
||||
|
||||
|
||||
|
||||
**Fonction récursive**
|
||||
|
||||
```python
|
||||
def generate_liste(n):
|
||||
if n == 0:
|
||||
return [0] # Cas de base
|
||||
else:
|
||||
return [n] + generate_liste(n - 1) # Ajoute n à la liste générée pour n-1
|
||||
|
||||
# Exemple de test
|
||||
print(generate_liste(5)) # Renvoie [5, 4, 3, 2, 1, 0]
|
||||
```
|
||||
|
||||
______
|
||||
|
||||
**Exercice 3 : Multiplication égyptienne**
|
||||
|
||||
|
||||
|
||||
**Utiliser la technique pour a = 13 et b = 61**
|
||||
|
||||
| **Étapes de la multiplication égyptienne** |
|
||||
| ------------------------------------------ |
|
||||
| 13 x 61 = 61 |
|
||||
| 6 x 122 |
|
||||
| 3 x 244 = 244 |
|
||||
| 1 x 488 = 488 |
|
||||
| **Total = 793** |
|
||||
|
||||
Fonction récursive :
|
||||
|
||||
```python
|
||||
def multiplication_egyptienne(a, b):
|
||||
if a == 0:
|
||||
return 0 # Cas de base : si a est 0, le produit est 0
|
||||
elif a % 2 == 1:
|
||||
return b + multiplication_egyptienne(a // 2, b * 2) # Ajouter b si a est impair
|
||||
else:
|
||||
return multiplication_egyptienne(a // 2, b * 2) # Continuer sans ajouter si a est pair
|
||||
|
||||
# Exemple de test
|
||||
print(multiplication_egyptienne(13, 61)) # Renvoie 793
|
||||
```
|
||||
|
||||
**Complexité de l’algorithme**
|
||||
|
||||
|
||||
|
||||
La complexité de cet algorithme dépend du nombre de divisions de a par 2, ce qui correspond à une complexité logarithmique : **O(log a)**. En effet, chaque étape divise a par 2, ce qui signifie qu’il y aura environ log_2(a) itérations.
|
||||
@@ -1,4 +1,3 @@
|
||||
|
||||
# Diviser pour régner
|
||||
|
||||
### Le programme
|
||||
@@ -59,54 +58,61 @@ Prenons une liste d'exemple : `[38, 27, 43, 3, 9, 82, 10]`.
|
||||
|
||||
3. **Combiner** : Enfin, on fusionne les deux sous-listes triées :
|
||||
- `[27, 38, 43]` et `[3, 9, 10, 82]` sont fusionnées pour donner la liste triée finale : `[3, 9, 10, 27, 38, 43, 82]`.
|
||||
|
||||
--------------
|
||||
|
||||
### Implémentation en python
|
||||
--------------
|
||||
|
||||
### Implémentation en Python
|
||||
|
||||
```python
|
||||
def tri_fusion(gauche:list, droite:list):
|
||||
tab_fusion = []
|
||||
l1, l2 = len(gauche), len(droite)
|
||||
i1, i2 = 0,0
|
||||
while i1 < l1 and i2 < l2:
|
||||
if gauche[i1] < droite[i2]:
|
||||
tab_fusion.append(gauche[i1])
|
||||
i1 += 1
|
||||
else:
|
||||
tab_fusion.append(droite[i2])
|
||||
i2 += 1
|
||||
return tab_fusion + gauche[i1:] + droite[i2:]
|
||||
def fusionner(gauche: list, droite: list) -> list:
|
||||
"""Fusionne deux listes triées en une seule liste triée."""
|
||||
resultat = []
|
||||
i, j = 0, 0
|
||||
|
||||
def fusion(tab:list):
|
||||
if len (tab) <=1:
|
||||
return tab
|
||||
m = len(tab) // 2
|
||||
return tri_fusion(fusion(tab[:m]), fusion (tab[m:]))
|
||||
while i < len(gauche) and j < len(droite):
|
||||
if gauche[i] < droite[j]:
|
||||
resultat.append(gauche[i])
|
||||
i += 1
|
||||
else:
|
||||
resultat.append(droite[j])
|
||||
j += 1
|
||||
|
||||
# Ajouter les éléments restants
|
||||
return resultat + gauche[i:] + droite[j:]
|
||||
|
||||
|
||||
def tri_fusion(tab: list) -> list:
|
||||
"""Trie une liste en utilisant l'algorithme du tri fusion."""
|
||||
# Cas de base : une liste de 0 ou 1 élément est déjà triée
|
||||
if len(tab) <= 1:
|
||||
return tab
|
||||
|
||||
# Diviser : trouver le milieu et séparer en deux sous-listes
|
||||
milieu = len(tab) // 2
|
||||
gauche = tri_fusion(tab[:milieu])
|
||||
droite = tri_fusion(tab[milieu:])
|
||||
|
||||
# Combiner : fusionner les deux sous-listes triées
|
||||
return fusionner(gauche, droite)
|
||||
```
|
||||
|
||||
```
|
||||
• tab_fusion est une liste vide où seront ajoutés les éléments fusionnés.
|
||||
• l1 et l2 stockent les tailles respectives de gauche et droite.
|
||||
• i1 et i2 sont des indices qui parcourent gauche et droite.
|
||||
2. Boucle principale :
|
||||
• Tant que l’on n’a pas parcouru complètement l’une des deux listes (gauche ou droite), on compare les éléments actuels de chaque liste (c’est-à-dire gauche[i1] et droite[i2]).
|
||||
• Si l’élément de gauche est plus petit, on l’ajoute à tab_fusion, et on incrémente i1.
|
||||
• Sinon, on ajoute l’élément de droite et on incrémente i2.
|
||||
3. Retour des éléments restants :
|
||||
• Une fois que l’une des deux listes est entièrement parcourue, on ajoute les éléments restants de l’autre liste à tab_fusion. C’est ce que fait gauche[i1:] pour la première liste, et droite[i2:] pour la deuxième.
|
||||
```
|
||||
#### Explication de la fonction `fusionner`
|
||||
|
||||
```
|
||||
Condition de base :
|
||||
• Si le tableau contient un seul élément (ou aucun), il est déjà trié, donc on le retourne tel quel.
|
||||
2. Diviser :
|
||||
• On divise le tableau en deux sous-tableaux de taille approximativement égale à l’aide de m = len(tab) // 2.
|
||||
• tab[:m] correspond à la première moitié du tableau et tab[m:] à la deuxième.
|
||||
3. Récursion et fusion :
|
||||
• On applique récursivement fusion() aux deux moitiés du tableau.
|
||||
• Une fois que les deux sous-tableaux sont triés, on les combine en utilisant la fonction tri_fusion.
|
||||
```
|
||||
- `resultat` est une liste vide où seront ajoutés les éléments fusionnés
|
||||
- `i` et `j` sont des indices qui parcourent respectivement `gauche` et `droite`
|
||||
- **Boucle principale** : tant que l'on n'a pas parcouru complètement l'une des deux listes, on compare les éléments actuels (`gauche[i]` et `droite[j]`)
|
||||
- Si l'élément de gauche est plus petit, on l'ajoute à `resultat` et on incrémente `i`
|
||||
- Sinon, on ajoute l'élément de droite et on incrémente `j`
|
||||
- **Éléments restants** : une fois qu'une liste est entièrement parcourue, on ajoute les éléments restants de l'autre liste
|
||||
|
||||
#### Explication de la fonction `tri_fusion`
|
||||
|
||||
- **Cas de base** : si le tableau contient un seul élément (ou aucun), il est déjà trié, donc on le retourne tel quel
|
||||
- **Diviser** : on divise le tableau en deux sous-tableaux de taille approximativement égale
|
||||
- `tab[:milieu]` correspond à la première moitié
|
||||
- `tab[milieu:]` correspond à la deuxième moitié
|
||||
- **Régner** : on applique récursivement `tri_fusion()` aux deux moitiés du tableau
|
||||
- **Combiner** : une fois les deux sous-tableaux triés, on les fusionne avec la fonction `fusionner`
|
||||
|
||||
|
||||
|
||||
@@ -133,5 +139,4 @@ Auteur : Florian Mathieu
|
||||
|
||||
Licence CC BY NC
|
||||
|
||||
<a rel="license" href="http://creativecommons.org/licenses/by-nc-sa/4.0/"><img alt="Licence Creative Commons" style="border-width:0" src="https://i.creativecommons.org/l/by-nc-sa/4.0/88x31.png" /></a> <br />Ce cours est mis à disposition selon les termes de la <a rel="license" href="http://creativecommons.org/licenses/by-nc-sa/4.0/">Licence Creative Commons Attribution - Pas d’Utilisation Commerciale - Partage dans les Mêmes Conditions 4.0 International</a>.
|
||||
|
||||
<a rel="license" href="http://creativecommons.org/licenses/by-nc-sa/4.0/"><img alt="Licence Creative Commons" style="border-width:0" src="https://i.creativecommons.org/l/by-nc-sa/4.0/88x31.png" /></a> <br />Ce cours est mis à disposition selon les termes de la <a rel="license" href="http://creativecommons.org/licenses/by-nc-sa/4.0/">Licence Creative Commons Attribution - Pas d'Utilisation Commerciale - Partage dans les Mêmes Conditions 4.0 International</a>.
|
||||
|
||||
40
Recursivité/Exercices_Recursivité.md
Normal file
40
Recursivité/Exercices_Recursivité.md
Normal file
@@ -0,0 +1,40 @@
|
||||
# Exercices Récursivité
|
||||
|
||||
---
|
||||
|
||||
## Exercice 1 : Exponentiation rapide
|
||||
|
||||
On rappelle que l'exponentiation rapide permet de calculer le nombre a<sup>n</sup> en utilisant les relations de récurrence suivantes :
|
||||
|
||||
- a<sup>0</sup> = 1
|
||||
- Si n est pair : a<sup>n</sup> = (a × a)<sup>n/2</sup>
|
||||
- Sinon : a<sup>n</sup> = a × (a × a)<sup>(n-1)/2</sup>
|
||||
|
||||
**Questions :**
|
||||
|
||||
1. Écrire une version récursive de l'exponentiation rapide.
|
||||
2. Écrire une version itérative de l'exponentiation rapide.
|
||||
|
||||
---
|
||||
|
||||
## Exercice 2 : Liste décroissante
|
||||
|
||||
Écrire une fonction récursive d'argument `n` qui génère la liste suivante :
|
||||
|
||||
```python
|
||||
[n, n-1, ..., 1, 0]
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Exercice 3 : Multiplication égyptienne
|
||||
|
||||
La multiplication égyptienne, dite aussi du paysan russe, était utilisée par les scribes dès l'Antiquité. Elle ne nécessite pas la connaissance des tables de multiplication, seulement l'addition et la division par deux.
|
||||
|
||||
On multiplie deux entiers, *a* et *b* de la manière suivante : on divise *a* par 2 tant que c'est possible, en doublant *b*, sinon on décrémente *a* et on ajoute *b* au résultat.
|
||||
|
||||
**Questions :**
|
||||
|
||||
1. Utiliser cette technique pour calculer le produit *a* × *b* avec *a* = 13 et *b* = 61.
|
||||
2. Écrire une fonction récursive qui calcule le produit de *a* et *b* en utilisant la multiplication égyptienne.
|
||||
3. Quelle est la complexité de cet algorithme en fonction de *a* ?
|
||||
@@ -1,4 +1,4 @@
|
||||
## Recursivité
|
||||
# Récursivité
|
||||
|
||||
|
||||
|
||||
@@ -17,11 +17,11 @@
|
||||
### Un peu de culture
|
||||
|
||||
La récursivité, en informatique, est une pratique qui permet à une fonction de s'appeler elle-même.
|
||||
On peut comparer cela à la [mise en abyme](https://fr.wikipedia.org/wiki/Mise_en_abyme), procédé littéraire qui décrit une oeuvre incrustée dans elle même
|
||||
On peut comparer cela à la [mise en abyme](https://fr.wikipedia.org/wiki/Mise_en_abyme), procédé littéraire qui décrit une œuvre incrustée dans elle-même.
|
||||
|
||||
<img src="assets/vache_qui_rit.gif" alt="vache qui rit" style="zoom: 67%;" />
|
||||
|
||||
**La fonction récursive s'appelle elle même dans sa définition.**
|
||||
**La fonction récursive s'appelle elle-même dans sa définition.**
|
||||
|
||||
-------------------------------
|
||||
|
||||
@@ -39,9 +39,9 @@ def fct_recursive() :
|
||||
fct_recursive()
|
||||
```
|
||||
|
||||
Cette fonction s'appelle elle même, mais elle présente un problème.
|
||||
Cette fonction s'appelle elle-même, mais elle présente un problème.
|
||||
|
||||
Si nous l'appelons, le résultat sera celui-ci :
|
||||
Si nous l'appelons, le résultat sera celui-ci :
|
||||
|
||||
```python
|
||||
>>> fct_recursive()
|
||||
@@ -55,33 +55,38 @@ Cette fonction s'appelle elle même, mais elle présente un problème.
|
||||
...
|
||||
```
|
||||
|
||||
Tout comme les boucles, il faut créer une instruction permettant d'arrêter l'exécution du code, en récursif nous l'appelons **le cas d'arrêt**. Il permettra d'éviter les appels **infinis**
|
||||
Tout comme les boucles, il faut créer une instruction permettant d'arrêter l'exécution du code, en récursif nous l'appelons **le cas de base** (ou cas d'arrêt). Il permettra d'éviter les appels **infinis**.
|
||||
|
||||
|
||||
|
||||
### Le cas d'arrêt
|
||||
### Le cas de base
|
||||
|
||||
Afin de stopper l'exécution du code il est donc essentiel de créer une instruction n'appelant pas notre fonction.
|
||||
|
||||
Par exemple :
|
||||
Par exemple :
|
||||
|
||||
Voici la fonction somme(n) se définissant comme :
|
||||
|
||||
$`somme(n) = \left\{ \begin{array}{ll} 0 {~si~} n = 0\\ n + somme(n -1){~sinon.} \end{array}\right.`$
|
||||
$$
|
||||
somme(n) = \begin{cases}
|
||||
0 & \text{si } n = 0 \text{ (cas de base)}\\
|
||||
n + somme(n-1) & \text{sinon (cas récursif)}
|
||||
\end{cases}
|
||||
$$
|
||||
|
||||
```python
|
||||
def somme(n) :
|
||||
if n == 0 :
|
||||
return 0
|
||||
return 0 # Cas de base
|
||||
else :
|
||||
return n + somme(n-1)
|
||||
return n + somme(n-1) # Cas récursif
|
||||
```
|
||||
|
||||
Cette fonction s'appelle donc elle même jusqu'à avoir n égal à 0.
|
||||
Cette fonction s'appelle donc elle-même jusqu'à avoir n égal à 0.
|
||||
|
||||
Mais quel sera le résultat de *somme(3)* ?
|
||||
Mais quel sera le résultat de *somme(3)* ?
|
||||
|
||||
Pour obtenir cette réponse nous allons dérouler *à la main* le code :
|
||||
Pour obtenir cette réponse nous allons dérouler *à la main* le code :
|
||||
|
||||
```
|
||||
somme(3) = 3 + somme(2)
|
||||
@@ -92,11 +97,11 @@ somme(0) = 0
|
||||
|
||||
Voici les différents appels de fonctions pour somme(3). Mais là, le résultat n'est pas encore obtenu.
|
||||
|
||||
Pour cela il faut pour cela reprendre les appels de fonctions pour revenir jusqu'à somme(3)
|
||||
Pour cela il faut reprendre les appels de fonctions pour revenir jusqu'à somme(3) :
|
||||
|
||||
```
|
||||
somme(0) = 0
|
||||
somme(1) = 1 + 0 = 1
|
||||
somme(1) = 1 + 0 = 1
|
||||
somme(2) = 2 + 1 = 3
|
||||
somme(3) = 3 + 3 = 6
|
||||
```
|
||||
@@ -105,15 +110,48 @@ Ici nous observons donc 4 appels de fonctions pour résoudre somme(3).
|
||||
|
||||
-----------
|
||||
|
||||
### Appel de fonction en python
|
||||
### La pile d'appels
|
||||
|
||||
En python il existe une limite au nombre d'appel de fonction que l'on peut faire pour une fonction récursive.
|
||||
Lorsqu'une fonction récursive s'exécute, Python utilise une structure de données appelée **pile d'appels** (ou *call stack*) pour gérer les différents appels.
|
||||
|
||||
#### Principe de fonctionnement
|
||||
|
||||
À chaque appel de fonction :
|
||||
1. Python **empile** un nouveau *contexte d'exécution* contenant les paramètres et variables locales
|
||||
2. Lorsque le cas de base est atteint, les appels sont **dépilés** un par un
|
||||
3. Chaque résultat remonte vers l'appel précédent
|
||||
|
||||
#### Visualisation avec somme(3)
|
||||
|
||||
```
|
||||
EMPILEMENT DÉPILEMENT
|
||||
(descente) (remontée)
|
||||
|
||||
┌─────────────┐ ┌─────────────┐
|
||||
│ somme(0) │ ← cas de base │ somme(0) │ → retourne 0
|
||||
├─────────────┤ ├─────────────┤
|
||||
│ somme(1) │ attend somme(0) │ somme(1) │ → retourne 1+0 = 1
|
||||
├─────────────┤ ├─────────────┤
|
||||
│ somme(2) │ attend somme(1) │ somme(2) │ → retourne 2+1 = 3
|
||||
├─────────────┤ ├─────────────┤
|
||||
│ somme(3) │ attend somme(2) │ somme(3) │ → retourne 3+3 = 6
|
||||
└─────────────┘ └─────────────┘
|
||||
BASE BASE
|
||||
```
|
||||
|
||||
> La pile fonctionne selon le principe **LIFO** (Last In, First Out) : le dernier appel empilé est le premier à être résolu.
|
||||
|
||||
-----------
|
||||
|
||||
### Limite de récursion en Python
|
||||
|
||||
En Python il existe une limite au nombre d'appels de fonction que l'on peut faire pour une fonction récursive.
|
||||
|
||||
En effet, avec notre exemple nous voyons que pour obtenir somme(3) nous faisons 4 appels de fonction.
|
||||
|
||||
Ces appels de fonction **s'empilent** en espace mémoire, python peut stocker autour de 1000 appels.
|
||||
Ces appels de fonction **s'empilent** en espace mémoire. Python peut stocker environ **1000 appels** par défaut.
|
||||
|
||||
Si cette limite est dépassée alors l'erreur **RecursionError** apparaîtra.
|
||||
Si cette limite est dépassée alors l'erreur **RecursionError** apparaîtra :
|
||||
|
||||
```python
|
||||
>>> somme(1001)
|
||||
@@ -121,37 +159,195 @@ Si cette limite est dépassée alors l'erreur **RecursionError** apparaîtra.
|
||||
RecursionError: maximum recursion depth exceeded in comparison
|
||||
```
|
||||
|
||||
### Autre type de récursivité
|
||||
> Cette limite existe pour protéger la mémoire de l'ordinateur. On peut la modifier avec `sys.setrecursionlimit()`, mais ce n'est généralement pas recommandé.
|
||||
|
||||
Il existe divers types de récursivité :
|
||||
-----------
|
||||
|
||||
- La récursivité multiple
|
||||
- La récursivité double
|
||||
- La récursivité imbriquée
|
||||
- etc ...
|
||||
### Terminaison d'une fonction récursive
|
||||
|
||||
Ces différents types de récursivité sont quelques peu différents de ce que l'on vient de voir. Mais nous pourrions les rencontrer dans la suite du programme.
|
||||
Une question essentielle se pose : **comment être sûr qu'une fonction récursive s'arrête ?**
|
||||
|
||||
### Récursivité double
|
||||
#### Le variant de boucle
|
||||
|
||||
En effet à la différence de la récursivité dite **simple** il y aura ici plusieurs appels de fonctions dans une même instruction.
|
||||
Pour prouver qu'une fonction récursive termine, on utilise un **variant** : une quantité entière qui :
|
||||
- est **positive ou nulle** à chaque appel
|
||||
- **décroît strictement** à chaque appel récursif
|
||||
|
||||
> En mathématiques, la suite de Fibonacci est une suite de nombres entiers dont chaque terme successif représente la somme des deux termes précédents, et qui commence par 0 puis 1. Ainsi, les dix premiers termes qui la composent sont 0, 1, 1, 2, 3, 5, 8, 13, 21 et 34.
|
||||
Quand le variant atteint 0 (ou une valeur minimale), on est dans le cas de base.
|
||||
|
||||
#### Exemple avec somme(n)
|
||||
|
||||
Pour la fonction `somme(n)` :
|
||||
- **Variant** : la valeur de `n`
|
||||
- À chaque appel récursif, on appelle `somme(n-1)`, donc `n` décroît de 1
|
||||
- Quand `n = 0`, on atteint le cas de base
|
||||
|
||||
| Appel | Valeur du variant (n) |
|
||||
|-------|----------------------|
|
||||
| somme(3) | 3 |
|
||||
| somme(2) | 2 |
|
||||
| somme(1) | 1 |
|
||||
| somme(0) | 0 → cas de base |
|
||||
|
||||
Le variant décroît strictement et atteint 0 : **la fonction termine**.
|
||||
|
||||
#### Attention aux erreurs
|
||||
|
||||
```python
|
||||
def mauvaise_somme(n):
|
||||
if n == 0:
|
||||
return 0
|
||||
else:
|
||||
return n + mauvaise_somme(n + 1) # n augmente !
|
||||
```
|
||||
|
||||
Ici, le paramètre **augmente** au lieu de diminuer : la fonction ne terminera jamais (jusqu'à la `RecursionError`).
|
||||
|
||||
-----------
|
||||
|
||||
### Écrire une fonction récursive : méthodologie
|
||||
|
||||
Pour écrire correctement une fonction récursive, il faut identifier **trois éléments** :
|
||||
|
||||
| Élément | Question à se poser | Exemple avec `somme(n)` |
|
||||
|---------|---------------------|------------------------|
|
||||
| **Cas de base** | Quel est le cas le plus simple, qui ne nécessite pas d'appel récursif ? | `n == 0` → retourne `0` |
|
||||
| **Cas récursif** | Comment décomposer le problème en un sous-problème plus petit ? | `somme(n) = n + somme(n-1)` |
|
||||
| **Variant** | Quelle quantité décroît à chaque appel ? | La valeur de `n` |
|
||||
|
||||
#### Exemple : la factorielle
|
||||
|
||||
On souhaite écrire `factorielle(n)` qui calcule `n! = n × (n-1) × ... × 2 × 1`.
|
||||
|
||||
1. **Cas de base** : `factorielle(0) = 1` (par convention, 0! = 1)
|
||||
2. **Cas récursif** : `factorielle(n) = n × factorielle(n-1)`
|
||||
3. **Variant** : `n` décroît de 1 à chaque appel
|
||||
|
||||
```python
|
||||
def factorielle(n):
|
||||
if n == 0:
|
||||
return 1 # Cas de base
|
||||
else:
|
||||
return n * factorielle(n - 1) # Cas récursif
|
||||
```
|
||||
|
||||
Vérification :
|
||||
```
|
||||
factorielle(4) = 4 × factorielle(3)
|
||||
= 4 × 3 × factorielle(2)
|
||||
= 4 × 3 × 2 × factorielle(1)
|
||||
= 4 × 3 × 2 × 1 × factorielle(0)
|
||||
= 4 × 3 × 2 × 1 × 1
|
||||
= 24
|
||||
```
|
||||
|
||||
-----------
|
||||
|
||||
### Récursif vs Itératif
|
||||
|
||||
Toute fonction récursive peut être réécrite de manière **itérative** (avec des boucles), et inversement.
|
||||
|
||||
#### Comparaison sur l'exemple de la somme
|
||||
|
||||
**Version récursive :**
|
||||
```python
|
||||
def somme_recursive(n):
|
||||
if n == 0:
|
||||
return 0
|
||||
else:
|
||||
return n + somme_recursive(n - 1)
|
||||
```
|
||||
|
||||
**Version itérative :**
|
||||
```python
|
||||
def somme_iterative(n):
|
||||
resultat = 0
|
||||
for i in range(1, n + 1):
|
||||
resultat += i
|
||||
return resultat
|
||||
```
|
||||
|
||||
#### Avantages et inconvénients
|
||||
|
||||
| Critère | Récursif | Itératif |
|
||||
|---------|----------|----------|
|
||||
| **Lisibilité** | Souvent plus élégant et proche de la définition mathématique | Peut être plus verbeux |
|
||||
| **Mémoire** | Utilise la pile d'appels (risque de débordement) | Utilise peu de mémoire |
|
||||
| **Performance** | Peut être plus lent (overhead des appels) | Généralement plus rapide |
|
||||
| **Cas d'usage** | Structures récursives (arbres, graphes), diviser pour régner | Calculs simples, itérations |
|
||||
|
||||
> En pratique, on choisit la récursivité quand elle rend le code **plus clair** ou quand le problème est **naturellement récursif** (parcours d'arbres, fractales, etc.).
|
||||
|
||||
-----------
|
||||
|
||||
### Autres types de récursivité
|
||||
|
||||
Il existe divers types de récursivité :
|
||||
|
||||
- La **récursivité simple** : un seul appel récursif (comme `somme`)
|
||||
- La **récursivité multiple** : plusieurs appels récursifs dans la fonction
|
||||
- La **récursivité mutuelle** : deux fonctions qui s'appellent mutuellement
|
||||
- La **récursivité terminale** : l'appel récursif est la dernière opération
|
||||
|
||||
Ces différents types de récursivité sont quelque peu différents de ce que l'on vient de voir. Mais nous pourrions les rencontrer dans la suite du programme.
|
||||
|
||||
### Récursivité multiple : la suite de Fibonacci
|
||||
|
||||
À la différence de la récursivité dite **simple**, il y aura ici **plusieurs appels de fonctions** dans une même instruction.
|
||||
|
||||
> En mathématiques, la suite de Fibonacci est une suite de nombres entiers dont chaque terme successif représente la somme des deux termes précédents, et qui commence par 0 puis 1. Ainsi, les dix premiers termes qui la composent sont 0, 1, 1, 2, 3, 5, 8, 13, 21 et 34.
|
||||
|
||||
$$
|
||||
fib(n) = \begin{cases}
|
||||
0 & \text{si } n = 0\\
|
||||
1 & \text{si } n = 1\\
|
||||
fib(n-1) + fib(n-2) & \text{sinon}
|
||||
\end{cases}
|
||||
$$
|
||||
|
||||
```python
|
||||
def fibonacci(n):
|
||||
if n == 0 :
|
||||
if n == 0:
|
||||
return 0
|
||||
elif n == 1 :
|
||||
elif n == 1:
|
||||
return 1
|
||||
else :
|
||||
return fibonnaci(n-1) + fibonnaci(n-2)
|
||||
else:
|
||||
return fibonacci(n-1) + fibonacci(n-2)
|
||||
```
|
||||
|
||||
#### Arbre des appels pour fibonacci(4)
|
||||
|
||||
```
|
||||
fibonacci(4)
|
||||
/ \
|
||||
fibonacci(3) fibonacci(2)
|
||||
/ \ / \
|
||||
fibonacci(2) fibonacci(1) fibonacci(1) fibonacci(0)
|
||||
/ \ | | |
|
||||
fibonacci(1) fibonacci(0) 1 1 0
|
||||
| |
|
||||
1 0
|
||||
```
|
||||
|
||||
On remarque que `fibonacci(2)` est calculé **deux fois**, et `fibonacci(1)` **trois fois**. Cette redondance rend l'algorithme très inefficace pour de grandes valeurs de `n`.
|
||||
|
||||
> Ce problème sera résolu grâce à la **programmation dynamique**, que nous verrons dans un prochain chapitre.
|
||||
|
||||
-----------------
|
||||
|
||||
### À retenir
|
||||
|
||||
- Une fonction **récursive** s'appelle elle-même
|
||||
- Elle doit avoir un **cas de base** pour s'arrêter
|
||||
- On prouve la **terminaison** avec un **variant** (quantité qui décroît)
|
||||
- Les appels s'empilent dans la **pile d'appels**
|
||||
- Python limite le nombre d'appels récursifs (~1000)
|
||||
- Récursif ≠ toujours meilleur : choisir selon le problème
|
||||
|
||||
-----------------
|
||||
|
||||
Auteurs : Florian Mathieu, Timothée Decoster, Enzo Frémeaux
|
||||
|
||||
Licence CC BY NC
|
||||
|
||||
<a rel="license" href="http://creativecommons.org/licenses/by-nc-sa/4.0/"><img alt="Licence Creative Commons" style="border-width:0" src="https://i.creativecommons.org/l/by-nc-sa/4.0/88x31.png" /></a> <br />Ce cours est mis à disposition selon les termes de la <a rel="license" href="http://creativecommons.org/licenses/by-nc-sa/4.0/">Licence Creative Commons Attribution - Pas d’Utilisation Commerciale - Partage dans les Mêmes Conditions 4.0 International</a>.
|
||||
<a rel="license" href="http://creativecommons.org/licenses/by-nc-sa/4.0/"><img alt="Licence Creative Commons" style="border-width:0" src="https://i.creativecommons.org/l/by-nc-sa/4.0/88x31.png" /></a> <br />Ce cours est mis à disposition selon les termes de la <a rel="license" href="http://creativecommons.org/licenses/by-nc-sa/4.0/">Licence Creative Commons Attribution - Pas d'Utilisation Commerciale - Partage dans les Mêmes Conditions 4.0 International</a>.
|
||||
|
||||
@@ -42,7 +42,7 @@ def somme(n) :
|
||||
def mystere(i,k):
|
||||
if i<=k :
|
||||
print(i)
|
||||
mystère(i+1,k)
|
||||
mystere(i+1,k)
|
||||
```
|
||||
|
||||
### 2. 2. Nombre de chiffre d'un nombre :
|
||||
|
||||
24
Recursivité/TP/Recherche_dicho.py
Normal file
24
Recursivité/TP/Recherche_dicho.py
Normal file
@@ -0,0 +1,24 @@
|
||||
def recherche_dichotomique(t, v):
|
||||
debut = 0
|
||||
fin = len(t)-1
|
||||
while debut <= fin :
|
||||
milieu = (debut + fin) // 2
|
||||
print(milieu,debut,fin)
|
||||
if t[milieu] == v :
|
||||
return True
|
||||
else:
|
||||
if t[milieu] > v :
|
||||
fin = milieu - 1
|
||||
else :
|
||||
debut = milieu + 1
|
||||
return False
|
||||
|
||||
def recherche_recur(t,v):
|
||||
if len(t) == 1:
|
||||
return t[0] == v
|
||||
else :
|
||||
milieu = len(t)//2
|
||||
if t[milieu] > v :
|
||||
return recherche_recur(t[:milieu],v)
|
||||
else :
|
||||
return recherche_recur(t[milieu:],v)
|
||||
29
Recursivité/TP/TP.md
Normal file
29
Recursivité/TP/TP.md
Normal file
@@ -0,0 +1,29 @@
|
||||
## Activité : La récursivité dans les jeux vidéo
|
||||
|
||||
### Contexte :
|
||||
Imaginez un jeu vidéo populaire où le héros doit traverser différents niveaux pour sauver un personnage captif. Chaque niveau est plus difficile que le précédent, et chaque niveau contient des mini-boss qu'il faut vaincre avant de passer au suivant.
|
||||
|
||||
### Objectif de l'activité :
|
||||
Utiliser la récursivité pour simuler le parcours du héros à travers les niveaux du jeu.
|
||||
|
||||
### Instructions :
|
||||
|
||||
### Présentation du problème :
|
||||
- Le héros commence au niveau 1 et doit atteindre le niveau `n`.
|
||||
- À chaque niveau, il y a un certain nombre de mini-boss à vaincre avant de passer au niveau suivant.
|
||||
- Si le héros vainc tous les mini-boss d'un niveau, il passe au niveau suivant, sinon il recommence le même niveau.
|
||||
|
||||
### Modélisation en pseudo-code :
|
||||
Écrire une fonction récursive `traverse_levels` qui prend en entrée le niveau actuel et le nombre total de niveaux.
|
||||
|
||||
- Si le niveau actuel est supérieur au nombre total de niveaux, le héros a gagné.
|
||||
- Sinon, le héros combat les mini-boss et passe au niveau suivant.
|
||||
|
||||
### 3. Exemple de code en Python
|
||||
```python
|
||||
def combat_mini_bosses(level):
|
||||
pass
|
||||
|
||||
def traverse_levels(current_level, total_levels):
|
||||
pass
|
||||
```
|
||||
349
Recursivité/TP/TP_Recursivite.ipynb
Normal file
349
Recursivité/TP/TP_Recursivite.ipynb
Normal file
@@ -0,0 +1,349 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"id": "66904fb8",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"# TP : La Récursivité et le Diviser pour Régner\n",
|
||||
"\n",
|
||||
"## Objectifs :\n",
|
||||
"- Comprendre le principe de la récursivité.\n",
|
||||
"- Appliquer la récursivité pour résoudre des problèmes simples.\n",
|
||||
"- Approfondir la méthode du **diviser pour régner** à travers des exemples concrets.\n",
|
||||
"- Compléter un algorithme de **tri fusion**.\n",
|
||||
"\n",
|
||||
"### Rappel sur la récursivité :\n",
|
||||
"La récursivité est une méthode où une fonction s'appelle elle-même pour résoudre un problème. Chaque appel de la fonction permet de simplifier le problème jusqu'à atteindre une condition de base (appelée **cas de base**) qui permet de terminer la récursion.\n",
|
||||
"\n",
|
||||
"**Exemple classique :** Calcul de la factorielle d'un nombre entier positif `n`.\n",
|
||||
"```python\n",
|
||||
"def factorielle(n):\n",
|
||||
" if n == 0:\n",
|
||||
" return 1 # Cas de base\n",
|
||||
" else:\n",
|
||||
" return n * factorielle(n-1) # Appel récursif\n",
|
||||
"```"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"id": "bb057eb6",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"### Exercice 1 : Fonction récursive `traduire_romain`\n",
|
||||
"**But :** É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.\n",
|
||||
"\n",
|
||||
"**Consignes :**\n",
|
||||
"- Chaque chiffre romain a une valeur : `I=1, V=5, X=10, L=50, C=100, D=500, M=1000`.\n",
|
||||
"- Si un chiffre plus petit précède un chiffre plus grand (ex : IV), cela signifie qu'il faut soustraire la valeur du chiffre plus petit.\n",
|
||||
" \n",
|
||||
"**Exemple :**\n",
|
||||
"```python\n",
|
||||
"traduire_romain(\"IX\") # Renvoie 9\n",
|
||||
"traduire_romain(\"MCMXCIV\") # Renvoie 1994\n",
|
||||
"```\n",
|
||||
"\n",
|
||||
"**Indication :** Utilisez la récursion pour traiter un caractère à la fois, et soustrayez ou ajoutez en fonction de la position relative des caractères.\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 7,
|
||||
"id": "ff49f2f3",
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"None\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"def traduire_romain(chaine):\n",
|
||||
" pass\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"print(traduire_romain(\"IX\")) # Doit afficher 9\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"id": "1aedbf03",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"### Exercice 2 : Compléter un Tri Fusion\n",
|
||||
"**But :** Compléter l'algorithme du tri fusion.\n",
|
||||
"\n",
|
||||
"Le tri fusion est un exemple typique de la méthode de **diviser pour régner**. L'idée est de diviser le tableau en deux, de trier chaque moitié, puis de fusionner les deux moitiés triées.\n",
|
||||
"\n",
|
||||
"Voici un code partiellement écrit que vous devez compléter :\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 8,
|
||||
"id": "31d950ac",
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"[38, 27, 43, 3, 9, 82, 10]\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"def tri_fusion(tab):\n",
|
||||
" if len(tab) <= 1:\n",
|
||||
" return tab # Cas de base\n",
|
||||
" milieu = len(tab) // 2\n",
|
||||
" gauche = tri_fusion(tab[:milieu]) # Appel récursif\n",
|
||||
" droite = tri_fusion(tab[milieu:]) # Appel récursif\n",
|
||||
" return fusionner(gauche, droite)\n",
|
||||
"\n",
|
||||
"def fusionner(gauche, droite):\n",
|
||||
" tableau_fusionne = []\n",
|
||||
" i, j = 0, 0\n",
|
||||
" # Complétez la fonction pour fusionner les deux sous-tableaux ici :\n",
|
||||
" # ---------------------------------------------\n",
|
||||
"\n",
|
||||
" # ---------------------------------------------\n",
|
||||
" # Ajoutez ici les éléments restants des sous-tableaux\n",
|
||||
" tableau_fusionne += gauche[i:]\n",
|
||||
" tableau_fusionne += droite[j:]\n",
|
||||
" return tableau_fusionne\n",
|
||||
"\n",
|
||||
"# Test de la fonction tri_fusion\n",
|
||||
"print(tri_fusion([38, 27, 43, 3, 9, 82, 10])) # Doit afficher une liste triée\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"id": "15791934",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"### Exercice 3 : Diviser pour Régner — Recherche d'un élément dans un tableau\n",
|
||||
"**But :** Implémenter la recherche d'un élément dans un tableau trié en utilisant la méthode de **diviser pour régner** (recherche dichotomique).\n",
|
||||
"\n",
|
||||
"La recherche dichotomique consiste à diviser le tableau en deux parties à chaque étape :\n",
|
||||
"- Si l'élément recherché est au milieu, vous avez terminé.\n",
|
||||
"- Si l'élément est plus petit que l'élément du milieu, il se trouve dans la première moitié du tableau.\n",
|
||||
"- Sinon, il se trouve dans la deuxième moitié.\n",
|
||||
"\n",
|
||||
"Voici un squelette à compléter :\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 9,
|
||||
"id": "ab9509b5",
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"None\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"def recherche_dichotomique(tab, element, debut=0, fin=None):\n",
|
||||
" if fin is None:\n",
|
||||
" fin = len(tab) - 1\n",
|
||||
" if debut > fin:\n",
|
||||
" return -1 # L'élément n'est pas dans le tableau\n",
|
||||
" milieu = (debut + fin) // 2\n",
|
||||
" if tab[milieu] == element:\n",
|
||||
" return # L'élément est trouvé\n",
|
||||
" # Complétez ici avec les appels récursifs manquants :\n",
|
||||
" # --------------------------------------------------\n",
|
||||
" \n",
|
||||
" # --------------------------------------------------\n",
|
||||
" \n",
|
||||
"# Test de la fonction\n",
|
||||
"tab = [3, 9, 10, 27, 38, 43, 82]\n",
|
||||
"element = 27\n",
|
||||
"print(recherche_dichotomique(tab, element)) # Doit afficher l'index de l'élément trouvé\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"id": "99671e3b",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"### Exercice 4 : \n",
|
||||
"\n",
|
||||
"On considère des tableaux de nombres dont tous les éléments sont présents\n",
|
||||
"exactement trois fois à la suite, sauf un élément qui est présent une unique fois et\n",
|
||||
"que l'on appelle « l'intrus ». \n",
|
||||
"\n",
|
||||
"\n",
|
||||
"Voici quelques exemples :\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 10,
|
||||
"id": "f7a2fa7d",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"tab_a = [3, 3, 3, 9, 9, 9, 1, 1, 1, 7, 2, 2, 2, 4, 4, 4, 8, 8, 8, 5,\n",
|
||||
"5, 5]\n",
|
||||
"#l'intrus est 7\n",
|
||||
"tab_b = [8, 5, 5, 5, 9, 9, 9, 18, 18, 18, 3, 3, 3]\n",
|
||||
"#l'intrus est 8\n",
|
||||
"tab_c = [5, 5, 5, 1, 1, 1, 0, 0, 0, 6, 6, 6, 3, 8, 8, 8]\n",
|
||||
"#l'intrus est 3"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"id": "f693789b",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"On remarque qu'avec de tels tableaux : \n",
|
||||
"\n",
|
||||
"\n",
|
||||
" pour les indices multiples de 3 situés strictement avant l'intrus, l'élément\n",
|
||||
"correspondant et son voisin de droite sont égaux,\n",
|
||||
"\n",
|
||||
"\n",
|
||||
" pour les indices multiples de 3 situés après l'intrus, l'élément correspondant et\n",
|
||||
"son voisin de droite - s'il existe - sont différents.\n",
|
||||
"\n",
|
||||
"Ce que l'on peut observer ci-dessous en observant les valeurs des paires de voisins\n",
|
||||
"marquées par des caractères ^"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"id": "b0549a7c",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"[3, 3, 3, 9, 9, 9, 1, 1, 1, 7, 2, 2, 2, 4, 4, 4, 8, 8, 8, 5, 5, 5]\n",
|
||||
"^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^\n",
|
||||
"0 3 6 9 12 15 18 21 "
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"id": "fbb578a8",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Dans des listes comme celles ci-dessus, un algorithme récursif pour trouver l'intrus\n",
|
||||
"consiste alors à choisir un indice i multiple de 3 situé approximativement au milieu\n",
|
||||
"des indices parmi lesquels se trouve l'intrus.\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"Puis, en fonction des valeurs de l'élément d'indice i et de son voisin de droite, à\n",
|
||||
"appliquer récursivement l'algorithme à la moitié droite ou à la moitié gauche des\n",
|
||||
"indices parmi lesquels se trouve l'intrus."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"id": "b0603315",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Par exemple, si on s’intéresse à l’indice 12, on voit les valeurs 2 et 4 qui sont\n",
|
||||
"différentes : l’intrus est donc à gauche de l’indice 12 (indice 12 compris)\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"En revanche, si on s’intéresse à l’indice 3, on voit les valeurs 9 et 9 qui sont\n",
|
||||
"identiques : l’intrus est donc à droite des indices 3-4-5, donc à partir de l’indice 6."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"id": "bb44af36",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Compléter la fonction récursive **trouver_intrus** proposée page suivante qui met\n",
|
||||
"en œuvre cet algorithme."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 11,
|
||||
"id": "887c8914",
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"ename": "SyntaxError",
|
||||
"evalue": "invalid character '–' (U+2013) (617363500.py, line 9)",
|
||||
"output_type": "error",
|
||||
"traceback": [
|
||||
"\u001b[0;36m Cell \u001b[0;32mIn[11], line 9\u001b[0;36m\u001b[0m\n\u001b[0;31m nombre_de_triplets = (d – g) // ...\u001b[0m\n\u001b[0m ^\u001b[0m\n\u001b[0;31mSyntaxError\u001b[0m\u001b[0;31m:\u001b[0m invalid character '–' (U+2013)\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"def trouver_intrus(tab, g, d):\n",
|
||||
" \n",
|
||||
" '''Renvoie la valeur de l'intrus situé entre les indices g et d dans la liste tab où :\n",
|
||||
" tab vérifie les conditions de l'exercice, g et d sont des multiples de 3.\n",
|
||||
" '''\n",
|
||||
" if g == d:\n",
|
||||
" return ...\n",
|
||||
" else:\n",
|
||||
" nombre_de_triplets = (d – g) // ...\n",
|
||||
" indice = g + 3 * (nombre_de_triplets // 2)\n",
|
||||
" if ... :\n",
|
||||
" return ...\n",
|
||||
" else:\n",
|
||||
" return ..."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"id": "679501d0",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Exemples :"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"id": "d06a36b2",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
">>> trouver_intrus([3, 3, 3, 9, 9, 9, 1, 1, 1, 7, 2, 2, 2, 4,\n",
|
||||
"4, 4, 8, 8, 8, 5, 5, 5], 0, 21)\n",
|
||||
"7\n",
|
||||
">>> trouver_intrus([8, 5, 5, 5, 9, 9, 9, 18, 18, 18, 3, 3, 3],\n",
|
||||
"0, 12)\n",
|
||||
"8\n",
|
||||
">>> trouver_intrus([5, 5, 5, 1, 1, 1, 0, 0, 0, 6, 6, 6, 3, 8,\n",
|
||||
"8, 8], 0, 15)\n",
|
||||
"3"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"kernelspec": {
|
||||
"display_name": "Python (myenv)",
|
||||
"language": "python",
|
||||
"name": "myenv"
|
||||
},
|
||||
"language_info": {
|
||||
"codemirror_mode": {
|
||||
"name": "ipython",
|
||||
"version": 3
|
||||
},
|
||||
"file_extension": ".py",
|
||||
"mimetype": "text/x-python",
|
||||
"name": "python",
|
||||
"nbconvert_exporter": "python",
|
||||
"pygments_lexer": "ipython3",
|
||||
"version": "3.12.4"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 5
|
||||
}
|
||||
103
Recursivité/TP/TP_recursivite.md
Normal file
103
Recursivité/TP/TP_recursivite.md
Normal file
@@ -0,0 +1,103 @@
|
||||
# TP Récursivité
|
||||
|
||||
------
|
||||
|
||||
## 1. Courbe de Koch
|
||||
|
||||
> Prérequis : Module turtle
|
||||
|
||||
La courbe de Koch est une figure fractale récursive. Elle fait partie des premières fractales décrites mathématiquement (1904).
|
||||
|
||||
### Principe de construction
|
||||
|
||||
**Ordre 0** : Un simple segment de longueur `cote`.
|
||||
|
||||
```
|
||||
─────────────────────
|
||||
```
|
||||
|
||||
**Ordre 1** : Le segment est divisé en 3 parties égales. La partie centrale est remplacée par deux segments formant un triangle équilatéral sans sa base (un "chapeau" ^).
|
||||
|
||||
```
|
||||
/\
|
||||
/ \
|
||||
──────/ \──────
|
||||
```
|
||||
|
||||
**Ordre 2 et suivants** : On applique la même transformation à chaque segment de la figure précédente.
|
||||
|
||||
```
|
||||
/\
|
||||
/ \ /\
|
||||
/ \ / \
|
||||
─/ \──/ \─
|
||||
```
|
||||
|
||||
### Questions
|
||||
|
||||
1. Écrire de manière récursive le code de la fonction `courbe_koch(n, cote)` permettant de dessiner cette courbe à l'ordre `n` avec des segments de longueur `cote`.
|
||||
|
||||
Nous voulons obtenir maintenant un **flocon de Koch**. Celui-ci est composé de trois courbes de Koch disposées en triangle équilatéral.
|
||||
|
||||
2. Écrire le code de la fonction `flocon(n, cote)` qui dessine le flocon de Koch.
|
||||
|
||||
> **Indice** : Le flocon est formé de 3 courbes de Koch, avec un angle de 120° entre chaque courbe.
|
||||
|
||||
---
|
||||
|
||||
## 2. Triangle de Pascal
|
||||
|
||||
Le triangle de Pascal représente les coefficients binomiaux sous la forme d'un triangle :
|
||||
|
||||
```
|
||||
1
|
||||
1 1
|
||||
1 2 1
|
||||
1 3 3 1
|
||||
1 4 6 4 1
|
||||
1 5 10 10 5 1
|
||||
```
|
||||
|
||||
La fonction `coef(n, p)` permet de calculer le coefficient à la ligne `n` et colonne `p` :
|
||||
|
||||
$$
|
||||
coef(n, p) = \begin{cases}
|
||||
1 & \text{si } p = 0 \text{ ou } n = p\\
|
||||
coef(n-1, p-1) + coef(n-1, p) & \text{sinon}
|
||||
\end{cases}
|
||||
$$
|
||||
|
||||
### Questions
|
||||
|
||||
1. Écrire le code de la fonction récursive `coef(n, p)`.
|
||||
|
||||
Le sommet du triangle est le résultat de `coef(0, 0)`, la première ligne est représentée par `coef(1, 0)` et `coef(1, 1)`, ainsi de suite pour les autres lignes.
|
||||
|
||||
2. À l'aide de deux boucles, écrire un code permettant d'afficher les 6 premières lignes du triangle.
|
||||
|
||||
---
|
||||
|
||||
## 3. Recherche dichotomique
|
||||
|
||||
La recherche dichotomique fonctionne sur un tableau trié et permet de trouver un élément de façon optimale en O(log n).
|
||||
|
||||
Voici le code de la recherche dichotomique (programme de 1ère) de manière itérative :
|
||||
|
||||
```python
|
||||
def recherche_dichotomique(t, v):
|
||||
debut = 0
|
||||
fin = len(t) - 1
|
||||
while debut <= fin:
|
||||
milieu = (debut + fin) // 2
|
||||
if t[milieu] == v:
|
||||
return True
|
||||
elif t[milieu] > v:
|
||||
fin = milieu - 1
|
||||
else:
|
||||
debut = milieu + 1
|
||||
return False
|
||||
```
|
||||
|
||||
### Question
|
||||
|
||||
1. Réécrire ce code en version récursive. La fonction prendra en paramètres le tableau `t`, la valeur cherchée `v`, ainsi que les indices `debut` et `fin`.
|
||||
27
Recursivité/TP/TP_recursivite.py
Normal file
27
Recursivité/TP/TP_recursivite.py
Normal file
@@ -0,0 +1,27 @@
|
||||
import turtle
|
||||
|
||||
def courbe_koch(n, l):
|
||||
if n == 0 :
|
||||
turtle.forward(l)
|
||||
else :
|
||||
courbe_koch(n-1, l/3)
|
||||
turtle.left(60)
|
||||
courbe_koch(n-1, l/3)
|
||||
turtle.left(-120)
|
||||
courbe_koch(n-1, l/3)
|
||||
turtle.left(60)
|
||||
courbe_koch(n-1, l/3)
|
||||
|
||||
def flocon(n,l,i=3):
|
||||
if i != 0:
|
||||
courbe_koch(n,l)
|
||||
turtle.left(-120)
|
||||
flocon(n,l,i-1)
|
||||
|
||||
turtle.setheading(0) # orientation intiale de la tête : vers la droite de l'écran
|
||||
#turtle.hideturtle() # on cache la tortue
|
||||
turtle.speed(0) # on accélère la tortue
|
||||
turtle.color('green')
|
||||
#flocon(1,300)
|
||||
#courbe_koch(,400)
|
||||
print(8)
|
||||
10
Recursivité/TP/Triangle_Pascal.py
Normal file
10
Recursivité/TP/Triangle_Pascal.py
Normal file
@@ -0,0 +1,10 @@
|
||||
def coef(n,p):
|
||||
if p==0 or n == p :
|
||||
return 1
|
||||
else :
|
||||
return coef(n-1,p-1) + coef(n-1,p)
|
||||
|
||||
for i in range(19):
|
||||
for j in range(i+1):
|
||||
print(coef(i,j),' ',end='')
|
||||
print()
|
||||
@@ -3,34 +3,7 @@
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"# Récursivité et Programmation Dynamique\n",
|
||||
"\n",
|
||||
"# La reproduction des lapins\n",
|
||||
"\n",
|
||||
"Nous allons utiliser 2 grandes méthodes de programmation que nous allons appliquer à un problème célèbre et récurrent dans le milieu de la programmation.\n",
|
||||
"\n",
|
||||
"En 1202, Leonardo Fibonacci publie un ouvrage dans lequel il traite d'un problème simple et concret : la croissance d'une population de lapins. Il s'agit de savoir comment contrôler la population des clapiers et quand vendre ses lapins, etc.\n",
|
||||
"\n",
|
||||
"Voici le fonctionnement simplifié de cette reproduction :\n",
|
||||
"\n",
|
||||
"1. On compte les lapins par **couple**\n",
|
||||
"2. **Chaque mois** chaque couple de lapins matures donne naissance à 1 couple de jeunes lapins immatures\n",
|
||||
"3. Après 2 mois les jeunes couples devienent matures et engendrent à leur tour un jeune couple immature\n",
|
||||
"4. On étudie la croissance de la population tous les mois : n est le nombre de mois\n",
|
||||
"\n",
|
||||
"| n | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |\n",
|
||||
"|:------------------------------:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:--:|:--:|:--:|:--:|\n",
|
||||
"| nb couples matures | 0 | 0 | 0 | 1 | 1 | 2 | 3 | 5 | 8 | 13 | 21 |\n",
|
||||
"| nb couples immatures 1er mois | 0 | 1 | 0 | 1 | 1 | 2 | 3 | 5 | 8 | 13 | 21 |\n",
|
||||
"| nb couples immatures 2ème mois | 0 | 0 | 1 | 0 | 1 | 1 | 2 | 3 | 5 | 8 | 13 |\n",
|
||||
"| nb couples | 0 | 1 | 1 | 2 | 3 | 5 | 8 | 13 | 21 | 34 | 55 |\n",
|
||||
"\n",
|
||||
"- Complétez les mois manquants en respectant les règles de reproduction.\n",
|
||||
"\n",
|
||||
"- En vous inspirant de la méthode que vous avez employée pour compléter le tableau ci-dessus, écrivez une fonction `lapinoux(n)` qui retourne le nombre de couples de lapin obtenus au mois n.\n",
|
||||
"- Testez votre fonction pour des valeurs de n entre 0 et 10."
|
||||
]
|
||||
"source": "# Récursivité et Programmation Dynamique\n\n# La reproduction des lapins\n\nNous allons utiliser 2 grandes méthodes de programmation que nous allons appliquer à un problème célèbre et récurrent dans le milieu de la programmation.\n\nEn 1202, Leonardo Fibonacci publie un ouvrage dans lequel il traite d'un problème simple et concret : la croissance d'une population de lapins. Il s'agit de savoir comment contrôler la population des clapiers et quand vendre ses lapins, etc.\n\nVoici le fonctionnement simplifié de cette reproduction :\n\n1. On compte les lapins par **couple**\n2. **Chaque mois** chaque couple de lapins matures donne naissance à 1 couple de jeunes lapins immatures\n3. Après 2 mois les jeunes couples deviennent matures et engendrent à leur tour un jeune couple immature\n4. On étudie la croissance de la population tous les mois : n est le nombre de mois\n\n| n | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |\n|:------------------------------:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:--:|:--:|:--:|:--:|\n| nb couples matures | 0 | 0 | 0 | 1 | 1 | 2 | 3 | 5 | 8 | 13 | 21 |\n| nb couples immatures 1er mois | 0 | 1 | 0 | 1 | 1 | 2 | 3 | 5 | 8 | 13 | 21 |\n| nb couples immatures 2ème mois | 0 | 0 | 1 | 0 | 1 | 1 | 2 | 3 | 5 | 8 | 13 |\n| nb couples | 0 | 1 | 1 | 2 | 3 | 5 | 8 | 13 | 21 | 34 | 55 |\n\n- Complétez les mois manquants en respectant les règles de reproduction.\n\n- En vous inspirant de la méthode que vous avez employée pour compléter le tableau ci-dessus, écrivez une fonction `lapinoux(n)` qui retourne le nombre de couples de lapin obtenus au mois n.\n- Testez votre fonction pour des valeurs de n entre 0 et 10."
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
@@ -7780,4 +7753,4 @@
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 2
|
||||
}
|
||||
}
|
||||
@@ -3,34 +3,7 @@
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"# Récursivité et Programmation Dynamique\n",
|
||||
"\n",
|
||||
"# La reproduction des lapins\n",
|
||||
"\n",
|
||||
"Nous allons utiliser 2 grandes méthodes de programmation que nous allons appliquer à un problème célèbre et récurrent dans le milieu de la programmation.\n",
|
||||
"\n",
|
||||
"En 1202, Leonardo Fibonacci publie un ouvrage dans lequel il traite d'un problème simple et concret : la croissance d'une population de lapins. Il s'agit de savoir comment contrôler la population des clapiers et quand vendre ses lapins, etc.\n",
|
||||
"\n",
|
||||
"Voici le fonctionnement simplifié de cette reproduction :\n",
|
||||
"\n",
|
||||
"1. On compte les lapins par **couple**\n",
|
||||
"2. **Chaque mois** chaque couple de lapins matures donne naissance à 1 couple de jeunes lapins immatures\n",
|
||||
"3. Après 2 mois les jeunes couples devienent matures et engendrent à leur tour un jeune couple immature\n",
|
||||
"4. On étudie la croissance de la population tous les mois : n est le nombre de mois\n",
|
||||
"\n",
|
||||
"| n | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |\n",
|
||||
"|:------------------------------:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:--:|:--:|:--:|:--:|\n",
|
||||
"| nb couples matures | 0 | 0 | 0 | 1 | | | | | | | |\n",
|
||||
"| nb couples immatures 1er mois | 0 | 1 | 0 | 1 | | | | | | | |\n",
|
||||
"| nb couples immatures 2ème mois | 0 | 0 | 1 | 0 | | | | | | | |\n",
|
||||
"| nb couples | 0 | 1 | 1 | 2 | | | | | | | |\n",
|
||||
"\n",
|
||||
"- Complétez les mois manquants en respectant les règles de reproduction.\n",
|
||||
"\n",
|
||||
"- En vous inspirant de la méthode que vous avez employée pour compléter le tableau ci-dessus, écrivez une fonction `lapinoux(n)` qui retourne le nombre de couples de lapin obtenus au mois n.\n",
|
||||
"- Testez votre fonction pour des valeurs de n entre 0 et 10."
|
||||
]
|
||||
"source": "# Récursivité et Programmation Dynamique\n\n# La reproduction des lapins\n\nNous allons utiliser 2 grandes méthodes de programmation que nous allons appliquer à un problème célèbre et récurrent dans le milieu de la programmation.\n\nEn 1202, Leonardo Fibonacci publie un ouvrage dans lequel il traite d'un problème simple et concret : la croissance d'une population de lapins. Il s'agit de savoir comment contrôler la population des clapiers et quand vendre ses lapins, etc.\n\nVoici le fonctionnement simplifié de cette reproduction :\n\n1. On compte les lapins par **couple**\n2. **Chaque mois** chaque couple de lapins matures donne naissance à 1 couple de jeunes lapins immatures\n3. Après 2 mois les jeunes couples deviennent matures et engendrent à leur tour un jeune couple immature\n4. On étudie la croissance de la population tous les mois : n est le nombre de mois\n\n| n | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |\n|:------------------------------:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:--:|:--:|:--:|:--:|\n| nb couples matures | 0 | 0 | 0 | 1 | | | | | | | |\n| nb couples immatures 1er mois | 0 | 1 | 0 | 1 | | | | | | | |\n| nb couples immatures 2ème mois | 0 | 0 | 1 | 0 | | | | | | | |\n| nb couples | 0 | 1 | 1 | 2 | | | | | | | |\n\n- Complétez les mois manquants en respectant les règles de reproduction.\n\n- En vous inspirant de la méthode que vous avez employée pour compléter le tableau ci-dessus, écrivez une fonction `lapinoux(n)` qui retourne le nombre de couples de lapin obtenus au mois n.\n- Testez votre fonction pour des valeurs de n entre 0 et 10."
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
@@ -6662,4 +6635,4 @@
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 2
|
||||
}
|
||||
}
|
||||
15
Recursivité/sources/combinaisons.py
Normal file
15
Recursivité/sources/combinaisons.py
Normal file
@@ -0,0 +1,15 @@
|
||||
def combinaisons(n,p):
|
||||
result = 1
|
||||
if n>p and p>0:
|
||||
result = combinaisons(n-1,p-1) + combinaisons(n-1,p)
|
||||
return result
|
||||
|
||||
print(combinaisons(32,5))
|
||||
|
||||
def combinaisons2(n,p):
|
||||
if n>p and p>0:
|
||||
return combinaisons(n-1,p-1) + combinaisons(n-1,p)
|
||||
else:
|
||||
return 1
|
||||
|
||||
print(combinaisons2(32,5))
|
||||
31
Recursivité/sources/escalier.py
Normal file
31
Recursivité/sources/escalier.py
Normal file
@@ -0,0 +1,31 @@
|
||||
from functools import lru_cache
|
||||
from functools import cache
|
||||
|
||||
@cache
|
||||
def steps_to(stair):
|
||||
if stair == 1:
|
||||
# You can reach the first stair with only a single step from the floor.
|
||||
return 1
|
||||
|
||||
elif stair == 2:
|
||||
# You can reach the second stair by jumping from the floor with a single two-stair hop or by jumping a single stair a couple of times.
|
||||
return 2
|
||||
|
||||
elif stair == 3:
|
||||
# You can reach the third stair using four possible combinations:
|
||||
# 1. Jumping all the way from the floor
|
||||
# 2. Jumping two stairs, then one
|
||||
# 3. Jumping one stair, then two
|
||||
# 4. Jumping one stair three times
|
||||
return 4
|
||||
|
||||
else:
|
||||
# You can reach your current stair from three different places:
|
||||
# 1. From three stairs down
|
||||
# 2. From two stairs down
|
||||
# 2. From one stair down
|
||||
# If you add up the number of ways of getting to those
|
||||
# those three positions, then you should have your solution.
|
||||
return steps_to(stair - 3) + steps_to(stair - 2) + steps_to(stair - 1)
|
||||
|
||||
print(steps_to(35))
|
||||
30
Recursivité/sources/fib5.dot
Normal file
30
Recursivité/sources/fib5.dot
Normal file
@@ -0,0 +1,30 @@
|
||||
digraph Fibonnacci {
|
||||
#bgcolor="transparent"
|
||||
"fib(6)" -> {fib4 [label="fib(4)"] fib5 [label="fib(5)"]}
|
||||
|
||||
subgraph cluster1 {
|
||||
style="rounded,dashed";
|
||||
fib4 -> {fib2 [label="fib(2)"] fib3 [label="fib(3)"]}
|
||||
subgraph cluster1 {
|
||||
style="rounded,dotted";
|
||||
fib3 -> {fib1 [label="fib(1)"] fib22 [label="fib(2)"]}
|
||||
}
|
||||
}
|
||||
|
||||
fib5 -> {fib33 [label="fib(3)"] fib44 [label="fib(4)"]};
|
||||
|
||||
subgraph cluster2 {
|
||||
style="rounded,dotted";
|
||||
fib33 -> {fib11 [label="fib(1)"] fib222 [label="fib(2)"]};
|
||||
}
|
||||
|
||||
subgraph cluster3 {
|
||||
style="rounded,dashed";
|
||||
fib44 -> {fib2222 [label="fib(2)"] fib333 [label="fib(3)"]}
|
||||
subgraph cluster4 {
|
||||
style="rounded,dotted";
|
||||
fib333 -> {fib111 [label="fib(1)"] fib22222 [label="fib(2)"]}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
41
Recursivité/sources/lumiere.py
Normal file
41
Recursivité/sources/lumiere.py
Normal file
@@ -0,0 +1,41 @@
|
||||
from random import randint
|
||||
|
||||
nb_interrupteurs = 10
|
||||
etats_interrupteurs = [_%2==1 for _ in range(nb_interrupteurs)]
|
||||
etats_interrupteurs = [False for _ in range(nb_interrupteurs)]
|
||||
etats_interrupteurs = [randint(0,1)==0 for _ in range(nb_interrupteurs)]
|
||||
|
||||
commutations = []
|
||||
|
||||
print(etats_interrupteurs)
|
||||
|
||||
def inverse_interrupteur(n: int):
|
||||
global etats_interrupteurs
|
||||
global commutations
|
||||
#print("On inverse l'interrupteur", n)
|
||||
commutations.append(n)
|
||||
etats_interrupteurs[n-1] = not etats_interrupteurs[n-1]
|
||||
|
||||
def islight() -> bool:
|
||||
global etats_interrupteurs
|
||||
result = True
|
||||
for etat_interrupteur in etats_interrupteurs:
|
||||
if not etat_interrupteur:
|
||||
result = False
|
||||
break
|
||||
return result
|
||||
|
||||
def cherche_commutations(n):
|
||||
#print("commute", n)
|
||||
if n == 1 and not islight():
|
||||
inverse_interrupteur(n)
|
||||
elif n > 1 and not islight():
|
||||
cherche_commutations(n-1)
|
||||
if not islight():
|
||||
inverse_interrupteur(n)
|
||||
if not islight():
|
||||
cherche_commutations(n-1)
|
||||
|
||||
cherche_commutations(nb_interrupteurs)
|
||||
print(etats_interrupteurs)
|
||||
print(len(commutations))
|
||||
38
Recursivité/sources/mult_egypt.py
Normal file
38
Recursivité/sources/mult_egypt.py
Normal file
@@ -0,0 +1,38 @@
|
||||
def multiplication_egyptienne(n: int, m: int) -> int:
|
||||
assert n>=1 and m>=1
|
||||
result = m
|
||||
if n > 1:
|
||||
if n % 2 == 0:
|
||||
result = multiplication_egyptienne(n//2, m*2)
|
||||
else:
|
||||
result = m + multiplication_egyptienne(n-1, m)
|
||||
return result
|
||||
|
||||
print(multiplication_egyptienne(7,5))
|
||||
|
||||
def multiplication_egyptienne2(n: int, m: int) -> int:
|
||||
assert n>=1 and m>=1
|
||||
if n == 1:
|
||||
return m
|
||||
elif n % 2 == 0:
|
||||
return multiplication_egyptienne(n//2, m*2)
|
||||
else:
|
||||
return m + multiplication_egyptienne(n-1, m)
|
||||
|
||||
print(multiplication_egyptienne2(7,5))
|
||||
|
||||
def multiplication_egyptienne_iterative(n: int, m: int) -> int:
|
||||
assert n > m
|
||||
assert n>=1 and m>=1
|
||||
result = 0
|
||||
while n > 1:
|
||||
if n % 2 != 0:
|
||||
result += m
|
||||
n = n-1
|
||||
else :
|
||||
n = n//2
|
||||
m = m*2
|
||||
result += m
|
||||
return result
|
||||
|
||||
print(multiplication_egyptienne_iterative(7,5))
|
||||
1324
Recursivité/sources/nsi_tle_02_02_exos_recursivite_correction.md
Normal file
1324
Recursivité/sources/nsi_tle_02_02_exos_recursivite_correction.md
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
207
Recursivité/sources/out.svg
Normal file
207
Recursivité/sources/out.svg
Normal file
@@ -0,0 +1,207 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
|
||||
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<!-- Generated by graphviz version 2.44.0 (0)
|
||||
-->
|
||||
<!-- Title: Fibonnacci Pages: 1 -->
|
||||
<svg width="683pt" height="356pt"
|
||||
viewBox="0.00 0.00 683.00 356.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 352)">
|
||||
<title>Fibonnacci</title>
|
||||
<polygon fill="white" stroke="transparent" points="-4,4 -4,-352 679,-352 679,4 -4,4"/>
|
||||
<g id="clust2" class="cluster">
|
||||
<title>cluster1</title>
|
||||
<path fill="none" stroke="black" stroke-dasharray="5,2" d="M20,-80C20,-80 239,-80 239,-80 245,-80 251,-86 251,-92 251,-92 251,-272 251,-272 251,-278 245,-284 239,-284 239,-284 20,-284 20,-284 14,-284 8,-278 8,-272 8,-272 8,-92 8,-92 8,-86 14,-80 20,-80"/>
|
||||
</g>
|
||||
<g id="clust4" class="cluster">
|
||||
<title>cluster1</title>
|
||||
<path fill="none" stroke="black" stroke-dasharray="1,5" d="M98,-88C98,-88 231,-88 231,-88 237,-88 243,-94 243,-100 243,-100 243,-200 243,-200 243,-206 237,-212 231,-212 231,-212 98,-212 98,-212 92,-212 86,-206 86,-200 86,-200 86,-100 86,-100 86,-94 92,-88 98,-88"/>
|
||||
</g>
|
||||
<g id="clust7" class="cluster">
|
||||
<title>cluster2</title>
|
||||
<path fill="none" stroke="black" stroke-dasharray="1,5" d="M271,-88C271,-88 404,-88 404,-88 410,-88 416,-94 416,-100 416,-100 416,-200 416,-200 416,-206 410,-212 404,-212 404,-212 271,-212 271,-212 265,-212 259,-206 259,-200 259,-200 259,-100 259,-100 259,-94 265,-88 271,-88"/>
|
||||
</g>
|
||||
<g id="clust9" class="cluster">
|
||||
<title>cluster3</title>
|
||||
<path fill="none" stroke="black" stroke-dasharray="5,2" d="M436,-8C436,-8 655,-8 655,-8 661,-8 667,-14 667,-20 667,-20 667,-200 667,-200 667,-206 661,-212 655,-212 655,-212 436,-212 436,-212 430,-212 424,-206 424,-200 424,-200 424,-20 424,-20 424,-14 430,-8 436,-8"/>
|
||||
</g>
|
||||
<g id="clust11" class="cluster">
|
||||
<title>cluster4</title>
|
||||
<path fill="none" stroke="black" stroke-dasharray="1,5" d="M514,-16C514,-16 647,-16 647,-16 653,-16 659,-22 659,-28 659,-28 659,-128 659,-128 659,-134 653,-140 647,-140 647,-140 514,-140 514,-140 508,-140 502,-134 502,-128 502,-128 502,-28 502,-28 502,-22 508,-16 514,-16"/>
|
||||
</g>
|
||||
<!-- fib(6) -->
|
||||
<g id="node1" class="node">
|
||||
<title>fib(6)</title>
|
||||
<ellipse fill="none" stroke="black" cx="231" cy="-330" rx="30.59" ry="18"/>
|
||||
<text text-anchor="middle" x="231" y="-326.3" font-family="Times,serif" font-size="14.00">fib(6)</text>
|
||||
</g>
|
||||
<!-- fib4 -->
|
||||
<g id="node2" class="node">
|
||||
<title>fib4</title>
|
||||
<ellipse fill="none" stroke="black" cx="165" cy="-258" rx="30.59" ry="18"/>
|
||||
<text text-anchor="middle" x="165" y="-254.3" font-family="Times,serif" font-size="14.00">fib(4)</text>
|
||||
</g>
|
||||
<!-- fib(6)->fib4 -->
|
||||
<g id="edge1" class="edge">
|
||||
<title>fib(6)->fib4</title>
|
||||
<path fill="none" stroke="black" d="M216.68,-313.81C207.77,-304.36 196.15,-292.04 186.19,-281.48"/>
|
||||
<polygon fill="black" stroke="black" points="188.7,-279.03 179.29,-274.16 183.61,-283.84 188.7,-279.03"/>
|
||||
</g>
|
||||
<!-- fib5 -->
|
||||
<g id="node3" class="node">
|
||||
<title>fib5</title>
|
||||
<ellipse fill="none" stroke="black" cx="337" cy="-258" rx="30.59" ry="18"/>
|
||||
<text text-anchor="middle" x="337" y="-254.3" font-family="Times,serif" font-size="14.00">fib(5)</text>
|
||||
</g>
|
||||
<!-- fib(6)->fib5 -->
|
||||
<g id="edge2" class="edge">
|
||||
<title>fib(6)->fib5</title>
|
||||
<path fill="none" stroke="black" d="M250.94,-315.83C267.33,-305.01 290.74,-289.55 309.01,-277.49"/>
|
||||
<polygon fill="black" stroke="black" points="311.09,-280.3 317.51,-271.87 307.24,-274.46 311.09,-280.3"/>
|
||||
</g>
|
||||
<!-- fib2 -->
|
||||
<g id="node4" class="node">
|
||||
<title>fib2</title>
|
||||
<ellipse fill="none" stroke="black" cx="47" cy="-186" rx="30.59" ry="18"/>
|
||||
<text text-anchor="middle" x="47" y="-182.3" font-family="Times,serif" font-size="14.00">fib(2)</text>
|
||||
</g>
|
||||
<!-- fib4->fib2 -->
|
||||
<g id="edge3" class="edge">
|
||||
<title>fib4->fib2</title>
|
||||
<path fill="none" stroke="black" d="M142.38,-245.7C125.45,-237.01 101.88,-224.42 82,-212 79.21,-210.26 76.35,-208.38 73.52,-206.46"/>
|
||||
<polygon fill="black" stroke="black" points="75.44,-203.53 65.24,-200.67 71.43,-209.27 75.44,-203.53"/>
|
||||
</g>
|
||||
<!-- fib3 -->
|
||||
<g id="node5" class="node">
|
||||
<title>fib3</title>
|
||||
<ellipse fill="none" stroke="black" cx="165" cy="-186" rx="30.59" ry="18"/>
|
||||
<text text-anchor="middle" x="165" y="-182.3" font-family="Times,serif" font-size="14.00">fib(3)</text>
|
||||
</g>
|
||||
<!-- fib4->fib3 -->
|
||||
<g id="edge4" class="edge">
|
||||
<title>fib4->fib3</title>
|
||||
<path fill="none" stroke="black" d="M165,-239.7C165,-231.98 165,-222.71 165,-214.11"/>
|
||||
<polygon fill="black" stroke="black" points="168.5,-214.1 165,-204.1 161.5,-214.1 168.5,-214.1"/>
|
||||
</g>
|
||||
<!-- fib33 -->
|
||||
<g id="node8" class="node">
|
||||
<title>fib33</title>
|
||||
<ellipse fill="none" stroke="black" cx="337" cy="-186" rx="30.59" ry="18"/>
|
||||
<text text-anchor="middle" x="337" y="-182.3" font-family="Times,serif" font-size="14.00">fib(3)</text>
|
||||
</g>
|
||||
<!-- fib5->fib33 -->
|
||||
<g id="edge7" class="edge">
|
||||
<title>fib5->fib33</title>
|
||||
<path fill="none" stroke="black" d="M337,-239.7C337,-231.98 337,-222.71 337,-214.11"/>
|
||||
<polygon fill="black" stroke="black" points="340.5,-214.1 337,-204.1 333.5,-214.1 340.5,-214.1"/>
|
||||
</g>
|
||||
<!-- fib44 -->
|
||||
<g id="node9" class="node">
|
||||
<title>fib44</title>
|
||||
<ellipse fill="none" stroke="black" cx="463" cy="-186" rx="30.59" ry="18"/>
|
||||
<text text-anchor="middle" x="463" y="-182.3" font-family="Times,serif" font-size="14.00">fib(4)</text>
|
||||
</g>
|
||||
<!-- fib5->fib44 -->
|
||||
<g id="edge8" class="edge">
|
||||
<title>fib5->fib44</title>
|
||||
<path fill="none" stroke="black" d="M358.94,-245.33C375.73,-236.35 399.42,-223.56 420,-212 424.29,-209.59 428.8,-207.01 433.23,-204.46"/>
|
||||
<polygon fill="black" stroke="black" points="435.18,-207.38 442.08,-199.33 431.67,-201.32 435.18,-207.38"/>
|
||||
</g>
|
||||
<!-- fib1 -->
|
||||
<g id="node6" class="node">
|
||||
<title>fib1</title>
|
||||
<ellipse fill="none" stroke="black" cx="125" cy="-114" rx="30.59" ry="18"/>
|
||||
<text text-anchor="middle" x="125" y="-110.3" font-family="Times,serif" font-size="14.00">fib(1)</text>
|
||||
</g>
|
||||
<!-- fib3->fib1 -->
|
||||
<g id="edge5" class="edge">
|
||||
<title>fib3->fib1</title>
|
||||
<path fill="none" stroke="black" d="M155.72,-168.76C150.95,-160.4 145.01,-150.02 139.63,-140.61"/>
|
||||
<polygon fill="black" stroke="black" points="142.51,-138.58 134.5,-131.63 136.43,-142.05 142.51,-138.58"/>
|
||||
</g>
|
||||
<!-- fib22 -->
|
||||
<g id="node7" class="node">
|
||||
<title>fib22</title>
|
||||
<ellipse fill="none" stroke="black" cx="204" cy="-114" rx="30.59" ry="18"/>
|
||||
<text text-anchor="middle" x="204" y="-110.3" font-family="Times,serif" font-size="14.00">fib(2)</text>
|
||||
</g>
|
||||
<!-- fib3->fib22 -->
|
||||
<g id="edge6" class="edge">
|
||||
<title>fib3->fib22</title>
|
||||
<path fill="none" stroke="black" d="M174.05,-168.76C178.7,-160.4 184.49,-150.02 189.73,-140.61"/>
|
||||
<polygon fill="black" stroke="black" points="192.92,-142.07 194.73,-131.63 186.81,-138.67 192.92,-142.07"/>
|
||||
</g>
|
||||
<!-- fib11 -->
|
||||
<g id="node10" class="node">
|
||||
<title>fib11</title>
|
||||
<ellipse fill="none" stroke="black" cx="298" cy="-114" rx="30.59" ry="18"/>
|
||||
<text text-anchor="middle" x="298" y="-110.3" font-family="Times,serif" font-size="14.00">fib(1)</text>
|
||||
</g>
|
||||
<!-- fib33->fib11 -->
|
||||
<g id="edge9" class="edge">
|
||||
<title>fib33->fib11</title>
|
||||
<path fill="none" stroke="black" d="M327.95,-168.76C323.3,-160.4 317.51,-150.02 312.27,-140.61"/>
|
||||
<polygon fill="black" stroke="black" points="315.19,-138.67 307.27,-131.63 309.08,-142.07 315.19,-138.67"/>
|
||||
</g>
|
||||
<!-- fib222 -->
|
||||
<g id="node11" class="node">
|
||||
<title>fib222</title>
|
||||
<ellipse fill="none" stroke="black" cx="377" cy="-114" rx="30.59" ry="18"/>
|
||||
<text text-anchor="middle" x="377" y="-110.3" font-family="Times,serif" font-size="14.00">fib(2)</text>
|
||||
</g>
|
||||
<!-- fib33->fib222 -->
|
||||
<g id="edge10" class="edge">
|
||||
<title>fib33->fib222</title>
|
||||
<path fill="none" stroke="black" d="M346.28,-168.76C351.05,-160.4 356.99,-150.02 362.37,-140.61"/>
|
||||
<polygon fill="black" stroke="black" points="365.57,-142.05 367.5,-131.63 359.49,-138.58 365.57,-142.05"/>
|
||||
</g>
|
||||
<!-- fib2222 -->
|
||||
<g id="node12" class="node">
|
||||
<title>fib2222</title>
|
||||
<ellipse fill="none" stroke="black" cx="463" cy="-114" rx="30.59" ry="18"/>
|
||||
<text text-anchor="middle" x="463" y="-110.3" font-family="Times,serif" font-size="14.00">fib(2)</text>
|
||||
</g>
|
||||
<!-- fib44->fib2222 -->
|
||||
<g id="edge11" class="edge">
|
||||
<title>fib44->fib2222</title>
|
||||
<path fill="none" stroke="black" d="M463,-167.7C463,-159.98 463,-150.71 463,-142.11"/>
|
||||
<polygon fill="black" stroke="black" points="466.5,-142.1 463,-132.1 459.5,-142.1 466.5,-142.1"/>
|
||||
</g>
|
||||
<!-- fib333 -->
|
||||
<g id="node13" class="node">
|
||||
<title>fib333</title>
|
||||
<ellipse fill="none" stroke="black" cx="542" cy="-114" rx="30.59" ry="18"/>
|
||||
<text text-anchor="middle" x="542" y="-110.3" font-family="Times,serif" font-size="14.00">fib(3)</text>
|
||||
</g>
|
||||
<!-- fib44->fib333 -->
|
||||
<g id="edge12" class="edge">
|
||||
<title>fib44->fib333</title>
|
||||
<path fill="none" stroke="black" d="M479.37,-170.5C490.49,-160.64 505.39,-147.44 517.87,-136.38"/>
|
||||
<polygon fill="black" stroke="black" points="520.49,-138.74 525.65,-129.49 515.85,-133.5 520.49,-138.74"/>
|
||||
</g>
|
||||
<!-- fib111 -->
|
||||
<g id="node14" class="node">
|
||||
<title>fib111</title>
|
||||
<ellipse fill="none" stroke="black" cx="541" cy="-42" rx="30.59" ry="18"/>
|
||||
<text text-anchor="middle" x="541" y="-38.3" font-family="Times,serif" font-size="14.00">fib(1)</text>
|
||||
</g>
|
||||
<!-- fib333->fib111 -->
|
||||
<g id="edge13" class="edge">
|
||||
<title>fib333->fib111</title>
|
||||
<path fill="none" stroke="black" d="M541.75,-95.7C541.64,-87.98 541.51,-78.71 541.39,-70.11"/>
|
||||
<polygon fill="black" stroke="black" points="544.89,-70.05 541.24,-60.1 537.89,-70.15 544.89,-70.05"/>
|
||||
</g>
|
||||
<!-- fib22222 -->
|
||||
<g id="node15" class="node">
|
||||
<title>fib22222</title>
|
||||
<ellipse fill="none" stroke="black" cx="620" cy="-42" rx="30.59" ry="18"/>
|
||||
<text text-anchor="middle" x="620" y="-38.3" font-family="Times,serif" font-size="14.00">fib(2)</text>
|
||||
</g>
|
||||
<!-- fib333->fib22222 -->
|
||||
<g id="edge14" class="edge">
|
||||
<title>fib333->fib22222</title>
|
||||
<path fill="none" stroke="black" d="M558.16,-98.5C569.14,-88.64 583.85,-75.44 596.17,-64.38"/>
|
||||
<polygon fill="black" stroke="black" points="598.75,-66.77 603.86,-57.49 594.08,-61.56 598.75,-66.77"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 10 KiB |
Reference in New Issue
Block a user