Skip to content
Snippets Groups Projects
Commit 0c6d767b authored by mschiess's avatar mschiess
Browse files

Ajout d'un exercice au nb recursivite2

parent 20af64be
No related branches found
No related tags found
No related merge requests found
recursivite/images/carresemboites.png

2.48 KiB

recursivite/images/flocon-iteration.png

21.3 KiB

recursivite/images/koch_snowflake.png

35.4 KiB

%% Cell type:markdown id: tags:
<h1 class="alert alert-success">Complément sur la récursivité en programmation</h2>
%% Cell type:markdown id: tags:
## <h2 class="alert alert-info"> 1. Introduction à la récursivité</h2>
Un algorithme récursif est un algorithme qui résout un problème en calculant des solutions d'instances plus petites du même problème.
%% Cell type:markdown id: tags:
<h2 class="alert alert-success"> Rappel : Algorithme pour implémenter une fonction récursive</h2>
- Etape 1 - Définir le cas de base : Identifier le cas le plus simple pour lequel une solution est connue.
- Etape 2 - Définir la récursion : Définir le problème en termes de plus petits sous-problèmes et appeler la fonction pour les résoudre.
- Etape 3 - Définir la fin : S'assurer que la récursion va bien arriver au cas de base pour éviter d'avoir une boucle infinie.
%% Cell type:markdown id: tags:
<h2 class = "alert alert-success"> Structure d'un code récursif en python :</h2>
%% Cell type:raw id: tags:
def fonction(n, ...):
if n==0 :
# code pour le cas de base
else :
# votre code où apparaîtra fonction(n-1,...)
%% Cell type:markdown id: tags:
### <h2 class="alert alert-info">2. Fractales : courbe de Koch Correction</h2>
La courbe de Koch est une fractale reposant sur la construction récursive suviante :
1. Étape 1 : Tracer un segment de longueur a.
![Image de losange](https://githepia.hesge.ch/info_sismondi/3AM.OS/-/raw/main/recursivite/koch_0.png)
2. Étape 2 : Diviser le segment en 3 parties de même longueur. Construire un triangle équilatéral ayant pour base le segment médian de la première étape, et en supprimer la base.
![Image de losange](https://githepia.hesge.ch/info_sismondi/3AM.OS/-/raw/main/recursivite/koch_1.png)
3. Étape 3 : Reprendre l'étape 2 sur chacun des segments créés.
![Image de losange](https://githepia.hesge.ch/info_sismondi/3AM.OS/-/raw/main/recursivite/koch_2.png)
4. Et ainsi de suite...
![Image de losange](https://githepia.hesge.ch/info_sismondi/3AM.OS/-/raw/main/recursivite/koch_3.png)
%% Cell type:markdown id: tags:
On peut construire récursivement cette courbe.
La fonction de tracer prend deux paramètres en entrée :
* la longeur $a$ du segment.
* l'étape $n$ de "profondeur" de récursivité.
Par exemple, à la profondeur $n=0$, on trace un simple segment : ceci constituera le cas de base et la condition d'arrêt des appels récursifs. À la profondeur $n=1$, le tracé donne la figure de l'étape 2.
%% Cell type:markdown id: tags:
<h2 class="alert alert-warning">Courbe de Koch : fonction récursive.</h2>
En vous inspirant de la logique du code de la fonction précédente (en la "rendant récursive"), écrire une fonction koch(a, n) récursive qui :
- prend comme paramètres un nombre entier a représentant la longueur du segment et un entier n égal au nombre de récursions souhaité.
- construit la courbe de Koch en divisant récursivement chacun des segments
*Rappel* : si n=0, le tracé est un simplement segment de longueur a.
%% Cell type:markdown id: tags:
<div class = "alert alert-block alert-success">
### Solution
</div>
%% Cell type:code id: tags:
``` python
import turtle as tt # import du module turtle
tt.speed(10)
tt.penup()
tt.setposition(-300, 0)
tt.pendown()
def koch(a, n):
if n == 0:
tt.forward(a)
else:
koch(a/3, n-1)
tt.left(60)
koch(a/3, n-1)
tt.right(120)
koch(a/3, n-1)
tt.left(60)
koch(a/3, n-1)
koch(360, 3)
tt.done()
```
%% Cell type:markdown id: tags:
<h2 class="alert alert-warning">Flocon de Koch : fonction récursive</h2>
Pour obtenir le flocon de Koch:
<figure>
<img title='Koch snowflake'
src="https://isquared.digital/assets/images/koch_snowflake.png"
width='600px' >
<figcaption>Etapes 0, 1, 2, 3 et 4</figcaption>
</figure>
Il suffit d'écrire une fonction `floconkoch(a,n)` qui va itérer `koch(a,n)` avec la bonne rotation.
%% Cell type:code id: tags:
``` python
a = 180
tt.speed(10)
tt.penup()
tt.setposition(-a/2, a/3)
tt.pendown()
def floconkoch(a, n):
for i in range(3):
koch(a, n)
tt.right(120)
# test pour afficher l'étape 3
flocon(a, 3)
tt.penup()
tt.home()
tt.done()
```
%% Cell type:markdown id: tags:
### <h2 class="alert alert-info">2. Fractales de Koch et perimètres </h2>
1. Complétez ce code récursif pour donner le perimètre du Flocon de Koch à l'étape n.
*Aidez vous de la figure ci-dessous pour comprendre l'évolution de l'aire entre deux itérations*
![Image du triangle de sierpinski](http://img.over-blog-kiwi.com/1/93/65/56/20160116/ob_804ca5_flcon-iteration.png)
%% Cell type:code id: tags:
``` python
def perimetreKoch(a,n):
if n==0 :
# code pour le cas de base
else :
# votre code où apparaîtra fonction(n-1,...)
```
%% Cell type:code id: tags:
``` python
# test pour a=50, n=3
perimetreKoch(50,3)
```
%% Cell type:code id: tags:
``` python
# test pour a=50, n=100
perimetreKoch(50,100)
```
%% Cell type:markdown id: tags:
**Question:** Que peut-on déduire du périmètre du Flocon de Koch (lorsque n tend vers l'infini) ?
**Réponse:**
%% Cell type:raw id: tags:
%% Cell type:markdown id: tags:
Pour calculer l'aire il est plus facile d'utiliser une boucle avec des variables qui comptes le nombres de triangles qu'on rajoute à chaque étape et la largeur de leur base.
2. Complétez le code de la fonction pour donner l'aire du Flocon de Koch à l'étape n.
%% Cell type:code id: tags:
``` python
def aireKoch(a,n):
A = ...
l = ...
c = ... # le nombre de carré
for i in range(n):
A = ...
l = ...
c = ...
return A
```
%% Cell type:code id: tags:
``` python
# test pour a=50, n=3
aireKoch(50,3)
```
%% Cell type:code id: tags:
``` python
# test pour a=50, n=100
aireKoch(50,100)
```
%% Cell type:markdown id: tags:
**Question:** Que peut-on déduire de l'aire du Flocon de Koch (lorsque n tend vers l'infini) ?
**Réponse:**
%% Cell type:raw id: tags:
%% Cell type:markdown id: tags:
### <h2 class="alert alert-info">3. une autre images fractale: le triangle de Sierpinski</h2>
La courbe de Koch est une fractale reposant sur la construction récursive suviante :
![Image du triangle de sierpinski](https://githepia.hesge.ch/info_sismondi/3AM.OS/-/raw/main/recursivite/images/triangle_de_sierpinski.png)
1. Écrire une fonction `triangle(a)` qui permet de dessiner un triangle de longeur `a`, puis une fonction `etape2(a)` qui permet de dessiner (pas de récursivité ici) la figure correspondant à l'étape 2 en utilisant la fonction `triangle(a)`.
%% Cell type:code id: tags:
``` python
import turtle as tt
def triangle(a):
...
def etape2(a) :
...
etape2(200)
tt.done()
```
%% Cell type:markdown id: tags:
2. En vous inspirant de la logique du code de la fonction précédente (en la "rendant récursive"), écrire une fonction `triangle_sierpinski(a, n)` récursive qui :
- remplace les appels à triangle par des appels récursifs pour n>=1
- trace un simple triangle lorsque n=0
%% Cell type:code id: tags:
``` python
import turtle as tt
def triangle_sierpinski(a, n) :
...
tt.hideturtle() # on cache la tortue
tt.speed(0) # tortue rapide
triangle_sierpinski( 200 , 7)
tt.done()
```
%% Cell type:markdown id: tags:
### <h2 class="alert alert-info">3. une autre images fractale: les carrés imbriqués</h2>
Écrire une fonction python récursive produisant le type de figures suivantes :
![Image du triangle de sierpinski](https://githepia.hesge.ch/info_sismondi/3AM.OS/-/raw/main/recursivite/images/carresemboites.png)
%% Cell type:code id: tags:
``` python
```
%% Cell type:markdown id: tags:
### <h2 class="alert alert-info">4. Décomposition d'un entier positif en somme d'au plus quatre carrés</h2>
Le théorème des quatre carrés de Lagrange affirme que tout nombre entier positif `n` peut s'écrire comme la somme d'au plus quatre carrés.
Par exemple, $1871 = 1 + 25 + 81 + 1764 = 1^2 + 5^2 + 9^2 + 42^2$.
Pour afficher une possibilité on peut donner l'algorithme suivant qui permet de décomposer un entier positif `n` en une somme d'au plus quatre carrés.
%% Cell type:markdown id: tags:
<div style='background-color: #f7bd83;
border-radius: 0.5em;
padding: 1em;
margin: 0em 2em 0em 2em'>
<p><b>Algorithme de décomposition de l'entier positif <code>n</code> en une somme d'au plus quatre carrés</b></p>
<p><b>Début</b></p>
<p STYLE="padding:0 0 0 40px;">Si <code>n</code> est le carré d'un entier alors</p>
<p STYLE="padding:0 0 0 80px;">Retourner un tableau contenant uniquement l'élément <code>n</code></p>
<p STYLE="padding:0 0 0 40px;">Sinon</p>
<p STYLE="padding:0 0 0 80px;"><code>liste_carres</code> tableau contenant la liste décroissante des nombres compris entre 1 et <code>n</code> qui sont des carrés d'entiers</p>
<p STYLE="padding:0 0 0 80px;">Pour chaque élément <code>carre</code> de <code>liste_carres</code> faire</p>
<p STYLE="padding:0 0 0 120px;"><code>decompo</code> ← liste renvoyé par <code>decomposition_carres(n - carre)</code> auquel on ajoute l'élément <code>carre</code> à la fin</p>
<p STYLE="padding:0 0 0 120px;">Si longueur(<code>decompo</code>) $\leq$ 4 alors</p>
<p STYLE="padding:0 0 0 160px;">Retourner <code>decompo</code></p>
<p><b>Fin</b></p>
</div>
%% Cell type:markdown id: tags:
**(1)** 💻 Définir une fonction `est_carre` qui prend en paramètre d'entrée un entier positif `n` et qui renvoie `True` si `n` est le carré d'un entier et `False` sinon.
%% Cell type:code id: tags:
``` python
def est_carre(n):
if ...:
return ...
else:
return ...
```
%% Cell type:code id: tags:
``` python
# Test
nb = 9
print(nb, "est-il un carre ? ", est_carre(nb))
nb = 10
print(nb, "est-il un carre ? ", est_carre(nb))
```
%% Cell type:markdown id: tags:
**(2)** 💻 Définir une fonction `liste_carres_entiers` qui prend en paramètre d'entrée un entier positif `n` et qui renvoie la liste décroissante des entiers compris entre 1 et `n` et qui sont des carrés d'entiers.
%% Cell type:code id: tags:
``` python
def liste_carres_entiers(n):
L = ...
for k in reversed(...):
if ...:
...
return L
```
%% Cell type:code id: tags:
``` python
# Test
listes_carres = liste_carres_entiers(100)
print(listes_carres) # doit afficher [100, 81, 64, 49, 36, 25, 16, 9, 4, 1]
```
%% Cell type:markdown id: tags:
**(3)** 💻 Implémenter la fonction `decomposition_carres` qui prend en paramètre d'entrée un entier positif `n` et qui renvoie, sous forme de tableau de longueur inférieure ou égale à 4, une décomposition de `n` en somme de carrés d'entiers.
%% Cell type:code id: tags:
``` python
def decomposition_carres(n):
...
```
%% Cell type:code id: tags:
``` python
# Test
nb = 1871
print("La décomposition de ",nb, "est : ", decomposition_carres(nb))
```
%% Cell type:markdown id: tags:
**(4)** ✏️ Donner une décomposition en somme d'au plus quatre carrés pour les entiers $300$, $1789$, $2021$ et $12345$.
%% Cell type:code id: tags:
``` python
```
%% Cell type:markdown id: tags:
**(5)** ✏️ Proposer une fonction non récursive `decomposition_carres2(n)` qui permet de calculer la décomposition et tester la fonction
%% Cell type:code id: tags:
``` python
def decomposition_carres2(n):
listes_carres = ...
for ...:
for ...:
for ...:
for ...:
if ... :
return ...
```
%% Cell type:code id: tags:
``` python
# Test
nb = 1871
print("La décomposition de ",nb, "est : ", decomposition_carres2(nb))
```
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment