Algorithmes et Programmation 2, année 2022

TD 2

L’objectif de ce TP est d’approfondir la récursivité et les calculs de complexité simple pour certaines fonctions.

Rappel Rendre le TP

Le TD doit être rendu sur Moodle avant le début du TD suivant. En cas de TD non rendu, vous aurez automatiquement 0, sauf cas exceptionnel.

Le rendu doit être un dossier compressé au format zip contenant:

Chaque fonction présente dans le TD doit contenir une documentation et un nom clair.

Les TP peuvent être rendus en binômes et le nom du binôme doit apparaître clairement dans le fichier réponses. Si une réponse est faite à plus que deux, vous devez l’indiquer dans le fichier réponse. Si ce n’est pas indiqué, cela sera considéré comme du plagiat.

Si vous utilisez du code sur internet, vous devez indiquer la source dans le code source et dans le fichier réponse. Si ce n’est pas indiqué, cela sera considéré comme du plagiat.

Des scripts automatiques sont exécutés pour vérifier cela pour chaque rendu, ne tentez pas la chance …

Exercice 1

Un étudiant de L2 MIASHS un rendu un TD en oubliant de respecter les consignes! Il a très mal nommé ses fonctions et ne leur à pas mis de documentations.

Afin qu’il n’ait pas 0, renommez les fonctions et écrivez pour lui la documentation.

Exercice 2

La suite de Fibonacci \((f_n)\) est définie par récurrence

\[ \begin{cases} f_0 = f_1 = 1 \\ f_{n+2} = f_{n+1} + f_n \end{cases} \]

  1. Écrire une fonction fibonacci récursive qui prend en argument un entier \(n\) et retourne \(f_n\), le \(n\)ème terme de la suite de Fibonacci.

  2. Analyser la complexité de la fonction.

  3. Écrire une fonction récursive de complexité linéaire qui prend en argument un entier \(n\) et retourne le couple \((f_n, f_{n-1})\). En déduire une fonction fibonacci2 qui prend en argument un entier \(n\) et retourne \(f_n\).

  4. (Difficile) Mémoisation

Écrire un décorateur (une fonction de fonction, voir ici) qui prend en argument:

et qui retourne une nouvelle fonction \(nf\) qui prend en argument un entier et:

Décorez la fonction fibonacci de la première question. Quelle la complexité de la fonction décorée? Quelle est la complexité en espace?

Exercice 3:

Voici la spécification du problème decoupe

Par exemple, decoupe("aabacbddddbebf","b") retourne la liste ["aa", "ac", "dddd", "e", "f"].

  1. Écrire une version itérative de la fonction decoupe

  2. Écrire une version récursive de la fonction decoupe

  3. Faire l’analyse de complexité de chaque implémentation

Exercice 4: Les ensembles de Mandelbrot

Pour \(c\in\mathbb{C}\), on définit la suite complexe

\[ \begin{cases} z_0 = 0\\ z_{n+1} = z_n^2 + c \end{cases} \]

Cette suite peut converger ou diverger en fonction de la valeur de \(c\). On sait qu’elle diverge quand son module est supérieur à 2.

  1. Écrire une fonction récursive mandelbrot qui prend en argument le nombre complexe \(c\) et \(n\) et retourne \(z_n\) ou \(2\) si le module de \(z_n\) est supérieur à \(2\). Écrire une fonction mandelbrot_module qui prends en argument un nombre complexe \(c\) et un entier \(n\) et retourne le module de \(z_n\) si celui ci est plus petit que \(2\) et \(2\) sinon.

Les complexes sont gérés nativement par Python sans effort. Le nombre \(13+4i\) s’écrit 13 + 4j.

  1. Écrire une fonction fenetre qui prend en argument un nombre complexe \(O\) (l’origine), un float \(D\) (le diametre), et un entier \(n\) (nombre de points) et retourne la liste de liste \(L\) tel que pour tout \(a,b< n\) on a \(L[a][b] = O + (a*\frac{D}{n} - \frac{D}{2}) + (b*\frac{D}{n} - \frac{D}{2})j\)

Vous pouvez le faire à la main facilement ou utiliser la fonction arange du module Python numpy

On peut voir une liste contenant \(n\) liste de taille \(m\) comme une matrice \(n\times m\).

  1. À l’aide d’une ou plusieurs application de map, construisez une fonction qui prends une liste de liste de complexe et applique la fonction Mandelbrot sur chaque point.

  2. Pour dessiner une matrice en Python, on peut utiliser le module matplotlib et numpy comme suit:

import matplotlib.pyplot as plt
import numpy as np

L = [
[0, 0, 0, 0, 0, 0, 0],
[0, 1, 1, 1, 1, 1, 0],
[0, 1, 0, 1, 0, 1, 0],
[0, 1, 1, 1, 1, 1, 0],
[0, 0, 1, 0, 1, 0, 0],
[0, 0, 1, 1, 1, 0, 0],
[0, 0, 0, 1, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0]
]

M = np.array(L) # Tranforme la liste de liste en tableau numpy
plt.imshow(M)
plt.axis("off") # enlève les axes, inutile ici
plt.show() # dessine le resultat

exemple

Les couleurs peuvent être changées (voir ici)

Dessiner les ensembles de Mandelbrot:

exemple

exemple

Pour les curieux, pour fabriquer un gif, il faut:

  1. générer chaque image indépendamment de manière numéroté et les sauvegardé à l’aide de plot.savefig.

  2. Utiliser un logiciel pour assembler les images. Dans Linux avec ImageMagick installé: :w

$ convert -delay 10 -loop 0 *.png mandelbrot.gif
/bin/sh: 1: $: not found

Cela prends pas mal de temps de calcul.

  1. (Bonus) Ajoutez des jolies images de fractales (voire des images animés) et le code qui les génèrent. Les plus jolies images seront ajoutés pour la postérité au sujet du TD (avec un remerciement).

Exercice 5: Répétition dans une liste

Voici la description d’un problème algorithmique.

Par exemple, sur la liste [0, 1, 1, 2, 1, 3, 2] retournera [0, 1, 2, 3] pour \(k = 1\), [1, 2] pour \(k=2\) et [1] pour \(k=3\).

Proposez une implémentation impérative et récursive pour ce problème et une analyse de complexité.

Exercice 6: Sous-mots

Pour \(u\) et \(v\) deux mots, on dit que:

\(u\) est un sous-mot de \(v\) si en effaçant des lettres de \(v\) on peut obtenir \(u\).

Par exemple "ab" est un sous mot de "acdb" mais pas un sous mot de "bcda"

Proposez une implémentation impérative et récursive pour ce problème et une analyse de complexité.



Compiled the: mer. 04 sept. 2024 12:49:49 CEST