diff --git a/slides/cours_5.md b/slides/cours_5.md
index 22b77c60c3399835e03871e856f1f17a3423308f..151a338a9d59eb6b250aeae8b18537ada39be042 100644
--- a/slides/cours_5.md
+++ b/slides/cours_5.md
@@ -483,474 +483,3 @@ $$
 
 * Comportement indéfini!
 
-# Nombres à virgule (1/3)
-
-## Comment manipuler des nombres à virgule?
-
-$$
-0.1 + 0.2 = 0.3.
-$$
-
-Facile non?
-
-. . .
-
-## Et ça?
-
-```C
-#include <stdio.h>
-#include <stdlib.h>
-int main(int argc, char *argv[]) {
-    float a = atof(argv[1]);
-    float b = atof(argv[2]);
-    printf("%.10f\n", (double)(a + b));
-}
-```
-
-. . .
-
-## Que se passe-t-il donc?
-
-# Nombres à virgule (2/3)
-
-## Nombres à virgule fixe
-
-+-------+-------+-------+-------+-----+----------+----------+----------+----------+
-| $2^3$ | $2^2$ | $2^1$ | $2^0$ | `.` | $2^{-1}$ | $2^{-2}$ | $2^{-3}$ | $2^{-4}$ |
-+-------+-------+-------+-------+-----+----------+----------+----------+----------+
-| `1`   | `0`   | `1`   |  `0`  | `.` | `0`      | `1`      | `0`      | `1`      |
-+-------+-------+-------+-------+-----+----------+----------+----------+----------+
-
-## Qu'est-ce ça donne en décimal?
-
-. . .
-
-$$
-2^3+2^1+\frac{1}{2^2}+\frac{1}{2^4} = 8+2+0.5+0.0625=10.5625.
-$$
-
-## Limites de cette représentation? 
-
-. . .
-
-
-* Tous les nombres `> 16`.
-* Tous les nombres `< 0.0625`.
-* Tous les nombres dont la décimale est pas un multiple de `0.0625`.
-
-# Nombres à virgule (3/3)
-
-## Nombres à virgule fixe
-
-* Nombres de $0=0000.0000$ à $15.9375=1111.1111$.
-* Beaucoup de "trous" (au moins $0.0625$) entre deux nombres.
-
-## Solution partielle?
-
-. . .
-
-* Rajouter des bits.
-* Bouger la virgule.
-
-# Nombres à virgule flottante (1/2)
-
-## Notation scientifique
-
-* Les nombres sont représentés en terme:
-    * Une mantisse
-    * Une base
-    * Un exposant
-
-$$
-\underbrace{22.1214}_{\mbox{nombre}}=\underbrace{221214}_{\mbox{mantisse}}\cdot
-{\underbrace{10}_{\mbox{base}}}{\overbrace{^{-4}}^{\mbox{exp.}}},
-$$
-
-. . .
-
-On peut donc séparer la représentation en 2:
-
-* La mantisse
-* L'exposant
-
-# Nombres à virgule flottante (2/2)
-
-## Quel est l'avantage?
-
-. . .
-
-On peut représenter des nombres sur énormément d'ordres de grandeur avec un
-nombre de bits fixés.
-
-## Différence fondamentale avec la virgule fixe?
-
-. . .
-
-La précision des nombres est **variable**:
-
-* On a uniquement un nombre de chiffres **significatifs**.
-$$
-123456\cdot 10^{23}+ 123456\cdot 10^{-23}.
-$$
-
-## Quel inconvénient y a-t-il?
-
-. . .
-
-Ce mélange d'échelles entraîne un **perte de précision**.
-
-# Nombres à virgule flottante simple précision (1/4)
-
-Aussi appelés *IEEE 754 single-precision binary floating point*.
-
-![Nombres à virgule flottante 32 bits. Source:
-[Wikipedia](https://en.wikipedia.org/wiki/Single-precision_floating-point_format)](figs/Float_example_bare.svg)
-
-## Spécification
-
-* 1 bit de signe,
-* 8 bits d'exposant,
-* 23 bits de mantisse.
-
-$$
-(-1)^{b_{31}}\cdot 2^{(b_{30}b_{29}\dots b_{23})_{2}-127}\cdot (1.b_{22}b_{21}\dots b_{0})_{2},
-$$
-
-## Calculer la valeur décimale du nombre ci-dessus
-
-# Nombres à virgule flottante simple précision (2/4)
-
-![Un exercice de nombres à virgule flottante 32 bits. Source:
-[Wikipedia](https://en.wikipedia.org/wiki/Single-precision_floating-point_format)](figs/Float_example.svg)
-
-. . .
-
-\begin{align}
-\mbox{exposant}&=\sum_{i=0}^7 b_{23+i}2^i=2^2+2^3+2^4+2^5+2^6=124-127,\\
-\mbox{mantisse}&=1+\sum_{i=1}^{23}b_{23-i}2^{-i}=1+2^{-2}=1.25,\\
-&\Rightarrow (-1)^0\cdot 2^{-3}\cdot 1.25=0.15625
-\end{align}
-
-# Nombres à virgule flottante simple précision (3/4)
-
-## Quel nombre ne peux pas être vraiment représenté?
-
-. . .
-
-## Zéro: exception pour l'exposant
-
-* Si l'exposant est `00000000` (zéro)
-$$
-(-1)^{\mbox{sign}}\cdot 2^{-126}\cdot 0.\mbox{mantisse},
-$$
-* Sinon si l'exposant est `00000001` à `11111110`
-$$
-\mbox{valeur normale},
-$$
-* Sinon `11111111` donne `NaN`.
-
-# Nombres à virgule flottante simple précision (4/4)
-
-## Quels sont les plus petits/grands nombres positifs représentables?
-
-. . .
-
-\begin{align}
-0\ 0\dots0\ 0\dots01&=2^{-126}\cdot 2^{-23}=1.4...\cdot
-10^{-45},\\
-0\ 1\dots10\ 1\dots1&=2^{127}\cdot (2-2^{-23})=3.4...\cdot
-10^{38}.
-\end{align}
-
-## Combien de chiffres significatifs en décimal?
-
-. . .
-
-* 24 bits ($23 + 1$) sont utiles pour la mantisse, soit $2^{24}-1$:
-    * La mantisse fait $\sim2^{24}\sim 10^7$,
-    * Ou encore $\sim \log_{10}(2^{24})\sim 7$.
-* Environ **sept** chiffres significatifs.
-
-# Nombres à virgule flottante double précision (64bits)
-
-## Spécification
-
-* 1 bit de signe,
-* 11 bits d'exposant,
-* 52 bits de mantisse.
-
-. . .
-
-## Combien de chiffres significatifs?
-
-* La mantisse fait $\sim 2^{53}\sim10^{16}$,
-* Ou encore $\sim \log_{10}(2^{53})\sim 16$,
-* Environ **seize** chiffres significatifs.
-
-## Plus petit/plus grand nombre représentable?
-
-. . .
-
-* Plus petite mantisse et exposant: $\sim 2^{-52}\cdot 2^{-1022}\sim 4\cdot 10^{-324}$,
-* Plus grande mantisse et exposant: $\sim 2\cdot 2^{1023}\sim \cdot 1.8\cdot 10^{308}$.
-
-# Précision finie (1/3)
-
-## Erreur de représentation
-
-* Les nombres réels ont potentiellement un **nombre infini** de décimales
-    * $1/3=0.\overline{3}$,
-    * $\pi=3.1415926535...$.
-* Les nombres à virgule flottante peuvent en représenter qu'un **nombre
-  fini**.
-  * $1/3\cong 0.33333$, erreur $0.00000\overline{3}$.
-  * $\pi\cong3.14159$, erreur $0.0000026535...$.
-
-On rencontre donc des **erreurs de représentation** ou **erreurs
-d'arrondi**.
-
-. . .
-    
-## Et quand on calcule?
-
-* Avec deux chiffres significatifs
-\begin{align}
-&8.9+(0.02+0.04)=8.96=9.0,\\
-&(8.9+0.02)+0.04=8.9+0.04=8.9.
-\end{align}
-
-. . .
-
-## Même pas associatif!
-
-# Précision finie (2/3)
-
-## Erreur de représentation virgule flottante
-
-$$
-(1.2)_{10} = 1.\overline{0011}\cdot 2^0\Rightarrow 0\ 01111111\
-00110011001100110011010.
-$$
-Erreur d'arrondi dans les deux derniers bits et tout ceux qui viennent
-ensuite
-$$
-\varepsilon_2 = (00000000000000000000011)_2.
-$$
-Ou en décimal
-$$
-\varepsilon_{10} = 4.76837158203125\cdot 10^{-8}.
-$$
-
-# Précision finie (3/3)
-
-## Comment définir l'égalité de 2 nombres à virgule flottante?
-
-. . .
-
-Ou en d'autres termes, pour quel $\varepsilon>0$ (appelé `epsilon-machine`) on a
-$$
-1+\varepsilon = 1,
-$$
-pour un nombre à virgule flottante?
-
-. . .
-
-Pour un `float` (32 bits) la différence est à 
-$$
-2^{-23}=1.19\cdot 10^{-7},
-$$
-Soit la précision de la mantisse.
-
-## Comment le mesurer (par groupe)?
-
-. . .
-
-```C
-float eps = 1.0;
-while ((float)1.0 + (float)0.5 * eps != (float)1.0) {
-    eps = (float)0.5 * eps;
-}
-printf("eps = %g\n", eps);
-```
-
-# Erreurs d'arrondi
-
-Et jusqu'ici on a encore pas fait d'arithmétique!
-
-## Multiplication avec deux chiffres significatifs, décimal
-
-$$
-(1.1)_{10}\cdot (1.1)_{10}=(1.21)_{10}=(1.2)_{10}.
-$$
-En continuant ce petit jeu:
-$$
-\underbrace{1.1\cdot 1.1\cdots 1.1}_{\mbox{10 fois}}=2.0.
-$$
-Alors qu'en réalité
-$$
-1.1^{10}=2.5937...
-$$
-Soit une erreur de près de 1/5e!
-
-. . .
-
-## Le même phénomène se produit (à plus petite échelle) avec les `float` ou `double`.
-
-# And now for something completely different
-
-\Huge La récursivité
-
-# Exemple de récursivité (1/2)
-
-## La factorielle
-
-```C
-int factorial(int n) {
-    if (n > 1) {
-        return n * factorial(n - 1);
-    } else {
-        return 1;
-    }
-}
-```
-
-. . .
-
-## Que se passe-t-il quand on fait `factorial(4)`?
-
-. . .
-
-## On empile les appels
-
-+----------------+----------------+----------------+----------------+
-|                |                |                | `factorial(1)` |
-+----------------+----------------+----------------+----------------+
-|                |                | `factorial(2)` | `factorial(2)` |
-+----------------+----------------+----------------+----------------+
-|                | `factorial(3)` | `factorial(3)` | `factorial(3)` |
-+----------------+----------------+----------------+----------------+
-| `factorial(4)` | `factorial(4)` | `factorial(4)` | `factorial(4)` |
-+----------------+----------------+----------------+----------------+
-
-# Exemple de récursivité (2/2)
-
-## La factorielle
-
-```C
-int factorial(int n) {
-    if (n > 1) {
-        return n * factorial(n - 1);
-    } else {
-        return 1;
-    }
-}
-```
-
-. . .
-
-## Que se passe-t-il quand on fait `factorial(4)`?
-
-. . .
-
-## On dépile les calculs
-
-+----------------+----------------+----------------+----------------+
-|  `1`           |                |                |                |
-+----------------+----------------+----------------+----------------+
-| `factorial(2)` |  `2 * 1 = 2`   |                |                |
-+----------------+----------------+----------------+----------------+
-| `factorial(3)` | `factorial(3)` |  `3 * 2 = 6`   |                |
-+----------------+----------------+----------------+----------------+
-| `factorial(4)` | `factorial(4)` | `factorial(4)` |  `4 * 6 = 24`  |
-+----------------+----------------+----------------+----------------+
-
-# La récursivité (1/4)
-
-## Formellement 
-
-* Une condition de récursivité - qui *réduit* les cas successifs vers...
-* Une condition d'arrêt - qui retourne un résultat
-
-## Pour la factorielle, qui est qui?
-
-```C
-int factorial(int n) {
-    if (n > 1) {
-        return n * factorial(n - 1);
-    } else {
-        return 1;
-    }
-}
-```
-
-# La récursivité (2/4)
-
-## Formellement 
-
-* Une condition de récursivité - qui *réduit* les cas successifs vers...
-* Une condition d'arrêt - qui retourne un résultat
-
-## Pour la factorielle, qui est qui?
-
-```C
-int factorial(int n) {
-    if (n > 1) { // Condition de récursivité
-        return n * factorial(n - 1);
-    } else {     // Condition d'arrêt
-        return 1;
-    }
-}
-```
-
-# La récursivité (3/4)
-
-## Exercice: trouver l'$\varepsilon$-machine pour un `double`
-
-. . .
-
-Rappelez-vous vous l'avez fait en style **impératif** plus tôt.
-
-. . .
-
-```C
-double epsilon_machine(double eps) {
-    if (1.0 + eps != 1.0) {
-        return epsilon_machine(eps / 2.0);
-    } else {
-        return eps;
-    }
-}
-```
-
-# La récursivité (4/4)
-
-\footnotesize
-
-## Exercice: que fait ce code récursif?
-
-```C
-void recurse(int n) {
-    printf("%d ", n % 2);
-    if (n / 2 != 0) {
-        recurse(n / 2);
-    } else {
-        printf("\n");
-    }
-}
-recurse(13); 
-```
-
-. . .
-
-```C
-recurse(13): n = 13, n % 2 = 1, n / 2 = 6,
-    recurse(6): n = 6, n % 2 = 0, n / 2 = 3,
-        recurse(3): n = 3, n % 2 = 1, n / 2 = 1,
-            recurse(1): n = 1, n % 2 = 1, n / 2 = 0.
-
-// affiche: 1 1 0 1
-```
-
-. . .
-
-Affiche la représentation binaire d'un nombre!
diff --git a/slides/cours_6.md b/slides/cours_6.md
new file mode 100644
index 0000000000000000000000000000000000000000..311016a350f1c2ee2d742fc083e2a097d8a82d30
--- /dev/null
+++ b/slides/cours_6.md
@@ -0,0 +1,946 @@
+---
+title: "Récursivité et complexité"
+date: "2023-10-31"
+---
+
+# Nombres à virgule (1/3)
+
+## Comment manipuler des nombres à virgule?
+
+$$
+0.1 + 0.2 = 0.3.
+$$
+
+Facile non?
+
+. . .
+
+## Et ça?
+
+```C
+#include <stdio.h>
+#include <stdlib.h>
+int main(int argc, char *argv[]) {
+    float a = atof(argv[1]);
+    float b = atof(argv[2]);
+    printf("%.10f\n", (double)(a + b));
+}
+```
+
+. . .
+
+## Que se passe-t-il donc?
+
+# Nombres à virgule (2/3)
+
+## Nombres à virgule fixe
+
++-------+-------+-------+-------+-----+----------+----------+----------+----------+
+| $2^3$ | $2^2$ | $2^1$ | $2^0$ | `.` | $2^{-1}$ | $2^{-2}$ | $2^{-3}$ | $2^{-4}$ |
++-------+-------+-------+-------+-----+----------+----------+----------+----------+
+| `1`   | `0`   | `1`   |  `0`  | `.` | `0`      | `1`      | `0`      | `1`      |
++-------+-------+-------+-------+-----+----------+----------+----------+----------+
+
+## Qu'est-ce ça donne en décimal?
+
+. . .
+
+$$
+2^3+2^1+\frac{1}{2^2}+\frac{1}{2^4} = 8+2+0.5+0.0625=10.5625.
+$$
+
+## Limites de cette représentation? 
+
+. . .
+
+
+* Tous les nombres `> 16`.
+* Tous les nombres `< 0.0625`.
+* Tous les nombres dont la décimale est pas un multiple de `0.0625`.
+
+# Nombres à virgule (3/3)
+
+## Nombres à virgule fixe
+
+* Nombres de $0=0000.0000$ à $15.9375=1111.1111$.
+* Beaucoup de "trous" (au moins $0.0625$) entre deux nombres.
+
+## Solution partielle?
+
+. . .
+
+* Rajouter des bits.
+* Bouger la virgule.
+
+# Nombres à virgule flottante (1/2)
+
+## Notation scientifique
+
+* Les nombres sont représentés en terme:
+    * Une mantisse
+    * Une base
+    * Un exposant
+
+$$
+\underbrace{22.1214}_{\mbox{nombre}}=\underbrace{221214}_{\mbox{mantisse}}\cdot
+{\underbrace{10}_{\mbox{base}}}{\overbrace{^{-4}}^{\mbox{exp.}}},
+$$
+
+. . .
+
+On peut donc séparer la représentation en 2:
+
+* La mantisse
+* L'exposant
+
+# Nombres à virgule flottante (2/2)
+
+## Quel est l'avantage?
+
+. . .
+
+On peut représenter des nombres sur énormément d'ordres de grandeur avec un
+nombre de bits fixés.
+
+## Différence fondamentale avec la virgule fixe?
+
+. . .
+
+La précision des nombres est **variable**:
+
+* On a uniquement un nombre de chiffres **significatifs**.
+$$
+123456\cdot 10^{23}+ 123456\cdot 10^{-23}.
+$$
+
+## Quel inconvénient y a-t-il?
+
+. . .
+
+Ce mélange d'échelles entraîne un **perte de précision**.
+
+# Nombres à virgule flottante simple précision (1/4)
+
+Aussi appelés *IEEE 754 single-precision binary floating point*.
+
+![Nombres à virgule flottante 32 bits. Source:
+[Wikipedia](https://en.wikipedia.org/wiki/Single-precision_floating-point_format)](figs/Float_example_bare.svg)
+
+## Spécification
+
+* 1 bit de signe,
+* 8 bits d'exposant,
+* 23 bits de mantisse.
+
+$$
+(-1)^{b_{31}}\cdot 2^{(b_{30}b_{29}\dots b_{23})_{2}-127}\cdot (1.b_{22}b_{21}\dots b_{0})_{2},
+$$
+
+## Calculer la valeur décimale du nombre ci-dessus
+
+# Nombres à virgule flottante simple précision (2/4)
+
+![Un exercice de nombres à virgule flottante 32 bits. Source:
+[Wikipedia](https://en.wikipedia.org/wiki/Single-precision_floating-point_format)](figs/Float_example.svg)
+
+. . .
+
+\begin{align}
+\mbox{exposant}&=\sum_{i=0}^7 b_{23+i}2^i=2^2+2^3+2^4+2^5+2^6=124-127,\\
+\mbox{mantisse}&=1+\sum_{i=1}^{23}b_{23-i}2^{-i}=1+2^{-2}=1.25,\\
+&\Rightarrow (-1)^0\cdot 2^{-3}\cdot 1.25=0.15625
+\end{align}
+
+# Nombres à virgule flottante simple précision (3/4)
+
+## Quel nombre ne peux pas être vraiment représenté?
+
+. . .
+
+## Zéro: exception pour l'exposant
+
+* Si l'exposant est `00000000` (zéro)
+$$
+(-1)^{\mbox{sign}}\cdot 2^{-126}\cdot 0.\mbox{mantisse},
+$$
+* Sinon si l'exposant est `00000001` à `11111110`
+$$
+\mbox{valeur normale},
+$$
+* Sinon `11111111` donne `NaN`.
+
+# Nombres à virgule flottante simple précision (4/4)
+
+## Quels sont les plus petits/grands nombres positifs représentables?
+
+. . .
+
+\begin{align}
+0\ 0\dots0\ 0\dots01&=2^{-126}\cdot 2^{-23}=1.4...\cdot
+10^{-45},\\
+0\ 1\dots10\ 1\dots1&=2^{127}\cdot (2-2^{-23})=3.4...\cdot
+10^{38}.
+\end{align}
+
+## Combien de chiffres significatifs en décimal?
+
+. . .
+
+* 24 bits ($23 + 1$) sont utiles pour la mantisse, soit $2^{24}-1$:
+    * La mantisse fait $\sim2^{24}\sim 10^7$,
+    * Ou encore $\sim \log_{10}(2^{24})\sim 7$.
+* Environ **sept** chiffres significatifs.
+
+# Nombres à virgule flottante double précision (64bits)
+
+## Spécification
+
+* 1 bit de signe,
+* 11 bits d'exposant,
+* 52 bits de mantisse.
+
+. . .
+
+## Combien de chiffres significatifs?
+
+* La mantisse fait $\sim 2^{53}\sim10^{16}$,
+* Ou encore $\sim \log_{10}(2^{53})\sim 16$,
+* Environ **seize** chiffres significatifs.
+
+## Plus petit/plus grand nombre représentable?
+
+. . .
+
+* Plus petite mantisse et exposant: $\sim 2^{-52}\cdot 2^{-1022}\sim 4\cdot 10^{-324}$,
+* Plus grande mantisse et exposant: $\sim 2\cdot 2^{1023}\sim \cdot 1.8\cdot 10^{308}$.
+
+# Précision finie (1/3)
+
+## Erreur de représentation
+
+* Les nombres réels ont potentiellement un **nombre infini** de décimales
+    * $1/3=0.\overline{3}$,
+    * $\pi=3.1415926535...$.
+* Les nombres à virgule flottante peuvent en représenter qu'un **nombre
+  fini**.
+  * $1/3\cong 0.33333$, erreur $0.00000\overline{3}$.
+  * $\pi\cong3.14159$, erreur $0.0000026535...$.
+
+On rencontre donc des **erreurs de représentation** ou **erreurs
+d'arrondi**.
+
+. . .
+    
+## Et quand on calcule?
+
+* Avec deux chiffres significatifs
+\begin{align}
+&8.9+(0.02+0.04)=8.96=9.0,\\
+&(8.9+0.02)+0.04=8.9+0.04=8.9.
+\end{align}
+
+. . .
+
+## Même pas associatif!
+
+# Précision finie (2/3)
+
+## Erreur de représentation virgule flottante
+
+$$
+(1.2)_{10} = 1.\overline{0011}\cdot 2^0\Rightarrow 0\ 01111111\
+00110011001100110011010.
+$$
+Erreur d'arrondi dans les deux derniers bits et tout ceux qui viennent
+ensuite
+$$
+\varepsilon_2 = (00000000000000000000011)_2.
+$$
+Ou en décimal
+$$
+\varepsilon_{10} = 4.76837158203125\cdot 10^{-8}.
+$$
+
+# Précision finie (3/3)
+
+## Comment définir l'égalité de 2 nombres à virgule flottante?
+
+. . .
+
+Ou en d'autres termes, pour quel $\varepsilon>0$ (appelé `epsilon-machine`) on a
+$$
+1+\varepsilon = 1,
+$$
+pour un nombre à virgule flottante?
+
+. . .
+
+Pour un `float` (32 bits) la différence est à 
+$$
+2^{-23}=1.19\cdot 10^{-7},
+$$
+Soit la précision de la mantisse.
+
+## Comment le mesurer (par groupe)?
+
+. . .
+
+```C
+float eps = 1.0;
+while ((float)1.0 + (float)0.5 * eps != (float)1.0) {
+    eps = (float)0.5 * eps;
+}
+printf("eps = %g\n", eps);
+```
+
+# Erreurs d'arrondi
+
+Et jusqu'ici on a encore pas fait d'arithmétique!
+
+## Multiplication avec deux chiffres significatifs, décimal
+
+$$
+(1.1)_{10}\cdot (1.1)_{10}=(1.21)_{10}=(1.2)_{10}.
+$$
+En continuant ce petit jeu:
+$$
+\underbrace{1.1\cdot 1.1\cdots 1.1}_{\mbox{10 fois}}=2.0.
+$$
+Alors qu'en réalité
+$$
+1.1^{10}=2.5937...
+$$
+Soit une erreur de près de 1/5e!
+
+. . .
+
+## Le même phénomène se produit (à plus petite échelle) avec les `float` ou `double`.
+
+# And now for something completely different
+
+\Huge La récursivité
+
+# La factorielle: Code impératif
+
+* Code impératif
+
+```C
+int factorial(int n) {
+    int f = 1;
+    for (int i = 1; i < n; ++i) {
+        f *= i;
+    }
+    return f;
+}
+```
+
+# Exemple de récursivité (1/2)
+
+## La factorielle
+
+```C
+int factorial(int n) {
+    if (n > 1) {
+        return n * factorial(n - 1);
+    } else {
+        return 1;
+    }
+}
+```
+
+. . .
+
+## Que se passe-t-il quand on fait `factorial(4)`?
+
+. . .
+
+## On empile les appels
+
++----------------+----------------+----------------+----------------+
+|                |                |                | `factorial(1)` |
++----------------+----------------+----------------+----------------+
+|                |                | `factorial(2)` | `factorial(2)` |
++----------------+----------------+----------------+----------------+
+|                | `factorial(3)` | `factorial(3)` | `factorial(3)` |
++----------------+----------------+----------------+----------------+
+| `factorial(4)` | `factorial(4)` | `factorial(4)` | `factorial(4)` |
++----------------+----------------+----------------+----------------+
+
+# Exemple de récursivité (2/2)
+
+## La factorielle
+
+```C
+int factorial(int n) {
+    if (n > 1) {
+        return n * factorial(n - 1);
+    } else {
+        return 1;
+    }
+}
+```
+
+. . .
+
+## Que se passe-t-il quand on fait `factorial(4)`?
+
+. . .
+
+## On dépile les calculs
+
++----------------+----------------+----------------+----------------+
+|  `1`           |                |                |                |
++----------------+----------------+----------------+----------------+
+| `factorial(2)` |  `2 * 1 = 2`   |                |                |
++----------------+----------------+----------------+----------------+
+| `factorial(3)` | `factorial(3)` |  `3 * 2 = 6`   |                |
++----------------+----------------+----------------+----------------+
+| `factorial(4)` | `factorial(4)` | `factorial(4)` |  `4 * 6 = 24`  |
++----------------+----------------+----------------+----------------+
+
+# La récursivité (1/4)
+
+## Formellement 
+
+* Une condition de récursivité - qui *réduit* les cas successifs vers...
+* Une condition d'arrêt - qui retourne un résultat
+
+## Pour la factorielle, qui est qui?
+
+```C
+int factorial(int n) {
+    if (n > 1) {
+        return n * factorial(n - 1);
+    } else {
+        return 1;
+    }
+}
+```
+
+# La récursivité (2/4)
+
+## Formellement 
+
+* Une condition de récursivité - qui *réduit* les cas successifs vers...
+* Une condition d'arrêt - qui retourne un résultat
+
+## Pour la factorielle, qui est qui?
+
+```C
+int factorial(int n) {
+    if (n > 1) { // Condition de récursivité
+        return n * factorial(n - 1);
+    } else {     // Condition d'arrêt
+        return 1;
+    }
+}
+```
+
+# La récursivité (3/4)
+
+## Exercice: trouver l'$\varepsilon$-machine pour un `double`
+
+. . .
+
+Rappelez-vous vous l'avez fait en style **impératif** plus tôt.
+
+. . .
+
+```C
+double epsilon_machine(double eps) {
+    if (1.0 + eps != 1.0) {
+        return epsilon_machine(eps / 2.0);
+    } else {
+        return eps;
+    }
+}
+```
+
+# La récursivité (4/4)
+
+\footnotesize
+
+## Exercice: que fait ce code récursif?
+
+```C
+void recurse(int n) {
+    printf("%d ", n % 2);
+    if (n / 2 != 0) {
+        recurse(n / 2);
+    } else {
+        printf("\n");
+    }
+}
+recurse(13); 
+```
+
+. . .
+
+```C
+recurse(13): n = 13, n % 2 = 1, n / 2 = 6,
+    recurse(6): n = 6, n % 2 = 0, n / 2 = 3,
+        recurse(3): n = 3, n % 2 = 1, n / 2 = 1,
+            recurse(1): n = 1, n % 2 = 1, n / 2 = 0.
+
+// affiche: 1 1 0 1
+```
+
+. . .
+
+Affiche la représentation binaire d'un nombre!
+
+# Exercice: réusinage et récursivité (1/4)
+
+## Réusiner le code du PGCD avec une fonction récursive
+
+## Étudier l'exécution
+
+```C
+42 = 27 * 1 + 15
+27 = 15 * 1 + 12
+15 = 12 * 1 + 3
+12 = 3  * 4 + 0
+```
+
+# Exercice: réusinage et récursivité (2/4)
+
+## Réusiner le code du PGCD avec une fonction récursive
+
+## Étudier l'exécution
+
+```C
+42 = 27 * 1 + 15   |   PGCD(42, 27) 
+27 = 15 * 1 + 12   |   PGCD(27, 15) 
+15 = 12 * 1 +  3   |   PGCD(15, 12) 
+12 =  3 * 4 +  0   |   PGCD(12,  3) 
+```
+
+# Exercice: réusinage et récursivité (3/4)
+
+## Réusiner le code du PGCD avec une fonction récursive
+
+## Étudier l'exécution
+
+```C
+42 = 27 * 1 + 15   |   PGCD(42, 27) 
+27 = 15 * 1 + 12   |   PGCD(27, 15) 
+15 = 12 * 1 +  3   |   PGCD(15, 12) 
+12 =  3 * 4 +  0   |   PGCD(12,  3) 
+```
+
+## Effectuer l'empilage - dépilage
+
+. . .
+
+```C
+PGCD(12,  3)    |     3
+PGCD(15, 12)    |     3
+PGCD(27, 15)    |     3
+PGCD(42, 27)    |     3
+```
+
+# Exercice: réusinage et récursivité (4/4)
+
+## Écrire le code
+
+. . .
+
+```C
+int pgcd(int n, int m) {
+    if (n % m > 0) {
+        return pgcd(m, n % m);
+    } else {
+        return m;
+    }
+}
+```
+
+# La suite de Fibonacci (1/2)
+
+## Règle
+
+$$
+\mathrm{Fib}(n) = \mathrm{Fib}(n-1) + \mathrm{Fib}(n-2),\quad
+\mathrm{Fib}(0)=0,\quad \mathrm{Fib}(1)=1.
+$$
+
+## Exercice: écrire la fonction $\mathrm{Fib}$ en récursif et impératif
+
+. . .
+
+## En récursif (6 lignes)
+
+```C
+int fib(int n) {
+    if (n > 1) {
+        return fib(n - 1) + fib(n - 2);
+    } 
+    return n;
+}
+```
+
+# La suite de Fibonacci (2/2)
+
+## Et en impératif (11 lignes)
+
+```C
+int fib_imp(int n) {
+    int fib0 = 1;
+    int fib1 = 1;
+    int fib  = n == 0 ? 0 : fib1;
+    for (int i = 2; i < n; ++i) {
+        fib  = fib0 + fib1;
+        fib0 = fib1;
+        fib1 = fib;
+    }
+    return fib;
+}
+```
+
+# Exponentiation rapide ou indienne (1/4)
+
+## But: Calculer $x^n$
+
+* Quel est l'algorithmie le plus simple que vous pouvez imaginer?
+
+. . .
+
+```C
+int pow(int x, int n) {
+    if (0 == n) {
+        return 1;
+    }
+    for (int i = 1; i < n; ++i) {
+        x = x * x; // x *= x
+    }
+    return x;
+}
+```
+
+* Combien de multiplication et d'assignations en fonction de `n`?
+
+. . .
+
+* `n` assignations et `n` multiplications.
+
+# Exponentiation rapide ou indienne (2/4)
+
+* Proposez un algorithme naïf et récursif
+
+. . .
+
+```C
+int pow(x, n) {
+    if (n != 0) {
+        return x * pow(x, n-1);
+    } else {
+        return 1;
+    }
+}
+```
+
+# Exponentiation rapide ou indienne (3/4)
+
+## Exponentiation rapide ou indienne de $x^n$
+
+* Écrivons $n=\sum_{i=0}^{d-1}b_i 2^i,\ b_i=\{0,1\}$ (écriture binaire sur $d$ bits, avec
+$d\sim\log_2(n)$).
+* 
+$$
+x^n={x^{2^0}}^{b_0}\cdot {x^{2^1}}^{b_1}\cdots {x^{2^{d-1}}}^{b_{d-1}}.
+$$
+* On a besoin de $d$ calculs pour les $x^{2^i}$.
+* On a besoin de $d$ calculs pour évaluer les produits de tous les termes.
+
+## Combien de calculs en terme de $n$?
+
+. . .
+
+* $n$ est représenté en binaire avec $d$ bits $\Rightarrow d\sim\log_2(n)$.
+* il y a $2\log_2(n)\sim \log_2(n)$ calculs.
+
+# Exponentiation rapide ou indienne (4/4)
+
+## Le vrai algorithme
+
+* Si n est pair: calculer $\left(x^{n/2}\right)^2$,
+* Si n est impair: calculer $x \cdot \left(x^{(n-1)/2}\right)^2$.
+
+## Exercice: écrire l'algorithme récursif correspondant
+
+. . .
+
+```C
+double pow(double x, int n) {
+    if (1 == n) {
+        return x;
+    } else if (n % 2 == 0) {
+        return pow(x, n / 2) * pow(x, n/2);
+    } else {
+        return x * pow(x, (n-1));
+    }
+}
+```
+
+
+# Efficacité d'un algorithmique
+
+Comment mesurer l'efficacité d'un algorithme?
+
+. . .
+
+* Mesurer le temps CPU,
+* Mesurer le temps d'accès à la mémoire,
+* Mesurer la place prise mémoire,
+
+. . .
+
+Dépendant du **matériel**, du **compilateur**, des **options de compilation**, etc!
+
+## Mesure du temps CPU
+
+```C
+#include <time.h>
+struct timespec tstart={0,0}, tend={0,0};
+clock_gettime(CLOCK_MONOTONIC, &tstart);
+// some computation
+clock_gettime(CLOCK_MONOTONIC, &tend);
+printf("computation about %.5f seconds\n",
+       ((double)tend.tv_sec + 1e-9*tend.tv_nsec) - 
+       ((double)tstart.tv_sec + 1e-9*tstart.tv_nsec));
+```
+
+# Programme simple: mesure du temps CPU
+
+## Preuve sur un [petit exemple](../source_codes/complexity/sum.c)
+
+```bash
+source_codes/complexity$ make bench
+RUN ONCE -O0
+the computation took about 0.00836 seconds
+RUN ONCE -O3
+the computation took about 0.00203 seconds
+RUN THOUSAND TIMES -O0
+the computation took about 0.00363 seconds
+RUN THOUSAND TIMES -O3
+the computation took about 0.00046 seconds
+```
+
+Et sur votre machine les résultats seront **différents**.
+
+. . .
+
+## Conclusion
+
+* Nécessité d'avoir une mesure indépendante du/de la
+  matériel/compilateur/façon de mesurer/météo.
+
+# Analyse de complexité algorithmique (1/4)
+
+* On analyse le **temps** pris par un algorithme en fonction de la **taille de
+  l'entrée**.
+
+## Exemple: recherche d'un élément dans une liste triée de taille N
+
+```C
+int sorted_list[N];
+bool in_list = is_present(N, sorted_list, elem);
+```
+
+* Plus `N` est grand, plus l'algorithme prend de temps sauf si...
+
+. . .
+
+* l'élément est le premier de la liste (ou à une position toujours la même).
+* ce genre de cas pathologique ne rentre pas en ligne de compte.
+
+# Analyse de complexité algorithmique (2/4)
+
+## Recherche linéaire
+
+```C
+bool is_present(int n, int tab[], int elem) {
+    for (int i = 0; i < n; ++i) {
+        if (tab[i] == elem) {
+            return true;
+        } else if (elem < tab[i]) {
+            return false;
+        }
+    }
+    return false;
+}
+```
+
+* Dans le **meilleurs des cas** il faut `1` comparaison.
+* Dans le **pire des cas** (élément absent p.ex.) il faut `n` comparaisons.
+
+. . .
+
+La **complexité algorithmique** est proportionnelle à `N`: on double la taille
+du tableau $\Rightarrow$ on double le temps pris par l'algorithme.
+
+# Analyse de complexité algorithmique (3/4)
+
+## Recherche dichotomique
+
+```C
+bool is_present_binary_search(int n, int tab[], int elem) {
+    int left  = 0;
+    int right = n - 1;
+    while (left <= right) {
+        int mid = (right + left) / 2;
+        if (tab[mid] < elem) {
+            left = mid + 1;
+        } else if (tab[mid] > elem) {
+            right = mid - 1;
+        } else {
+            return true;
+        }
+    }
+    return false;
+}
+```
+
+# Analyse de complexité algorithmique (4/4)
+
+## Recherche dichotomique
+
+![Source: [Wikipédia](https://upload.wikimedia.org/wikipedia/commons/a/aa/Binary_search_complexity.svg)](figs/Binary_search_complexity.svg){width=80%}
+
+. . .
+
+* Dans le **meilleurs de cas** il faut `1` comparaison.
+* Dans le **pire des cas** il faut $\log_2(N)+1$ comparaisons
+
+. . .
+
+## Linéaire vs dichotomique
+
+* $N$ vs $\log_2(N)$ comparaisons logiques.
+* Pour $N=1000000$: `1000000` vs `21` comparaisons.
+
+# Notation pour la complexité
+
+## Constante de proportionnalité
+
+* Pour la recherche linéaire ou dichotomique, on a des algorithmes qui sont $\sim N$ ou $\sim \log_2(N)$
+* Qu'est-ce que cela veut dire?
+
+. . .
+
+* Temps de calcul est $t=C\cdot N$ (où $C$ est le temps pris pour une comparaisons sur une machine/compilateur donné)
+* La complexité ne dépend pas de $C$.
+
+## Le $\mathcal{O}$ de Leibnitz
+
+* Pour noter la complexité d'un algorithme on utilise le symbole $\mathcal{O}$ (ou "grand Ô de").
+* Les complexités les plus couramment rencontrées sont
+
+. . .
+
+$$
+\mathcal{O}(1),\quad \mathcal{O}(\log(N)),\quad \mathcal{O}(N),\quad
+\mathcal{O}(\log(N)\cdot N), \quad \mathcal{O}(N^2), \quad
+\mathcal{O}(N^3).
+$$
+
+# Ordres de grandeur
+
+\begin{table}[!h]  
+\begin{center} 
+\caption{Valeurs approximatives de quelques fonctions usuelles de complexité.} 
+\medskip 
+\begin{tabular}{|c|c|c|c|c|} 
+\hline 
+$\log_2(N)$ & $\sqrt{N}$      & $N$    & $N\log_2(N)$    & $N^2$     \\ 
+\hline\hline 
+$3$         & $3$             & $10$   & $30$            & $10^2$    \\ 
+\hline 
+$6$         & $10$            & $10^2$ & $6\cdot 10^2$   & $10^4$    \\ 
+\hline 
+$9$         & $31$            & $10^3$ & $9\cdot 10^3$   & $10^6$    \\ 
+\hline 
+$13$        & $10^2$          & $10^4$ & $1.3\cdot 10^5$ & $10^8$    \\ 
+\hline 
+$16$        & $3.1\cdot 10^2$ & $10^5$ & $1.6\cdot 10^6$ & $10^{10}$ \\ 
+\hline 
+$19$        & $10^3$          & $10^6$ & $1.9\cdot 10^7$ & $10^{12}$ \\ 
+\hline 
+\end{tabular} 
+\end{center} 
+\end{table} 
+
+
+# Quelques exercices (1/3)
+
+## Complexité de l'algorithme de test de primalité naïf?
+
+```C
+for (i = 2; i < sqrt(N); ++i) {
+    if (N % i == 0) {
+        return false;
+    }
+}
+return true;
+```
+
+. . .
+
+## Réponse 
+
+$$
+\mathcal{O}(\sqrt{N}).
+$$
+
+# Quelques exercices (2/3)
+
+## Complexité de trouver le minimum d'un tableau?
+
+```C
+int min = MAX;
+for (i = 0; i < N; ++i) {
+    if (tab[i] < min) {
+        min = tab[i];
+    }
+}
+return min;
+```
+
+. . .
+
+## Réponse 
+
+$$
+\mathcal{O}(N).
+$$
+
+# Quelques exercices (3/3)
+
+## Complexité du tri par sélection?
+
+```C
+int ind = 0
+while (ind < SIZE-1) {
+    min = find_min(tab[ind:SIZE]);
+    swap(min, tab[ind]);
+    ind += 1
+}
+```
+
+. . .
+
+## Réponse
+
+### `min = find_min`
+
+$$
+(N-1)+(N-2)+...+2+1=\sum_{i=1}^{N-1}i=N\cdot(N-1)/2=\mathcal{O}(N^2).
+$$
+
+## Finalement
+
+$$
+\mathcal{O}(N^2\mbox{ comparaisons}) + \mathcal{O}(N\mbox{swaps})=\mathcal{O}(N^2).
+$$
+
+