ajout de tous les cours et TP préparés cet été

This commit is contained in:
2026-01-17 23:10:49 +01:00
parent ed9415bc81
commit 301cf5a98f
125 changed files with 21614 additions and 542 deletions

View 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 dune 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 lalgorithme**
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 quil y aura environ log_2(a) itérations.

View File

@@ -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 lon na pas parcouru complètement lune des deux listes (gauche ou droite), on compare les éléments actuels de chaque liste (cest-à-dire gauche[i1] et droite[i2]).
• Si lélément de gauche est plus petit, on lajoute à 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 lune des deux listes est entièrement parcourue, on ajoute les éléments restants de lautre liste à tab_fusion. Cest 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 à laide 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 dUtilisation 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>.

View 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* ?

View File

@@ -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 dUtilisation 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>.

View File

@@ -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 :

View 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
View 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
```

View 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 sintéresse à lindice 12, on voit les valeurs 2 et 4 qui sont\n",
"différentes : lintrus est donc à gauche de lindice 12 (indice 12 compris)\n",
"\n",
"\n",
"En revanche, si on sintéresse à lindice 3, on voit les valeurs 9 et 9 qui sont\n",
"identiques : lintrus est donc à droite des indices 3-4-5, donc à partir de lindice 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
}

View 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`.

View 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)

View 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()

View File

@@ -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
}
}

View File

@@ -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
}
}

View 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))

View 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))

View 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)"]}
}
}
}

View 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))

View 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))

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

View 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)&#45;&gt;fib4 -->
<g id="edge1" class="edge">
<title>fib(6)&#45;&gt;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)&#45;&gt;fib5 -->
<g id="edge2" class="edge">
<title>fib(6)&#45;&gt;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&#45;&gt;fib2 -->
<g id="edge3" class="edge">
<title>fib4&#45;&gt;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&#45;&gt;fib3 -->
<g id="edge4" class="edge">
<title>fib4&#45;&gt;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&#45;&gt;fib33 -->
<g id="edge7" class="edge">
<title>fib5&#45;&gt;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&#45;&gt;fib44 -->
<g id="edge8" class="edge">
<title>fib5&#45;&gt;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&#45;&gt;fib1 -->
<g id="edge5" class="edge">
<title>fib3&#45;&gt;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&#45;&gt;fib22 -->
<g id="edge6" class="edge">
<title>fib3&#45;&gt;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&#45;&gt;fib11 -->
<g id="edge9" class="edge">
<title>fib33&#45;&gt;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&#45;&gt;fib222 -->
<g id="edge10" class="edge">
<title>fib33&#45;&gt;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&#45;&gt;fib2222 -->
<g id="edge11" class="edge">
<title>fib44&#45;&gt;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&#45;&gt;fib333 -->
<g id="edge12" class="edge">
<title>fib44&#45;&gt;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&#45;&gt;fib111 -->
<g id="edge13" class="edge">
<title>fib333&#45;&gt;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&#45;&gt;fib22222 -->
<g id="edge14" class="edge">
<title>fib333&#45;&gt;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