Skip to content
Snippets Groups Projects
Commit 20af64be authored by SCHIESS Mathieu's avatar SCHIESS Mathieu
Browse files

ajout des formules dans ton corrigé

parent b15fe731
No related branches found
No related tags found
No related merge requests found
%% Cell type:markdown id: tags:
<div class = "alert alert-danger">
# Cours avec solution
Cliquez sur **Exécuter tout** Dans le menu **Cellule**
</div>
%% 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
import turtle as tt # import du module turtle
a = 180
tt.speed(10)
tt.penup()
tt.setposition(-a/2, a/3)
tt.pendown()
def floconkoch(a, n):
def flocon(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
return 3*a
else :
# votre code où apparaîtra fonction(n-1,...)
return (4/3)*perimetreKoch(a,n-1)
return (4/3)*perimetreKoch(a,n-1) # P(n) = (4/3)P(n-1)
```
%% Cell type:code id: tags:
``` python
# test pour a=50, n=3
perimetreKoch(50,3)
```
%% Output
355.5555555555555
%% Cell type:code id: tags:
``` python
# test pour a=50, n=100
perimetreKoch(50,100)
```
%% Output
%% Cell type:code id: tags:
``` python
def perimetreKoch2(a,n):
return (4/3)**n * 3*a
```
%% Cell type:markdown id: tags:
On utilise la relation $P_n = \left(\frac{4}{3}\right)^n P_0$
%% Cell type:code id: tags:
467697361531188.8
``` python
# test pour a=50, n=3
perimetreKoch2(50,3)
```
%% 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:
Son périmètre tend aussi vers l'infini.
%% 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 = (3**0.5 / 4 * a**2)
l = a / 3
c = 3 # le nombre de carré
A0 = (3**0.5 /4) * a**2 #l'aire des triangles qu'on rajoute
A = A0
c = 3 # le nombre de triangles qu'on rajoute
for i in range(n):
A = A + c * (3**0.5 / 4 * l**2)
l = l / 3
c = c * 3
A0 = 1/9*A0
A = A + c*A0
c = 3*c
return A
```
%% Cell type:code id: tags:
``` python
# test pour a=50, n=3
aireKoch(50,3)
```
%% Output
1603.7507477489605
%% Cell type:code id: tags:
``` python
# test pour a=50, n=100
aireKoch(50,100)
```
%% Output
%% Cell type:code id: tags:
1623.7976320958232
``` python
# test pour a=50, n=500
aireKoch(50,500)
```
%% 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:
On à l'aire qui converge vers 1623,80...
%% Cell type:markdown id: tags:
Mathématiquement (voir les calculs sur moodle), on peut montrer que l'aire tend vers $A=\frac{3 \sqrt{3}}{8}a^2$.
Ici si $a=50$, on a $A=\frac{3 \sqrt{3}}{8}50^2\approx 1623,80$
%% 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):
for _ in range(3) :
tt.forward(a)
tt.left(120)
def etape2(a) :
for _ in range(3) :
triangle(a/2)
tt.forward(a)
tt.left(120)
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) :
if n > 0 :
for _ in range(3) :
triangle_sierpinski(a/2, n-1)
tt.forward(a)
tt.left(120)
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">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 round(n**0.5)**2 == n:
return True
else:
return False
```
%% 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(range(1, n+1)):
if est_carre(k):
L.append(k)
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):
if est_carre(n):
return [n]
else:
listes_carres = liste_carres_entiers(n)
for carre in listes_carres:
decompo = decomposition_carres(n - carre) + [carre]
if len(decompo) <= 4:
return decompo
```
%% 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
def print_decompoision(n, decompo):
s = str(n)+ " = "
for n in decompo:
s = s + str(int(n**0.5))+"² + "
s = s[:-3]
print(s)
```
%% Cell type:code id: tags:
``` python
nb = 1871
print_decompoision(nb, decomposition_carres(nb))
nb = 300
print_decompoision(nb, decomposition_carres(nb))
nb = 1789
print_decompoision(nb, decomposition_carres(nb))
nb = 2021
print_decompoision(nb, decomposition_carres(nb))
nb = 12345
print_decompoision(nb, decomposition_carres(nb))
```
%% 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 = liste_carres_entiers(n)
listes_carres = listes_carres + [0]
for carre1 in listes_carres:
for carre2 in listes_carres:
for carre3 in listes_carres:
for carre4 in listes_carres:
if carre1 + carre2 +carre3 +carre4 ==n :
return [carre1, carre2, carre3, carre4]
```
%% Cell type:code id: tags:
``` python
nb = 1871
print_decompoision(nb, decomposition_carres2(nb))
nb = 300
print_decompoision(nb, decomposition_carres2(nb))
nb = 1789
print_decompoision(nb, decomposition_carres2(nb))
nb = 2021
print_decompoision(nb, decomposition_carres2(nb))
nb = 12345
print_decompoision(nb, decomposition_carres2(nb))
```
%% Cell type:code id: tags:
``` python
```
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment