From 3cdf061bd30c422bee9f5206ec930776a11d6b19 Mon Sep 17 00:00:00 2001
From: Orestis <orestis.malaspinas@pm.me>
Date: Sun, 17 Sep 2023 22:49:27 +0200
Subject: [PATCH] cours 1 updated

---
 slides/cours_10.md |  402 --------------
 slides/cours_11.md |  514 ------------------
 slides/cours_12.md |  409 --------------
 slides/cours_13.md |  605 ---------------------
 slides/cours_14.md |  367 -------------
 slides/cours_15.md |  929 --------------------------------
 slides/cours_16.md | 1277 --------------------------------------------
 slides/cours_17.md |  695 ------------------------
 slides/cours_18.md |  947 --------------------------------
 slides/cours_19.md |  488 -----------------
 slides/cours_2.md  |  317 -----------
 slides/cours_20.md |  795 ---------------------------
 slides/cours_21.md |  731 -------------------------
 slides/cours_22.md |  351 ------------
 slides/cours_23.md | 1013 -----------------------------------
 slides/cours_24.md |  709 ------------------------
 slides/cours_25.md | 1077 -------------------------------------
 slides/cours_3.md  |  339 ------------
 slides/cours_4.md  |  851 -----------------------------
 slides/cours_5.md  |  834 -----------------------------
 slides/cours_6.md  |  488 -----------------
 slides/cours_7.md  |  295 ----------
 slides/cours_8.md  |  281 ----------
 slides/cours_9.md  |  304 -----------
 24 files changed, 15018 deletions(-)
 delete mode 100644 slides/cours_10.md
 delete mode 100644 slides/cours_11.md
 delete mode 100644 slides/cours_12.md
 delete mode 100644 slides/cours_13.md
 delete mode 100644 slides/cours_14.md
 delete mode 100644 slides/cours_15.md
 delete mode 100644 slides/cours_16.md
 delete mode 100644 slides/cours_17.md
 delete mode 100644 slides/cours_18.md
 delete mode 100644 slides/cours_19.md
 delete mode 100644 slides/cours_2.md
 delete mode 100644 slides/cours_20.md
 delete mode 100644 slides/cours_21.md
 delete mode 100644 slides/cours_22.md
 delete mode 100644 slides/cours_23.md
 delete mode 100644 slides/cours_24.md
 delete mode 100644 slides/cours_25.md
 delete mode 100644 slides/cours_3.md
 delete mode 100644 slides/cours_4.md
 delete mode 100644 slides/cours_5.md
 delete mode 100644 slides/cours_6.md
 delete mode 100644 slides/cours_7.md
 delete mode 100644 slides/cours_8.md
 delete mode 100644 slides/cours_9.md

diff --git a/slides/cours_10.md b/slides/cours_10.md
deleted file mode 100644
index 5af82c0..0000000
--- a/slides/cours_10.md
+++ /dev/null
@@ -1,402 +0,0 @@
----
-title: "Piles"
-date: "2022-12-14"
-patat:
-  eval:
-    tai:
-      command: fish
-      fragment: false
-      replace: true
-    ccc:
-      command: fish
-      fragment: false
-      replace: true
-  images:
-    backend: auto
----
-
-# Rappel
-
-## Qu'est-ce qu'une pile?
-
-. . .
-
-* Structure de données LIFO.
-
-## Quelles fonctionnalités?
-
-. . .
-
-1. Empiler (push): ajouter un élément sur la pile.
-2. Dépiler (pop): retirer l'élément du sommet de la pile et le retrouner.
-3. Liste vide? (is_empty?).
-4. Jeter un oeil (peek): retourner l'élément du sommet de la pile (sans le dépiler).
-5. Nombre d'éléments (length).
-
-# Le tri à deux piles (3/3)
-
-## Exercice: trier le tableau `[2, 10, 5, 20, 15]`
-
-```C
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-```
-
-# La calculatrice (1/8)
-
-## Vocabulaire
-
-```C
-2 + 3 = 2 3 +,
-```
-
-`2` et `3` sont les *opérandes*, `+` l'*opérateur*.
-
-. . .
-
-## La notation infixe
-
-```C
-2 * (3 + 2) - 4 = 6.
-```
-
-## La notation postfixe
-
-```C
-2 3 2 + * 4 - = 6.
-```
-
-## Exercice: écrire `2 * 3 * 4 + 2` en notation `postfixe`
-
-. . .
-
-```C
-2 3 4 * * 2 + = (2 * (3 * 4)) + 2.
-```
-
-# La calculatrice (2/8)
-
-## De infixe à post-fixe
-
-* Une *pile* est utilisée pour stocker *opérateurs* et *parenthèses*.
-* Les opérateurs on des *priorités* différentes.
-
-```C
-^   : priorité 3
-* / : priorité 2
-+ - : priorité 1
-( ) : priorité 0 // pas un opérateur mais bon
-```
-
-
-# La calculatrice (3/8)
-
-## De infixe à post-fixe: algorithme
-
-* On lit l'expression infixe de gauche à droite.
-
-* On examine le prochain caractère de l'expression infixe.
-    * Si opérande, le placer dans l'expression du résultat.
-    * Si parenthèse le mettre dans la pile (priorité 0).
-    * Si opérateur, comparer sa priorité avec celui du sommet de la pile:
-        * Si sa priorité est plus élevée, empiler.
-        * Sinon dépiler l'opérateur de la pile dans l'expression du résultat et
-          recommencer jusqu'à apparition d'un opérateur de priorité plus faible
-          au sommet de la pile (ou pile vide).
-    * Si parenthèse fermée, dépiler les opérateurs du sommet de la pile et les
-      placer dans l'expression du résultat, jusqu'à ce qu'une parenthèse
-      ouverte apparaisse au sommet, dépiler également la parenthèse.
-    * Si il n'y a pas de caractère dans l'expression dépiler tous les
-      opérateurs dans le résultat.
-
-# La calculatrice (4/8)
-
-## De infixe à post-fixe: exemple
-
-```C
-Infixe              Postfixe            Pile    Priorité
-((A*B)/D-F)/(G+H)   Vide                Vide    Néant
- (A*B)/D-F)/(G+H)   Vide                (       0
-  A*B)/D-F)/(G+H)   Vide                ((      0
-   *B)/D-F)/(G+H)   A                   ((      0
-    B)/D-F)/(G+H)   A                   ((*     2
-     )/D-F)/(G+H)   AB                  ((*     2
-      /D-F)/(G+H)   AB*                 (       0
-       D-F)/(G+H)   AB*                 (/      2
-        -F)/(G+H)   AB*D                (/      2
-         F)/(G+H)   AB*D/               (-      1
-          )/(G+H)   AB*D/F              (-      1
-           /(G+H)   AB*D/F-             Vide    Néant
-```
-
-# La calculatrice (5/8)
-
-## De infixe à post-fixe: exemple
-
-```C
-Infixe              Postfixe            Pile    Priorité
-((A*B)/D-F)/(G+H)   Vide                Vide    Néant
---------------------------------------------------------
-           /(G+H)   AB*D/F-             Vide    Néant
-            (G+H)   AB*D/F-             /       2
-             G+H)   AB*D/F-             /(      0
-              +H)   AB*D/F-G            /(      0
-               H)   AB*D/F-G            /(+     1
-                )   AB*D/F-GH           /(+     1
-             Vide   AB*D/F-GH+          /       2
-             Vide   AB*D/F-GH+/         Vide    Néant
-```
-
-# La calculatrice (6/8)
-
-\footnotesize
-
-## Exercice: écrire le code et le poster sur matrix
-
-* Quelle est la signature de la fonction?
-
-. . .
-
-* Une sorte de corrigé:
-
-```C
-char *infix_to_postfix(char* infix) { // init and alloc stack and postfix
-    for (size_t i = 0; i < strlen(infix); ++i) {
-        if (is_operand(infix[i])) { 
-            // we just add operands in the new postfix string
-        } else if (infix[i] == '(') { 
-            // we push opening parenthesis into the stack
-        } else if (infix[i] == ')') { 
-            // we pop everything into the postfix
-        } else if (is_operator(infix[i])) {
-            // this is an operator. We add it to the postfix based 
-            // on the priority of what is already in the stack and push it
-        }    
-    } 
-    // pop all the operators from the s at the end of postfix
-    // and end the postfix with `\0`
-    return postfix;
-} 
-```
-
-
-# La calculatrice (7/8)
-
-## Évaluation d'expression postfixe: algorithme
-
-* Chaque *opérateur* porte sur les deux opérandes qui le précèdent.
-* Le *résultat d'une opération* est un nouvel *opérande* qui est remis au
-  sommet de la pile.
-
-## Exemple
-
-```C
-2 3 4 + * 5 - = ?
-```
-
-* On parcours de gauche à droite:
-
-```C
-Caractère lu        Pile opérandes
-    2               2
-    3               2, 3
-    4               2, 3, 4
-    +               2, (3 + 4)
-    *               2 * 7
-    5               14, 5
-    -               14 - 5 = 9
-```
-
-# La calculatrice (8/8)
-
-## Évaluation d'expression postfixe: algorithme
-
-1. La valeur d'un opérande est *toujours* empilée.
-2. L'opérateur s'applique *toujours* au 2 opérandes au sommet.
-3. Le résultat est remis au sommet.
-
-## Exercice: écrire l'algorithme en C (et poster sur matrix)
-
-. . .
-
-```C
-bool evaluate(char *postfix, double *val) { // init stack
-    for (size_t i = 0; i < strlen(postfix); ++i) {
-        if (is_operand(postfix[i])) {
-            stack_push(&s, postfix[i]);
-        } else if (is_operator(postfix[i])) {
-            double rhs = stack_pop(&s);
-            double lhs = stack_pop(&s);
-            stack_push(&s, op(postfix[i], lhs, rhs));
-        }    
-    }
-    return stack_pop(&s);
-}
-```
-
-
-
-# La liste chaînée et pile (1/6)
-
-## Structure de données
-
-* Chaque élément de la liste contient:
-    1. une valeur,
-    2. un pointeur vers le prochain élément.
-* La pile est un pointeur vers le premier élément.
-
-![Un exemple de liste chaînée.](figs/Singly-linked-list.svg){width=80%}
-
-# La liste chaînée et pile (2/6)
-
-## Une pile-liste-chaînée
-
-```C
-typedef struct _element {
-    int data;
-    struct _element *next;
-} element;
-typedef element* stack;
-```
-
-## Fonctionnalités?
-
-. . .
-
-```C
-void stack_create(stack *s); // *s = NULL;
-void stack_destroy(stack *s);
-void stack_push(stack *s, int val);
-void stack_pop(stack *s, int *val);
-void stack_peek(stack s, int *val);
-bool stack_is_empty(stack s); // reutrn NULL == stack;
-```
-
-# La liste chaînée et pile (3/6)
-
-## Empiler? (faire un dessin)
-
-. . .
-
-```C
-
-
-
-
-
-
-
-```
-
-## Empiler? (le code ensemble)
-
-. . .
-
-```C
-void stack_push(stack *s, int val) {
-    element *elem = malloc(sizeof(*elem));
-    elem->data = val;
-    elem->next = *s;
-    s = elem;
-}
-```
-
-# La liste chaînée et pile (4/6)
-
-## Jeter un oeil? (faire un dessin)
-
-. . .
-
-```C
-
-
-
-
-
-
-
-```
-
-## Jeter un oeil? (le code ensemble)
-
-. . .
-
-```C
-void stack_peek(stack s, int *val) {
-    *val = s->data;
-}
-```
-
-# La liste chaînée et pile (5/6)
-
-## Dépiler? (faire un dessin)
-
-. . .
-
-```C
-
-
-
-
-
-
-
-```
-
-## Dépiler? (le code ensemble)
-
-. . .
-
-```C
-void stack_pop(stack *s, int *val) {
-    stack_peek(*s, val);
-    element *tmp = *s;
-    *s = (*s)->next;
-    free(tmp);
-    return val;
-}
-```
-
-# La liste chaînée et pile (6/6)
-
-## Détruire? (faire un dessin)
-
-. . .
-
-```C
-
-
-
-
-
-
-
-```
-
-## Détruire? (le code ensemble)
-
-. . .
-
-```C
-void stack_destroy(stack *s) {
-    while (!stack_is_empty(*s)) {
-        int val = stack_pop(s);
-    }
-}
-```
-
-
diff --git a/slides/cours_11.md b/slides/cours_11.md
deleted file mode 100644
index 13e2536..0000000
--- a/slides/cours_11.md
+++ /dev/null
@@ -1,514 +0,0 @@
----
-title: "Files d'attente et listes triées"
-date: "2022-12-21"
----
-
-# La file d'attente (1/N)
-
-* Structure de données abstraite permettant le stockage d'éléments.
-* *FIFO*: First In First Out, ou première entrée première sortie.
-* Analogue de la vie "réelle"":
-    * File à un guichet,
-    * Serveur d'impressions,
-    * Mémoire tampon, ...
-
-## Fonctionnalités
- 
- . . .
-
-* Enfiler: ajouter un élément à la fin de la file.
-* Défiler: extraire un élément au devant de la file.
-* Tester si la file est vide.
-
-. . .
-
-* Lire l'élément de la fin de la file.
-* Lire l'élément du devant de la file.
-* Créer une liste vide.
-* Détruire une liste vide.
-
-# La file d'attente (2/N)
-
-\footnotesize
-
-## Implémentation possible
-
-* La structure file, contient un pointeur vers la tête et un vers le début de la file.
-* Entre les deux, les éléments sont stockés dans une liste chaînée.
-
-![Illustration d'une file d'attente.](figs/fig_queue_representation.png){width=80%}
-
-## Structure de données en C?
-
-. . .
-
-```C
-typedef struct _element {  // Elément de liste
-   int data;
-   struct _element* next;
-} element;
-typedef struct _queue {    // File d'attente:
-   element* head;  //    tête de file d'attente
-   element* tail;  //    queue de file d'attente
-} queue;
-```
-
-# Fonctionnalités d'une file d'attente
-
-## Creation et consultations
-
-. . .
-
-```C
-void queue_init(queue *fa); // head = tail = NULL
-bool queue_is_empty(queue fa); // fa.head == fa.tail == NULL
-int queue_tail(queue fa); // return fa.head->data
-int queue_head(queue fa); // return fa.tail->data
-```
-
-## Manipulations et destruction
-
-. . .
-
-```C
-void queue_enqueue(queue *fa, int val);
-// adds an element before the tail
-int queue_dequeue(queue *fa);
-// removes the head and returns stored value
-void queue_destroy(queue *fa);
-// dequeues everything into oblivion
-```
-
-# Enfilage
-
-## Deux cas différents:
-
-1. La file est vide (faire un dessin):
-
-. . .
-
-![Insertion dans une file d'attente vide.](./figs/fig_empty_queue_insert.png){width=40%}
-
-2. La file n'est pas vide (faire un dessin):
-
-. . .
-
-![Insertion dans une file d'attente non-vide.](./figs/fig_non_empty_queue_insert.png){width=70%}
-
-# Enfilage
-
-## Live (implémentation)
-
-. . .
-
-```C
-void queue_enqueue(queue *fa, int val) {
-    element* elmt = malloc(sizeof(*elmt));
-    elmt->data = val;
-    elmt->next = NULL;
-    if (queue_is_empty(*fa)) {
-        fa->head = elmt;
-        fa->tail = elmt;
-    } else {
-        fa->tail->next = elmt;
-        fa->tail = elmt;
-    }
-}
-```
-
-# Défilage
-
-## Trois cas différents
-
-1. La file a plus d'un élément (faire un dessin):
-
-. . .
-
-![Extraction d'une file d'attente](./figs/fig_queue_extract.png){width=80%}
-
-2. La file un seul élément (faire un dessin):
-
-. . .
-
-![Extraction d'une file d'attente de longueur 1.](./figs/fig_queue_extract_one.svg){width=25%}
-
-
-3. La file est vide (problème)
-
-# Défilage
-
-## Live (implémentation)
-
-. . .
-
-```C
-int queue_dequeue(queue *fa) {
-    element* elmt = fa->head;
-    int val = elmt->data;
-    fa->head = fa->head->next;
-    free(elmt);
-    if (NULL == fa->head) {
-        fa->tail = NULL;
-    }
-    return val;
-}
-```
-
-. . .
-
-## Problème avec cette implémentation?
-
-# Destruction
-
-## Comment on faire la désallocation?
-
-. . .
-
-On défile jusqu'à ce que la file soit vide!
-
-# Complexité
-
-## Quelle sont les complexité de:
-
-* Enfiler?
-
-. . .
-
-* Défiler?
-
-. . .
-
-* Détruire?
-
-. . .
-
-* Est vide?
-
-
-# Implémentation alternative
-
-## Comment implémenter la file autrement?
-
-. . .
-
-* Données stockées dans un tableau;
-* Tableau de taille connue à la compilation ou pas (réallouable);
-* `tail` seraient les indices du tableau;
-* `capacity` seraient la capacité maximale;
-* On *enfile* "au bout" du tableau, au défile au début (indice `0`).
-
-. . .
-
-## Structure de données
-
-```C
-typedef struct _queue {
-    int *data;
-    int tail, capacity;
-} queue;
-```
-
-# File basée sur un tableau
-
-* Initialisation?
-
-. . .
-
-```C
-
-
-
-
-```
-
-* Est vide?
-
-. . .
-
-```C
-
-
-
-
-```
-
-
-* Enfiler?
-
-. . .
-
-```C
-
-
-
-
-```
-
-* Défiler?
-
-. . .
-
-```C
-
-
-
-
-```
-
-# Complexité
-
-## Quelle sont les complexités de:
-
-* Initialisation?
-
-. . .
-
-```C
-
-
-
-
-```
-
-* Est vide?
-
-. . .
-
-```C
-
-```
-
-
-* Enfiler?
-
-. . .
-
-```C
-
-
-
-
-```
-
-* Défiler?
-
-. . .
-
-```C
-
-
-
-
-```
-
-# Une file plus efficace
-
-## Comment faire une file plus efficace?
-
-* Où est-ce que ça coince?
-
-. . .
-
-* Défiler est particulièrement lent $\mathcal{O}(N)$.
-
-## Solution?
-
-. . .
-
-* Utiliser un indice séparé pour `head`.
-
-```C
-typedef struct _queue {
-    int *data;
-    int head, tail, capacity;
-} queue;
-```
-
-# Une file plus efficace (implémentation)
-
-## Enfilage
-
-\footnotesize
-
-```C
-void queue_enqueue(queue *fa, int val) {
-    if ((fa->head == 0 && fa->tail == fa->capacity-1) ||
-            (fa->tail == (fa->head-1) % (fa->capacity-1))) {
-        return; // queue is full
-    }
-    if (fa->head == -1) { // queue was empty
-        fa->head = fa->tail = 0;
-        fa->data[fa->tail] = val;
-    } else if (fa->tail == fa->capacity-1 && fa->head != 0) {
-        // the tail reached the end of the array
-        fa->tail = 0;
-        fa->data[fa->tail] = val;
-    } else {
-        // nothing particular
-        fa->tail += 1;
-        fa->data[fa->tail] = val;
-    }
-}
-```
-
-# Une file plus efficace (implémentation)
-
-## Défilage
-
-```C
-void queue_dequeue(queue *fa, int *val) {
-    if (queue_is_empty(*fa)) {
-        return; // queue is empty
-    }
-    *val = fa->data[fa->head];
-    if (fa->head == fa->tail) { // that was the last element
-        fa->head = fa->tail = -1;
-    } else if (fa->head == fa->capacity-1) {
-        fa->head = 0;
-    } else {
-        fa->head += 1;
-    }
-}
-```
-
-
-# Les listes triées
-
-Une liste chaînée triée est:
-
-* une liste chaînée
-* dont les éléments sont insérés dans l'ordre.
-
-![Exemple de liste triée.](./figs/sorted_list_example.svg)
-
-. . .
-
-* L'insertion est faite telle que l'ordre est maintenu.
-
-## Quelle structure de données?
-
-```C
-
-
-
-
-
-```
-
-# Les listes triées
-
-## Quel but?
-
-* Permet de retrouver rapidement un élément.
-* Utile pour la recherche de plus court chemin dans des graphes.
-* Ordonnancement de processus par degré de priorité.
-
-## Comment?
-
-* Les implémentations les plus efficaces se basent sur les tableaux.
-* Possibles aussi avec des listes chaînées.
-
-# Les listes triées
-
-\footnotesize
-
-## Quelle structure de données dans notre cas?
-
-
-Une liste chaînée bien sûr (oui c'est pour vous entraîner)!
-
-```C
-typedef struct _element { // chaque élément
-    int data;
-    struct _element *next;
-} element;
-typedef element* sorted_list; // la liste
-```
-
-## Fonctionnalités
-
-```C
-// insertion de val
-sorted_list sorted_list_push(sorted_list list, int val);
-// la liste est-elle vide?
-bool is_empty(sorted_list list); // list == NULL
-// extraction de val (il disparaît)
-sorted_list sorted_list_extract(sorted_list list, int val); 
- // rechercher un élément et le retourner
-element* sorted_list_search(sorted_list list, int val);
-```
-
-# L'insertion
-
-## Trois cas
-
-1. La liste est vide.
-
-. . .
-
-![Insertion dans une liste vide, `list == NULL`.](figs/sorted_list_insert_one.svg){width=30%}
-
-. . .
-
-```C
-sorted_list sorted_list_push(sorted_list list, int val) {
-    if (sorted_list_is_empty(list)) {
-        list = malloc(sizeof(*list));
-        list->data = val;
-        list->next = NULL;
-        return list;
-    }
-}
-```
-
-# L'insertion
-
-2. L'insertion se fait en première position.
-
-. . .
-
-![Insertion en tête de liste, `list->data >=
-val`.](figs/sorted_list_insert_first.svg){width=80%}
-
-. . .
-
-```C
-sorted_list sorted_list_push(sorted_list list, int val) {
-    if (list->data >= val) {
-        element *tmp = malloc(sizeof(*tmp));
-        tmp->data = val;
-        tmp->next = list;
-        list = tmp;
-        return list;
-    }
-}
-```
-
-# L'insertion
-
-3. L'insertion se fait sur une autre position que la première.
-
-. . .
-
-![Insertion sur une autre position, list->data <
-val.](figs/sorted_list_insert_any.svg){width=70%}
-
-. . .
-
-\footnotesize
-
-```C
-sorted_list sorted_list_push(sorted_list list, int val) {
-    element *tmp = malloc(sizeof(*tmp));
-    tmp->data = val;
-    element *crt = list;
-    while (NULL != crt->next && val > crt->next->data) {
-        crt = crt->next;
-    }
-    tmp->next = crt->next;
-    crt->next = tmp;
-    return list;
-}
-```
-
-
diff --git a/slides/cours_12.md b/slides/cours_12.md
deleted file mode 100644
index c9646d2..0000000
--- a/slides/cours_12.md
+++ /dev/null
@@ -1,409 +0,0 @@
----
-title: "Listes triées et listes doublement chaînées"
-date: "2023-01-11"
----
-
-# Les listes triées
-
-Une liste chaînée triée est:
-
-* une liste chaînée
-* dont les éléments sont insérés dans l'ordre.
-
-![Exemple de liste triée.](./figs/sorted_list_example.svg)
-
-. . .
-
-* L'insertion est faite telle que l'ordre est maintenu.
-
-## Quelle structure de données?
-
-```C
-
-
-
-
-
-```
-
-# Les listes triées
-
-## Quel but?
-
-* Permet de retrouver rapidement un élément.
-* Utile pour la recherche de plus court chemin dans des graphes.
-* Ordonnancement de processus par degré de priorité.
-
-## Comment?
-
-* Les implémentations les plus efficaces se basent sur les tableaux.
-* Possibles aussi avec des listes chaînées.
-
-# Les listes triées
-
-## Quelle structure de données dans notre cas?
-
-
-Une liste chaînée bien sûr (oui c'est pour vous entraîner)!
-
-```C
-typedef struct _element { // chaque élément
-    int data;
-    struct _element *next;
-} element;
-typedef element* sorted_list; // la liste
-```
-
-## Fonctionnalités
-
-```C
-// insertion de val
-sorted_list sorted_list_push(sorted_list list, int val);
-// la liste est-elle vide?
-bool is_empty(sorted_list list); // list == NULL
-// extraction de val (il disparaît)
-sorted_list sorted_list_extract(sorted_list list, int val); 
- // rechercher un élément et le retourner
-element* sorted_list_search(sorted_list list, int val);
-```
-
-# L'insertion
-
-## Trois cas
-
-1. La liste est vide.
-
-. . .
-
-![Insertion dans une liste vide, `list == NULL`.](figs/sorted_list_insert_one.svg){width=30%}
-
-. . .
-
-```C
-sorted_list sorted_list_push(sorted_list list, int val) {
-    if (sorted_list_is_empty(list)) {
-        list = malloc(sizeof(*list));
-        list->data = val;
-        list->next = NULL;
-        return list;
-    }
-}
-```
-
-# L'insertion
-
-2. L'insertion se fait en première position.
-
-. . .
-
-![Insertion en tête de liste, `list->data >=
-val`.](figs/sorted_list_insert_first.svg){width=80%}
-
-. . .
-
-```C
-sorted_list sorted_list_push(sorted_list list, int val) {
-    if (list->data >= val) {
-        element *tmp = malloc(sizeof(*tmp));
-        tmp->data = val;
-        tmp->next = list;
-        list = tmp;
-        return list;
-    }
-}
-```
-
-# L'insertion
-
-3. L'insertion se fait sur une autre position que la première.
-
-. . .
-
-![Insertion sur une autre position, list->data <
-val.](figs/sorted_list_insert_any.svg){width=70%}
-
-. . .
-
-\footnotesize
-
-```C
-sorted_list sorted_list_push(sorted_list list, int val) {
-    element *tmp = malloc(sizeof(*tmp));
-    tmp->data = val;
-    element *crt = list;
-    while (NULL != crt->next && val > crt->next->data) {
-        crt = crt->next;
-    }
-    tmp->next = crt->next;
-    crt->next = tmp;
-    return list;
-}
-```
-
-
-# L'extraction
-
-## Trois cas
-
-1. L'élément à extraire n'est **pas** le premier élément de la liste
-
-. . .
-
-![Extraction d'un élément qui n'est pas le premier.](figs/sorted_list_extract_any.svg){width=70%}
-
-. . .
-
-\scriptsize
-
-```C
-sorted_list sorted_list_extract(sorted_list list, int val) {
-    element *prec = *crt = list; // needed to glue elements together
-    while (NULL != crt && val > crt->data) {
-	   prec = crt;
-	   crt = crt->next;
-	}
-    if (NULL != crt && prec != crt && crt->data == val) { // glue things together
-        prec->next = crt->next;
-        free(crt);
-    }
-    return list;
-}
-```
-
-
-# L'extraction
-
-2. L'élément à extraire est le premier élément de la liste
-
-. . .
-
-![Extraction d'un élément qui est le premier.](figs/sorted_list_extract_first.svg){width=70%}
-
-. . .
-
-\footnotesize
-
-```C
-sorted_list sorted_list_extract(sorted_list list, int val) {
-    element *prec = *crt = list; // needed to glue elements together
-    while (NULL != crt && val > crt->data) {
-	   prec = crt;
-	   crt = crt->next;
-	}
-    if (NULL != crt && crt->data == val && prec == crt) { // glue things together
-        list = list->next;
-        free(crt);
-    }
-    return list;
-}
-```
-
-# L'extraction
-
-3. L'élément à extraire n'est **pas** dans la liste.
-    * La liste est vide.
-    * La valeur est plus grande que le dernier élément de la liste.
-    * La valeur est plus petite que la valeur de `crt`.
-
-. . .
-
-On retourne la liste inchangée.
-
-. . .
-
-\footnotesize
-
-```C
-sorted_list sorted_list_extract(sorted_list list, int val) {
-    element *prec = *crt = list; // needed to glue elements together
-    while (NULL != crt && val > crt->data) {
-	   prec = crt;
-	   crt = crt->next;
-	}
-    if (NULL == crt || crt->data != val) { // val not present
-        return list;
-    }
-}
-```
-
-# La recherche
-
-
-
-```C
-element* sorted_list_search(sorted_list list, int val);
-```
-
-* Retourne `NULL` si la valeur n'est pas présente (ou la liste vide).
-* Retourne un pointeur vers l'élément si la valeur est présente.
-
-. . .
-
-```C
-element* sorted_list_search(sorted_list list, int val) {
-    // search for element smaller than val
-    element* pos = sorted_list_position(list, val); 
-    if (NULL == pos && val == list->data) {
-        return list; // first element contains val
-    } else if (NULL != pos && NULL != pos->next && val == pos->next->data) {
-        return pos->next; // non-first element contains val
-    } else {
-        return NULL; // well... val's not here
-    }
-}
-```
-
-# La recherche
-
-## La fonction `sorted_list_position`
-
-```C
-element* sorted_list_position(sorted_list list, int val);
-```
-
-![Trois exemples de retour de la fonction `sorted_list_position()`.](figs/sorted_list_position.svg)
-
-# La recherche
-
-## Exercice: implémenter
-
-```C
-element* sorted_list_position(sorted_list list, int val);
-```
-
-. . .
-
-```C
-element* sorted_list_position(sorted_list list, int val) {
-    element* pos = list;
-    if (sorted_list_is_empty(list) || val <= list->data) {
-        pos = NULL;
-    } else {
-        while (NULL != pos->next && val > pos->next->data) {
-            pos = pos->next;
-        }
-    }
-    return pos;
-}
-```
-
-# Complexité de la liste chaînée triée
-
-## L'insertion?
-
-. . .
-
-$$
-\mathcal{O}(N).
-$$
-
-## L'extraction?
-
-. . .
-
-$$
-\mathcal{O}(N).
-$$
-
-## La recherche?
-
-. . .
-
-$$
-\mathcal{O}(N).
-$$
-
-
-# Liste doublement chaînée
-
-## Application: navigateur ou éditeur de texte
-
-* Avec une liste chaînée:
-    * Comment implémenter les fonctions `back` et `forward` d'un navigateur?
-    * Comment implémenter les fonctions `undo` et `redo` d'un éditeur de texte?
-
-. . .
-
-Pas possible.
-
-## Solution?
-
-. . .
-
-* Garder un pointeur supplémentaire sur l'élément précédent et pas seulement le
-  suivant.
-
-. . .
-
-* Cette structure de donnée est la **liste doublement chaînée** ou **doubly
-  linked list**.
-
-# Liste doublement chaînée
-
-## Exercices
-
-* Partir du dessin suivant et par **groupe de 5**
-
-![Un schéma de liste doublement chaînée d'entiers.](figs/doubly_linked_list.svg)
-
-1. Écrire les structures de données pour représenter la liste doublement
-   chaînée dont le type sera `dll` (pour
-   `doubly_linked_list`)
-
-# Liste doublement chaînée
-
-2. Écrire les fonctionnalités de création et consultation
-
-```C 
-// crée la liste doublement chaînée
-dll dll_create();
-// retourne la valeur à la position actuelle dans la liste
-int dll_value(dll list);
-// la liste est-elle vide?
-bool dll_is_empty(dll list);
-// Est-ce que pos est le 1er élément?
-bool dll_is_head(dll list);
-// Est-ce que pos est le dernier élément?
-bool dll_is_tail(dll list);
-// data est-elle dans la liste?
-bool dll_is_present(dll list, int data);
-// affiche la liste
-void dll_print(dll list);
-```
-
-# Liste doublement chaînée
-
-3. Écrire les fonctionnalités de manipulation 
-
-```C 
-// déplace pos au début de la liste
-dll dll_move_to_head(dll list);
-// déplace pos à la position suivante dans la liste
-dll dll_next(dll list);
-// déplace pos à la position précédente dans la liste
-dll dll_prev(dll list);
-```
-
-# Liste doublement chaînée
-
-4. Écrire les fonctionnalités d'insertion
-
-```C
-// insertion de data dans l'élément après pos
-dll dll_insert_after(dll list, int data);
-// insertion de data en tête de liste
-dll dll_push(dll list, int data);
-```
-
-5. Écrire les fonctionnalités d'extraction
-
-```C
-// extraction de la valeur se trouvant dans l'élément pos
-// l'élément pos est libéré
-int dll_extract(dll *list);
-// extrait la donnée en tête de liste
-int dll_pop(dll *list);
-// vide la liste
-void dll_destroy(dll *list)
-```
-
diff --git a/slides/cours_13.md b/slides/cours_13.md
deleted file mode 100644
index d6d3d13..0000000
--- a/slides/cours_13.md
+++ /dev/null
@@ -1,605 +0,0 @@
----
-title: "Tables de hachage"
-date: "2023-01-18"
----
-
-# Tableau vs Table
-
-## Tableau
-
-* Chaque élément (ou valeur) est lié à un indice (la case du tableau).
-
-```C 
-annuaire tab[2] = {
-    "+41 22 123 45 67", "+41 22 234 56 78", ...
-};
-tab[1] == "+41 22 123 45 67";
-```
-
-## Table
-
-* Chaque élément (ou valeur) est lié à une clé.
-
-```C 
-annuaire tab = {
-//  Clé   ,    Valeur
-    "Paul",    "+41 22 123 45 67",
-    "Orestis", "+41 22 234 56 78",
-};
-tab["Paul"]    == "+41 22 123 45 67";
-tab["Orestis"] == "+41 22 234 56 78";
-```
-
-# Table
-
-## Définition
-
-Structure de données abstraite où chaque *valeur* (ou élément) est associée à une *clé* (ou
-argument).
-
-On parle de paires *clé-valeur* (*key-value pairs*).
-
-## Donnez des exemples de telles paires
-
-. . .
-
-* Annuaire (nom-téléphone),
-* Catalogue (objet-prix),
-* Table de valeur fonctions (nombre-nombre),
-* Index (nombre-page)
-* ...
-
-# Table
-
-## Opérations principales sur les tables
-
-* Insertion d'élément (`insert(clé, valeur)`{.C}), insère la paire `clé-valeur`
-* Consultation (`get(clé)`{.C}), retourne la `valeur` correspondant à `clé`
-* Suppression (`remove(clé)`{.C}), supprime la paire `clé-valeur`
-
-## Structure de données / implémentation
-
-Efficacité dépend de différents paramètres:
-
-* taille (nombre de clé-valeurs maximal),
-* fréquence d'utilisation (insertion, consultation, suppression),
-* données triées/non-triées,
-* ...
-
-# Consultation séquentielle (`sequential_get`)
-
-## Séquentielle
-
-* table représentée par un (petit) tableau ou liste chaînée,
-* types: `key_t` et `value_t` quelconques, et `key_value_t`
-
-    ```C
-    typedef struct {
-        key_t key;
-        value_t value;
-    } key_value_t;
-    ```
-* on recherche l'existence de la clé séquentiellement dans le tableau, on
-  retourne la valeur.
-
-# Consultation séquentielle (`sequential_get`)
-
-## Implémentation? Une idée?
-
-. . .
-
-```C
-bool sequential_get(int n, key_value_t table[n], key_t key, 
-    value_t *value) 
-{
-    int pos = n - 1;
-    while (pos >= 0) {
-        if (key ==  table[pos].key) {
-            *value = table[pos].value;
-            return true;
-        }
-        pos--;
-    }
-    return false;
-}
-```
-
-. . .
-
-## Inconvénient?
-
-# Consultation séquentielle (`sequential_get`)
-
-## Exercice: implémenter la même fonction avec une liste chaînée
-
-Poster le résultat sur matrix.
-
-# Consultation dichotomique (`binary_get`)
-
-## Dichotomique
-
-* table représentée par un (petit) tableau trié par les clés,
-* types: `key_t` et `value_t` quelconques, et `key_value_t`
-* on recherche l'existence de la clé par dichotomie dans le tableau, on
-  retourne la valeur,
-* les clés possèdent la notion d'ordre (`<, >, =` sont définis).
-
-# Consultation dichotomique (`binary_get`)
-
-\footnotesize
-
-## Implémentation? Une idée?
-
-. . .
-
-```C
-bool binary_get1(int n, value_key_t table[n], key_t key, value_t *value) {
-    int top = n - 1, bottom = 0;
-    while (top > bottom) { 
-        int middle = (top + bottom) / 2;
-        if (key > table[middle].key) {
-            bottom  = middle+1;
-        } else {
-            top = middle;
-        }
-    }
-    if (key == table[top].key) {
-        *value = table[top].value;
-        return true;
-    } else {
-        return false;
-    }
-} 
-```
-
-# Consultation dichotomique (`binary_get`)
-
-\footnotesize
-
-## Autre implémentation
-
-```C
-bool binary_get2(int n, key_value_t table[n], key_t key, value_t *value) {
-    int top = n - 1, bottom = 0;
-    while (true) { 
-        int middle = (top + bottom) / 2;
-        if (key > table[middle].key) {
-            bottom  = middle + 1;
-        } else if (key < table[middle].key) {
-            top = middle;
-        } else {
-            *value = table[middle].value;
-            return true;
-        }
-        if (top < bottom) {
-             break;
-        }
-    }
-    return false;
-}
-```
-
-## Quelle est la différence avec le code précédent?
-
-# Transformation de clé (hashing)
-
-## Problématique: Numéro AVS (13 chiffres)
-
-* Format: 106.3123.8492.13
-
-    ```
-    Numéro AVS    | Nom
-    0000000000000 | -------
-    ...           | ...
-    1063123849213 | Paul
-    ...           | ...
-    3066713878328 | Orestis
-    ...           | ...
-    9999999999999 | -------
-    ```
-
-## Quelle est la clé? Quelle est la valeur?
-
-. . .
-
-* Clé: Numéro AVS, Valeur: Nom.
-
-## Nombre de clés? Nombre de citoyens? Rapport?
-
-. . .
-
-* $10^{13}$ clés, $10^7$ citoyens, $10^{-5}$ ($10^{-3}\%$ de la table est
-  occupée) $\Rightarrow$ *inefficace*.
-* Pire: $10^{13}$ entrées ne rentre pas dans la mémoire d'un
-  ordinateur.
-
-# Transformation de clé (hashing)
-
-## Problématique 2: Identificateurs d'un programme
-
-* Format: 8 caractères (simplification)
-
-    ```
-    Identificateur | Adresse
-    aaaaaaaa       | -------
-    ...            | ...
-    resultat       | 3aeff
-    compteur       | 4fedc
-    ...            | ...
-    zzzzzzzz       | -------
-    ```
-
-## Quelle est la clé? Quelle est la valeur?
-
-. . .
-
-* Clé: Identificateur, Valeur: Adresse.
-
-## Nombre de clés? Nombre d'identificateur d'un programme? Rapport?
-
-. . .
-
-* $26^{8}\sim 2\cdot 10^{11}$ clés, $2000$ identificateurs, $10^{-8}$ ($10^{-6}\%$ de la table est
-  occupée) $\Rightarrow$ *un peu inefficace*.
-
-# Fonctions de transformation de clé (hash functions)
-
-* La table est représentée avec un tableau.
-* La taille du tableau est beaucoup plus petit que le nombre de clés.
-* On produit un indice du tableau à partir d'une clé:
-$$
-h(key) = n,\quad n\in\mathbb{N}.
-$$
-En français: on transforme `key` en nombre entier qui sera l'indice dans le
-tableau correspondant à `key`.
-
-## La fonction de hash
-
-* La taille du domaine des clés est beaucoup plus grand que le domaine des
-  indices.
-* Plusieurs indices peuvent correspondre à la **même clé**:
-    * Il faut traiter les **collisions**.
-* L'ensemble des indices doit être plus petit ou égal à la taille de la table.
-
-## Une bonne fonction de hash
-
-* Distribue uniformément les clés sur l'ensemble des indices.
-
-# Fonctions de transformation de clés: exemples
-
-## Méthode par troncature
-
-\begin{align*}
-&h: [0,9999]\rightarrow [0,9]\\
-&h(key)=\mbox{troisième chiffre du nombre.}
-\end{align*}
-
-```
-Key  | Index
-0003 | 0
-1123 | 2 \
-1234 | 3  |-> collision.
-1224 | 2 / 
-1264 | 6 
-```
-
-## Quelle est la taille de la table?
-
-. . .
-
-C'est bien dix oui.
-
-# Fonctions de transformation de clés: exemples
-
-## Méthode par découpage
-
-Taille de l'index: 3 chiffres.
-
-```
-key = 321 991 24 ->  321
-                     991
-                    + 24
-                    ----
-                    1336 -> index = 336
-```
-
-## Devinez l'algorithme?
-
-. . .
-
-On part de la gauche:
-
-1. On découpe la clé en tranche de longueur égale à celle de l'index.
-2. On somme les nombres obtenus.
-3. On tronque à la longueur de l'index.
-
-# Fonctions de transformation de clés: exemples
-
-## Méthode multiplicative
-
-Taille de l'index: 2 chiffres.
-
-```
-key = 5486 -> key^2 = 30096196 -> index = 96
-```
-
-On prend le carré de la clé et on garde les chiffres du milieu du résultat.
-
-# Fonctions de transformation de clés: exemples
-
-## Méthode par division modulo
-
-Taille de l'index: `N` chiffres.
-
-```
-h(key) = key % N.
-```
-
-## Quelle doit être la taille de la table?
-
-. . .
-
-Oui comme vous le pensiez au moins `N`.
-
-# Traitement des collisions
-
-## La collision
-
-```
-key1 != key2, h(key1) == h(key2)
-```
-
-## Traitement (une idée?)
-
-. . .
-
-* La première clé occupe la place prévue dans le tableau.
-* La deuxième (troisième, etc.) est placée ailleurs de façon **déterministe**.
-
-Dans ce qui suit la taille de la table est `table_size`.
-
-# La méthode séquentielle
-
-\footnotesize
-
-## Comment ça marche?
-
-* Quand l'index est déjà occupé on regarde sur la position suivante, jusqu'à en
-  trouver une libre.
-
-```C
-index = h(key);
-while (table[index].state == OCCUPIED && table[index].key != key) {
-   index = (index + 1) % table_size; // attention à pas dépasser
-}
-table[index].key = key;
-table[index].state = OCCUPIED;
-```
-
-## Problème?
-
-. . .
-
-* Regroupement d'éléments (clustering).
-
-# Méthode linéaire
-
-\footnotesize
-
-## Comment ça marche?
-
-* Comme la méthode séquentielle mais on "saute" de `k`.
-
-```C
-index = h(key);
-while (table[index].state == OCCUPIED && table[index].key != key) {
-   index = (index + k) % table_size; // attention à pas dépasser
-}
-table[index].key = key;
-table[index].state = OCCUPIED;
-```
-
-## Quelle valeur de `k` éviter?
-
-. . .
-
-* Une valeur où  `table_size` est multiple de `k`.
-
-Cette méthode répartit mieux les regroupements au travers de la table.
-
-# Méthode du double hashing
-
-\footnotesize
-
-## Comment ça marche?
-
-* Comme la méthode linéaire, mais `k = h2(key)` (variable).
-
-```C
-index = h(key);
-while (table[index].state == OCCUPIED && table[index].key != key) {
-   index = (index + h2(k)) % table_size; // attention à pas dépasser
-}
-table[index].key = key;
-table[index].state = OCCUPIED;
-```
-
-## Quelle propriété doit avoir `h2`?
-
-## Exemple
-
-```C
-h2(key) = (table_size - 2) - key % (table_size -2)
-```
-
-# Méthode pseudo-aléatoire
-
-\footnotesize
-
-## Comment ça marche?
-
-* Comme la méthode linéaire mais on génère `k` pseudo-aléatoirement.
-
-    ```C
-    index = h(key);
-    while (table[index].state == OCCUPIED && table[index].key != key) {
-        index = (index + random_number) % table_size;
-    }
-    table[index].key = key;
-    table[index].state = OCCUPIED;
-    ```
-
-## Comment s'assurer qu'on va bien retrouver la bonne clé?
-
-. . .
-
-* Le germe (seed) de la séquence pseudo-aléatoire doit être le même.
-* Le germe à choisir est l'index retourné par `h(key)`.
-
-    ```C
-    srand(h(key));
-    while {
-        random_number = rand();
-    }
-    ```
-
-# Méthode quadratique
-
-* La fonction des indices de collision est de degré 2.
-* Soit $J_0=h(key)$, les indices de collision se construisent comme:
-
-    ```C 
-    J_i = J_0 + i^2 % table_size, i > 0,
-    J_0 = 100, J_1 = 101, J_2 = 104, J_3 = 109, ...
-    ```
-
-## Problème possible?
-
-. . .
-
-* Calculer le carré peut-être "lent".
-* En fait on peut ruser un peu.
-
-# Méthode quadratique
-
-\footnotesize
-
-```C 
-J_i = J_0 + i^2 % table_size, i > 0,
-J_0 = 100
-          \
-           d_0 = 1 
-          /        \
-J_1 = 101           Delta = 2
-          \        /
-           d_1 = 3
-          /        \
-J_2 = 104           Delta = 2
-          \        /
-           d_2 = 5
-          /        \
-J_3 = 109           Delta = 2
-          \        /
-           d_3 = 7
-          /        
-J_4 = 116
---------------------------------------
-J_{i+1} = J_i + d_i,
-d_{i+1} = d_i + Delta, d_0 = 1, i > 0.
-```
-
-# Méthode de chaînage
-
-## Comment ça marche?
-
-* Chaque index de la table contient un pointeur vers une liste chaînée
-  contenant les paires clés-valeurs.
-
-## Un petit dessin
-
-```
-
-
-
-
-
-
-
-
-
-
-
-```
-
-# Méthode de chaînage
-
-## Exemple
-
-On hash avec la fonction `h(key) = key % 11` (`key` est le numéro de la lettre
-de l'alphabet)
-
-```
- U  | N | E | X | E | M | P | L | E | D | E | T | A | B | L | E
- 10 | 3 | 5 | 2 | 5 | 2 | 5 | 1 | 5 | 4 | 5 | 9 | 1 | 2 | 1 | 5
-```
-
-## Comment on représente ça? (à vous)
-
-. . .
-
-![La méthode de chaînage](figs/fig_hash.png){width=80%}
-
-# Méthode de chaînage
-
-Avantages:
-
-* Si les clés sont grandes l'économie de place est importante (les places vides
-  sont `NULL`).
-* La gestion des collisions est conceptuellement simple.
-* Pas de problème de regroupement (clustering).
-
-# Exercice 1
-
-* Construire une table à partir de la liste de clés suivante:
-    ```
-    R, E, C, O, U, P, A, N, T
-    ```
-
-* On suppose que la table est initialement vide, de taille $n = 13$.
-* Utiliser la fonction $h1(k)= k \mod 13$ où k est la $k$-ème lettre de l'alphabet et un traitement séquentiel des collisions.
-
-# Exercice 2
-
-* Reprendre l'exercice 1 et utiliser la technique de double hachage pour traiter
-  les collisions avec
-
-\begin{align*}
-h_1(k)&=k\mod 13,\\
-h_2(k)&=1+(k\mod 11).
-\end{align*}
-* La fonction de hachage est donc $h(k)=(h(k)+h_2(k)) \% 13$ en cas de
-  collision.
-
-
-# Exercice 3
-
-* Stocker les numéros de téléphones internes d'une entreprise suivants dans un
-tableau de 10 positions.
-* Les numéros sont compris entre 100 et 299.
-* Soit $N$ le numéro de téléphone, la fonction de hachage est
-$$
-h(N)=N\mod 10.
-$$
-* La fonction de gestion des collisions est
-$$
-C_1(N,i)=(h(N)+3\cdot i)\mod 10.
-$$
-* Placer 145, 167, 110, 175, 210, 215 (mettre son état à occupé).
-* Supprimer 175 (rechercher 175, et mettre son état à supprimé).
-* Rechercher 35.
-* Les cases ni supprimées, ni occupées sont vides.
-* Expliquer se qui se passe si on utilise?
-$$
-C_1(N,i)=(h(N)+5\cdot i)\mod 10.
-$$
-
diff --git a/slides/cours_14.md b/slides/cours_14.md
deleted file mode 100644
index b4057a4..0000000
--- a/slides/cours_14.md
+++ /dev/null
@@ -1,367 +0,0 @@
----
-title: "Tables de hachage"
-date: "2023-02-24"
-patat:
-  eval:
-    tai:
-      command: fish
-      fragment: false
-      replace: true
-    ccc:
-      command: fish
-      fragment: false
-      replace: true
-  images:
-    backend: auto
----
-
-# Rappel sur les tables de hachage (1/N)
-
-## Définition? Qui se souvient?
-
-. . .
-
-Structure de données abstraite où chaque *valeur* (ou élément) est associée à une *clé* (ou
-argument).
-
-On parle de paires *clé-valeur* (*key-value pairs*).
-
-## Donnez des exemples de telles paires
-
-. . .
-
-* Annuaire (nom-téléphone),
-* Catalogue (objet-prix),
-* Table de valeur fonctions (nombre-nombre),
-* Index (nombre-page)
-* ...
-
-# Rappel sur les tables de hachage (1/N)
-
-## Opérations principales sur les tables
-
-* Insertion d'élément (`insert(clé, valeur)`{.C}), insère la paire `clé-valeur`
-* Consultation (`get(clé)`{.C}), retourne la `valeur` correspondant à `clé`
-* Suppression (`remove(clé)`{.C}), supprime la paire `clé-valeur`
-
-## Transformation de clé (hashing)
-
-* Format: 106.3123.8492.13
-
-    ```
-    Numéro AVS    | Nom
-    0000000000000 | -------
-    ...           | ...
-    1063123849213 | Paul
-    ...           | ...
-    3066713878328 | Orestis
-    ...           | ...
-    9999999999999 | -------
-    ```
-* Nombre de numéros >> nombre d'entrées.
-
-# Fonctions de transformation de clé (hash functions)
-
-* La table est représentée avec un tableau.
-* La taille du tableau est beaucoup plus petit que le nombre de clés.
-* On produit un indice du tableau à partir d'une clé:
-$$
-h(key) = n,\quad n\in\mathbb{N}.
-$$
-En français: on transforme `key` en nombre entier qui sera l'indice dans le
-tableau correspondant à `key`.
-
-## La fonction de hash
-
-* La taille du domaine des clés est beaucoup plus grand que le domaine des
-  indices.
-* Plusieurs indices peuvent correspondre à la **même clé**:
-    * Il faut traiter les **collisions**.
-* L'ensemble des indices doit être plus petit ou égal à la taille de la table.
-
-## Une bonne fonction de hash
-
-* Distribue uniformément les clés sur l'ensemble des indices.
-
-# Fonctions de transformation de clés: exemple
-
-## Méthode par division modulo
-
-Taille de l'index: `N` chiffres.
-
-```
-h(key) = key % N.
-```
-
-## Quelle doit être la taille de la table?
-
-. . .
-
-Oui comme vous le pensiez au moins `N`.
-
-# Traitement des collisions
-
-## La collision
-
-```
-key1 != key2, h(key1) == h(key2)
-```
-
-## Traitement (une idée?)
-
-. . .
-
-* La première clé occupe la place prévue dans le tableau.
-* La deuxième (troisième, etc.) est placée ailleurs de façon **déterministe**.
-
-Dans ce qui suit la taille de la table est `table_size`.
-
-# La méthode séquentielle
-
-\footnotesize
-
-* Quand l'index est déjà occupé on regarde sur la position suivante, jusqu'à en
-  trouver une libre.
-
-```C
-index = h(key);
-while (table[index].state == OCCUPIED && table[index].key != key) {
-   index = (index + 1) % table_size; // attention à pas dépasser
-}
-table[index].key = key;
-table[index].state = OCCUPIED;
-```
-
-# Méthode de chaînage
-
-## Comment ça marche?
-
-* Chaque index de la table contient un pointeur vers une liste chaînée
-  contenant les paires clés-valeurs.
-
-## Un petit dessin
-
-```
-
-
-
-
-
-
-
-
-
-
-
-```
-
-# Méthode de chaînage
-
-## Exemple
-
-On hash avec la fonction `h(key) = key % 11` (`key` est le numéro de la lettre
-de l'alphabet)
-
-```
- U  | N | E | X | E | M | P | L | E | D | E | T | A | B | L | E
- 10 | 3 | 5 | 2 | 5 | 2 | 5 | 1 | 5 | 4 | 5 | 9 | 1 | 2 | 1 | 5
-```
-
-## Comment on représente ça? (à vous)
-
-. . .
-
-![La méthode de chaînage](figs/fig_hash.png){width=80%}
-
-# Exercice 1
-
-* Construire une table à partir de la liste de clés suivante:
-    ```
-    R, E, C, O, U, P, A, N, T
-    ```
-
-* On suppose que la table est initialement vide, de taille $n = 13$.
-* Utiliser la fonction $h1(k)= k \mod 13$ où k est la $k$-ème lettre de l'alphabet et un traitement séquentiel des collisions.
-
-# Exercice 2
-
-* Reprendre l'exercice 1 et utiliser la technique de double hachage pour traiter
-  les collisions avec
-
-\begin{align*}
-h_1(k)&=k\mod 13,\\
-h_2(k)&=1+(k\mod 11).
-\end{align*}
-
-* La fonction de hachage est donc $h(k)=(h(k)+h_2(k)) \% 13$ en cas de
-  collision.
-
-
-# Exercice 3
-
-* Stocker les numéros de téléphones internes d'une entreprise suivants dans un
-tableau de 10 positions.
-* Les numéros sont compris entre 100 et 299.
-* Soit $N$ le numéro de téléphone, la fonction de hachage est
-$$
-h(N)=N\mod 10.
-$$
-* La fonction de gestion des collisions est
-$$
-C_1(N,i)=(h(N)+3\cdot i)\mod 10.
-$$
-* Placer 145, 167, 110, 175, 210, 215 (mettre son état à occupé).
-* Supprimer 175 (rechercher 175, et mettre son état à supprimé).
-* Rechercher 35.
-* Les cases ni supprimées, ni occupées sont vides.
-* Expliquer se qui se passe si on utilise?
-$$
-C_1(N,i)=(h(N)+5\cdot i)\mod 10.
-$$
-
-# Préambule
-
-\small
-
-* On considère pas le cas du chaînage en cas de collisions.
-* L'insertion est construite avec une forme du type
-
-    ```C
-    index = h(key);
-    while (table[index].state == OCCUPIED 
-           && table[index].key != key) {
-       index = (index + k) % table_size; // attention à pas dépasser
-    }
-    table[index].key = key;
-    table[index].state = OCCUPIED;
-    ```
-\normalsize
-
-* Gestion de l'état d'une case *explicite*
-
-    ```C
-    typedef enum {EMPTY, OCCUPIED, DELETED} state;
-    ```
-
-# L'insertion
-
-## Pseudocode?
-
-. . .
-
-```C
-insert(table, key, value) {
-    index = hash de la clé;
-    index = 
-        si "index" est déjà "occupé"
-        et la clé correspondante n'est pas "key"
-        alors gérer la collision;
-
-    changer l'état de la case "index" à "occupé";
-    changer la valeur de la case "index" à "value";
-}
-```
-
-# La suppression
-
-## Pseudocode?
-
-. . .
-
-```C
-value_t remove(table, key) {
-    index = hash de la clé;
-    tant que l'état de la case n'est pas "vide"
-        si "index" est "occupé" et la clé est "key" 
-            changer l'état de la case à "supprimé"
-        sinon
-            index = rehash
-}
-```
-
-# La recherche
-
-## Pseudocode?
-
-. . .
-
-```C
-bool search(table, key, value) {
-    index = hash de la clé;
-    tant que l'état de la case n'est pas "vide"
-        si "index" est "occupé" et la clé est "key" 
-            retourner vrai
-        sinon
-            index = rehash
-}
-```
-
-# Écrivons le code!
-
-* Mais avant:
-    * Quelles sont les structures de données dont nous avons besoin?
-    * Y a-t-il des fonctions auxiliaires à écrire?
-    * Écrire les signatures des fonctions.
-
-. . .
-
-## Structures de données
-
-\footnotesize
-
-. . .
-
-```C
-typedef enum {empty, deleted, occupied};
-typedef ... key_t;
-typedef ... value_t;
-typedef struct _cell_t {
-    key_t key; 
-    value_t value;
-    state_t state;
-} cell_t;
-typedef struct _hm {
-    cell_t *table;
-    int capacity;
-    int size;
-} hm;
-```
-
-# Écrivons le code!
-
-## Fonctions auxiliaires
-
-. . .
-
-```C
-static int hash(key_t key);
-static int rehash(int index, key_t key);
-static int find_index(hm h, key_t key);
-```
-
-##  Signature de l'API 
-
-. . .
-
-```C
-void hm_init(hm *h, int capacity);
-void hm_destroy(hm *h);
-bool hm_set(hm *h, key_t key, value_t *value);
-bool hm_get(hm h, key_t key, value_t *value);
-bool hm_remove(hm *h, key_t key, value_t *value);
-bool hm_search(hm h, key_t key);
-void hm_print(hm h);
-```
-
-# Live code session! 
-
-0. Offered to you by ProtonVPN[^1]!
-
-. . .
-
-1. Like the video.
-2. Subscribe to the channel.
-3. Use our one time voucher for ProtonVPN: `PAULISAWESOME`.
-4. Consider donating on our patreon.
-
-[^1]: The fastest way to connect to BBB!
diff --git a/slides/cours_15.md b/slides/cours_15.md
deleted file mode 100644
index 09a8ed0..0000000
--- a/slides/cours_15.md
+++ /dev/null
@@ -1,929 +0,0 @@
----
-title: "Arbres"
-date: "2023-03-10"
----
-
-# Les arbres: définition
-
-"Un arbre est un graphe acyclique orienté possédant une unique racine, et tel que tous les nœuds sauf la racine ont un unique parent."
-
-. . .
-
-**Santé!**
-
-## Plus sérieusement
-
-* Ensemble de **nœuds** et d'**arêtes** (graphe),
-* Les arêtes relient les nœuds entre eux, mais pas n'importe comment: chaque
-  nœud a au plus un **parent**,
-* Le seul nœud sans parent est la **racine**,
-* Chaque nœud a un nombre fini de **fils**,
-* La hiérarchie des nœuds rend les arêtes **orientées** (parent -> fils), et empêche les
-  **cycles** (acyclique, orienté).
-* La **feuille** ou **nœud terminal** est un nœud sans enfants,
-* Le **niveau** est 1 à la racine et **niveau+1** pour les fils,
-* Le **degré** d'un nœud est le nombre de fils du nœud.
-
-. . .
-
-* Chaque nœud est un arbre en lui même.
-* La **récursivité** sera très utile!
-
-
-# Arbre ou pas arbre?
-
-::: columns
-
-:::: column
-```{.mermaid format=pdf width=400 loc=figs/}
-graph TD;
-    1-->2;
-    1-->3;
-    3-->2;
-    3-->4;
-    3-->5;
-```
-::::
-
-. . .
-
-:::: column
-```{.mermaid format=pdf width=400 loc=figs/}
-graph TD;
-    1-->2;
-    1-->3;
-    3-->4;
-    3-->5;
-    3-->6;
-```
-::::
-
-:::
-
-# Arbre ou pas arbre?
-
-::: columns
-
-:::: column
-```{.mermaid format=pdf width=400 loc=figs/}
-graph TD;
-    1-->2;
-    1-->3;
-    3-->4;
-    3-->5;
-    3-->6;
-    6-->7;
-    7-->3;
-```
-::::
-
-. . .
-
-:::: column
-```{.mermaid format=pdf width=300 loc=figs/}
-graph TD;
-    1;
-```
-::::
-
-:::
-
-# Arbre ou pas arbre?
-
-::: columns
-
-:::: column
-```{.mermaid format=pdf width=400 loc=figs/}
-graph TD;
-    1---2;
-    1---3;
-    3---4;
-    3---5;
-```
-::::
-
-. . .
-
-:::: column
-```{.mermaid format=pdf width=300 loc=figs/}
-graph BT;
-    1-->2;
-    1-->3;
-    3-->4;
-    3-->5;
-    3-->6;
-```
-::::
-
-:::
-
-# Degré et niveau
-
-* Illustration du degré (nombre de fils) et du niveau (profondeur)
-
-::: columns
-
-:::: column
-```{.mermaid format=pdf width=400 loc=figs/}
-graph TD;
-    1[degré 2]-->2[degré 0];
-    1-->3[degré 3];
-    3-->4[degré 0];
-    3-->5[degré 0];
-    3-->6[degré 0];
-```
-::::
-
-. . .
-
-:::: column
-```{.mermaid format=pdf width=300 loc=figs/}
-graph TD;
-    1[niveau 1]-->2[niveau 2];
-    1-->3[niveau 2];
-    3-->4[niveau 3];
-    3-->5[niveau 3];
-    3-->6[niveau 3];
-```
-::::
-
-:::
-
-* Les nœuds de degré 0, sont des feuilles.
-
-# Application: recherche rapide
-
-## Pouvez vous construire un arbre pour résoudre le nombre secret?
-
- . . .
-
-* Le nombre secret ou la recherche dichotomique (nombre entre 0 et 10).
-
-::: columns
-
-:::: column
-```{.mermaid format=pdf width=400 loc=figs/}
-graph LR;
-    5-->|<|2;
-    5-->|>|7;
-    7-->|>|8;
-    7-->|<|6;
-    8-->|>|9;
-    9-->|>|10;
-    2-->|<|1;
-    2-->|>|3;
-    3-->|>|4;
-    1-->|<|0;
-```
-::::
-
-:::: column
-
-**Question:** Quelle est la complexité pour trouver un nombre?
-
-::::
-
-:::
-
-# Autres représentation
-
-* Botanique
-* **Exercice:** Ajouter les degrés/niveaux et feuilles
-
-```{.mermaid width=250 format=pdf loc=figs/}
-graph TD;
-    A-->B;
-    A-->C;
-    B-->D;
-    B-->E;
-    B-->F;
-    F-->I;
-    F-->J;
-    C-->G;
-    C-->H;
-    H-->K;
-```
-
-# Autres représentation
-
-* Ensembliste
-
-::: columns
-
-:::: column
-```{.mermaid width=300 format=pdf loc=figs/}
-graph TD;
-    A-->B;
-    A-->C;
-    B-->D;
-    B-->E;
-    B-->F;
-    F-->I;
-    F-->J;
-    C-->G;
-    C-->H;
-    H-->K;
-```
-::::
-
-. . .
-
-:::: column
-![](figs/ensemble.svg)
-::::
-
-:::
-
-# Autres représentation
-
-* Liste
-
-::: columns
-
-:::: column
-```{.mermaid width=400 format=pdf loc=figs/}
-graph TD;
-    A-->B;
-    A-->C;
-    B-->D;
-    B-->E;
-    B-->F;
-    F-->I;
-    F-->J;
-    C-->G;
-    C-->H;
-    H-->K;
-```
-::::
-
-. . .
-
-:::: column
-```
-(A 
-    (B 
-        (D) 
-        (E) 
-        (F 
-            (I) 
-            (J)
-        )
-    ) 
-    (C
-        (G) 
-        (H 
-            (K)
-        )
-    )
-)
-```
-::::
-
-:::
-
-# Autres représentation
-
-* Par niveau
-
-::: columns
-
-:::: column
-```{.mermaid width=400 format=pdf loc=figs/}
-graph TD;
-    A-->B;
-    A-->C;
-    B-->D;
-    B-->E;
-    B-->F;
-    F-->I;
-    F-->J;
-    C-->G;
-    C-->H;
-    H-->K;
-```
-::::
-
-. . .
-
-:::: column
-```
-1       2       3       4
--------------------------
-A       
-        B       
-                D 
-                E 
-                F           
-                        I
-                        J
-        C       
-                G
-                H
-                        K
-```
-::::
-
-:::
-
-# L'arbre binaire
-
-* Structure de données abstraite,
-* Chaque nœud a au plus deux fils: gauche et droite,
-* Chaque fils est un arbre.
-
-## Comment représenteriez vous une telle structure?
-
-. . .
-
-```C
-<R, G, D>
-    R: racine
-    G: sous-arbre gauche
-    D: sous-arbre droite
-```
-
-## Comment cela s'écrirait en C?
-
-. . .
-
-```C
-typedef struct _node {
-    contenu info;
-    struct _node *left, *right;
-} node;
-typedef node *tree;
-```
-
-# L'arbre binaire
-
-## Que se passerait-il avec 
-
-```C
-typedef struct _node {
-    int info;
-    struct _node left, right;
-} node;
-```
-
-* On ne sait pas quelle est la taille de node, on ne peut pas l'allouer!
-
-## Interface minimale
-
-* Qu'y mettriez vous?
-
-. . .
-
-```C 
-NULL              -> arbre (vide)
-<n, arbre, arbre> -> arbre
-visiter(arbre)    -> nœud (la racine de l'arbre)
-gauche(arbre)     -> arbre (sous-arbre de gauche)
-droite(arbre)     -> arbre (sous-arbre de droite)
-```
-
-* Les autres opérations (insertion, parcours, etc) dépendent de ce qu'on stocke
-  dans l'arbre.
-
-# Exemple d'arbre binaire
-
-* Représentez `(c - a * b) * (d + e / f)` à l'aide d'un arbre binaire (matrix)
-
-. . .
-
-::: columns
-
-:::: column
-```{.mermaid format=pdf width=400 loc=figs/}
-graph TD;
-    A[*]-->B[-];
-    B-->C[c];
-    B-->D[*];
-    D-->E[a];
-    D-->F[b];
-    A-->G[+];
-    G-->H[d];
-    G-->I["/"];
-    I-->J[e];
-    I-->K[f];
-```
-::::
-
-
-:::: column
-
-## Remarques
-
-* L'arbre est **hétérogène**: le genre d'info est pas le même sur chaque nœud
-  (opérateur, opérande).
-    * Les feuilles contiennent les opérandes.
-    * Les nœuds internes contiennent les opérateurs.
-
-::::
-
-:::
-
-# Parcours d'arbres binaires
-
-* Appliquer une opération à tous les nœuds de l'arbre,
-* Nécessité de **parcourir** l'arbre,
-* Utiliser uniquement l'interface: visiter, gauche,
-  droite.
-
-## Une idée de comment parcourir cet arbre?
-
-* 3 parcours (R: Racine, G: sous-arbre gauche, D: sous-arbre droit):
-
-
-::: columns
-
-:::: column
-```{.mermaid format=pdf width=400 loc=figs/}
-graph TD;
-    A[*]-->B[-];
-    B-->C[c];
-    B-->D[*];
-    D-->E[a];
-    D-->F[b];
-    A-->G[+];
-    G-->H[d];
-    G-->I["/"];
-    I-->J[e];
-    I-->K[f];
-```
-::::
-
-:::: column
-
-1. Parcours **préfixe** (R, G D),
-2. Parcours **infixe** (G, R, D),
-3. Parcours **postfixe** (G, D, R).
-
-::::
-
-:::
-
-# Le parcours infixe (G, R, D)
-
-* Gauche, Racine, Droite:
-    1. On descend dans l'arbre de gauche tant qu'il est pas vide,
-    2. On visite la racine du sous arbre,
-    3. On descend dans le sous-arbre de droite (s'il est pas vide),
-    4. On recommence.
-
-. . .
-
-## Incompréhensible?
-
-* La récursivité c'est la vie.
-    
-```
-parcours_infixe(arbre a)
-    si est_pas_vide(gauche(a))
-       parcours_infixe(gauche(a))
-    visiter(A)
-    si est_pas_vide(droite(A))
-       parcours_infixe(droite(A))
-```
-
-# Graphiquement (dessinons)
-
-::: columns
-
-:::: column
-```{.mermaid format=pdf width=400 loc=figs/}
-graph TD;
-    A[*]-->B[-];
-    B-->C[c];
-    B-->D[*];
-    D-->E[a];
-    D-->F[b];
-    A-->G[+];
-    G-->H[d];
-    G-->I["/"];
-    I-->J[e];
-    I-->K[f];
-```
-::::
-
-:::: column
-
-```
-parcours_infixe(arbre a)
-    si est_pas_vide(gauche(a))
-       parcours_infixe(gauche(a))
-    visiter(A)
-    si est_pas_vide(droite(A))
-       parcours_infixe(droite(A))
-```
-
-::::
-
-:::
-
-
-# Graphiquement (`mermaid` c'est super)
-
-::: columns
-
-:::: column
-```{.mermaid format=pdf width=400 loc=figs/}
-graph TD;
-    A[*]-->B[-];
-    A[*]-.->|1|B[-];
-    B-->C[c];
-    B-.->|2|C[c];
-    C-.->|3|B;
-    B-->D[*];
-    B-.->|4|D;
-    D-->E[a];
-    D-.->|5|E;
-    E-.->|6|D;
-    D-->F[b];
-    D-.->|7|F;
-    F-.->|8|A;
-    A-->G[+];
-    A-.->|9|G;
-    G-->H[d];
-    G-.->|10|H;
-    H-.->|11|G;
-    G-->I["/"];
-    G-.->|12|I;
-    I-->J[e];
-    I-.->|13|J;
-    J-.->|14|I;
-    I-->K[f];
-    I-.->|15|K;
-```
-::::
-
-:::: column
-
-```
-parcours_infixe(arbre a)
-    si est_pas_vide(gauche(a))
-       parcours_infixe(gauche(a))
-    visiter(A)
-    si est_pas_vide(droite(A))
-       parcours_infixe(droite(A))
-```
-
-## Remarque 
-
-Le nœud est visité à la **remontée**.
-
-## Résultat
-
-```
-c - a * b * d + e / f
-```
-
-::::
-
-:::
-
-# Et en C?
-
-## Live code
-
-\footnotesize
-
-. . .
-
-```C
-typedef int data;
-typedef struct _node {
-    data info;
-    struct _node* left;
-    struct _node* right;
-} node;
-typedef node* tree_t;
-void tree_print(tree_t tree, int n) {
-    if (NULL != tree) {
-        tree_print(tree->left, n+1);
-        for (int i = 0; i < n; i++) {
-            printf(" ");
-        }
-        printf("%d\n", tree->info);
-        tree_print(tree->right, n+1);
-    }
-}
-```
-
-# Question
-
-## Avez-vous compris le fonctionnement?
-
-. . .
-
-## Vous en êtes sûr·e·s?
-
-. . .
-
-## OK, alors deux exercices:
-
-1. Écrire le pseudo-code pour le parcours R, G, D (matrix).
-2. Écrire le pseudo-code pour la parcours G, D, R (matrix),
-
-## Rappel
-
-```
-parcours_infixe(arbre a)
-    si est_pas_vide(gauche(a))
-       parcours_infixe(gauche(a))
-    visiter(A)
-    si est_pas_vide(droite(A))
-       parcours_infixe(droite(A))
-```
-
-# Correction
-
-\footnotesize
-
-* Les deux parcours sont des modifications **triviales**[^1] de l'algorithme
-  infixe.
-
-## Le parcours postfixe
-
-```python
-parcours_postfixe(arbre a)
-    si est_pas_vide(gauche(a))
-       parcours_postfixe(gauche(a))
-    si est_pas_vide(droite(a))
-       parcours_postfixe(droite(a))
-    visiter(a)
-```
-
-## Le parcours préfixe
-
-```python
-parcours_préfixe(arbre a)
-    visiter(a)
-    si est_pas_vide(gauche(a))
-        parcours_préfixe(gauche(a))
-    si est_pas_vide(droite(a))
-        parcours_préfixe(droite(a))
-```
-
-. . .
-
-**Attention:** L'implémentation de ces fonctions en C sont **à faire** en
-exercice (inspirez vous de ce qu'on a fait avant)!
-
-# Exercice: parcours
-
-## Comment imprimer l'arbre ci-dessous?
-
-```
-                        f
-                /
-                        e
-        +
-                d
-*
-                c
-        -
-                        b
-                *
-                        a
-```
-
-. . .
-
-## Bravo vous avez trouvé! 
-
-* Il s'agissait du parcours D, R, G.
-
-# Implémentation
-
-## Vous avez 5 min pour implémenter cette fonction et la poster sur matrix!
-
-. . .
-
-```C 
-void pretty_print(tree_t tree, int n) {
-    if (NULL != tree) {
-        pretty_print(tree->right, n+1);
-        for (int i = 0; i < n; ++i) {
-            printf(" ");
-        }
-        printf("%d\n", tree->info);
-        pretty_print(tree->left, n+1);
-    }
-}
-```
-
-# Exercice supplémentaire (sans corrigé)
-
-Écrire le code de la fonction 
-
-```C
-int depth(tree_t t);
-```
-
-qui retourne la profondeur maximale d'un arbre.
-
-Indice: la profondeur à chaque niveau peut-être calculée à partir du niveau des
-sous-arbres de gauche et de droite.
-
-# La recherche dans un arbre binaire
-
-* Les arbres binaires peuvent retrouver une information très rapidement.
-* À quelle complexité? À quelle condition?
-
-. . .
-
-## Condition
-
-* Le contenu de l'arbre est **ordonné** (il y a une relation d'ordre (`<`, `>`
-  entre les éléments).
-
-## Complexité
-
-* La profondeur de l'arbre (ou le $\mathcal{O}(\log_2(N))$)
-
-. . .
-
-## Exemple: les arbres lexicographiques
-
-* Chaque nœud contient une information de type ordonné, la **clé**,
-* Par construction, pour chaque nœud $N$:
-    * Toutes clé du sous-arbre à gauche de $N$ sont inférieurs à la clé de $N$.
-    * Toutes clé du sous-arbre à droite de $N$ sont inférieurs à la clé de $N$.
-
-# Algorithme de recherche
-
-* Retourner le nœud si la clé est trouvée dans l'arbre.
-
-```python
-arbre recherche(clé, arbre)
-    tante_que est_non_vide(arbre)
-        si clé < clé(arbre)
-            arbre = gauche(arbre)
-        sinon si clé > clé(arbre)
-            arbre = droite(arbre)
-        sinon
-            retourne arbre
-    retourne NULL
-```
-
-# Algorithme de recherche, implémentation (live)
-
-\footnotesize
-
-. . .
-
-```C 
-typedef int key_t;
-typedef struct _node {
-    key_t key;
-    struct _node* left;
-    struct _node* right;
-} node;
-typedef node* tree_t;
-tree_t search(key_t key, tree_t tree) {
-    tree_t current = tree;
-    while (NULL != current) {
-        if (current->key > X) {
-            current = current->gauche;
-        } else if (current->key < X){
-            current = current->droite;
-        } else {
-            return current;
-        }
-    }
-    return NULL;
-}
-```
-
-# Exercice (5-10min)
-
-Écrire le code de la fonction
-
-```C 
-int tree_size(tree_t tree);
-```
-
-qui retourne le nombre total de nœuds d'un arbre et poster le résultat sur
-matrix.
-
-Indication: la taille, est 1 + le nombre de nœuds du sous-arbre de gauche
-additionné au nombre de nœuds dans le sous-arbre de droite.
-
-. . .
-
-```C
-int arbre_size(tree_t tree) {
-    if (NULL == tree) {
-        return 0;
-    } else {   
-        return 1 + tree_size(tree->left) 
-            + tree_size(tree->right);
-    }
-}
-```
-
-# L'insertion dans un arbre binaire
-
-* C'est bien joli de pouvoir faire des parcours, recherches, mais si on peut
-  pas construire l'arbre....
-
-## Pour un arbre lexicographique
-
-* Rechercher la position dans l'arbre où insérer.
-* Créer un nœud avec la clé et le rattacher à l'arbre.
-
-# Exemple d'insertions
-
-* Clés uniques pour simplifier.
-* Insertion de 5, 15, 10, 25, 2, -5, 12, 14, 11.
-* Rappel:
-    * Plus petit que la clé courante => gauche,
-    * Plus grand que la clé courante => droite.
-* Faisons le dessins ensemble
-
-```
-
-
-
-
-
-
-
-
-
-```
-
-## Exercice (3min, puis matrix)
-
-* Dessiner l'arbre en insérant 20, 30, 60, 40, 10, 15, 25, -5 
-
-
-# Pseudo-code d'insertion (1/2)
-
-* Deux parties:
-    * Recherche le parent où se passe l'insertion.
-    * Ajout du fils dans l'arbre.
-
-## Recherche du parent
-
-```
-arbre position(arbre, clé)
-    si est_non_vide(arbre)
-        si clé < clé(arbre)
-            suivant = gauche(arbre)
-        sinon
-            suivant = droite(arbre)
-        tant que clé(arbre) != clé && est_non_vide(suivant)
-            arbre = suivant
-            si clé < clé(arbre)
-                suivant = gauche(arbre)
-            sinon
-                suivant = droite(arbre)
-            
-    retourne arbre
-```
-
-# Pseudo-code d'insertion (2/2)
-
-* Deux parties:
-    * Recherche de la position.
-    * Ajout dans l'arbre.
-
-## Ajout du fils
-
-```
-ajout(arbre, clé)
-    si est_vide(arbre)
-        arbre = nœud(clé)
-    sinon
-        si clé < clé(arbre)
-            gauche(arbre) = nœud(clé)
-        sinon si clé > clé(arbre)
-            droite(arbre) = nœud(clé)
-        sinon
-            retourne
-```
-
-# Code d'insertion en C (1/2)
-
-## Recherche du parent (ensemble)
-
-. . .
-
-```C
-tree_t position(tree_t tree, key_t key) {
-    tree_t current = tree;
-    if (NULL != current) {
-        tree_t subtree = key > current->key ? current->right :
-        current->left;
-        while (key != current->key && NULL != subtree) {
-            current = subtree;
-            subtree = key > current->key ? current->right :
-            current->left;
-        }
-    }
-    return current;
-}
-```
-
-[^1]: Copyright cours de mathématiques pendant trop d'années.
diff --git a/slides/cours_16.md b/slides/cours_16.md
deleted file mode 100644
index 6e284d6..0000000
--- a/slides/cours_16.md
+++ /dev/null
@@ -1,1277 +0,0 @@
----
-title: "Arbres et tri par tas"
-date: "2023-03-17"
----
-
-# Un joli site
-
-## Visualisation d'algorithmes
-
-* <https://visualgo.net/>
-* Allons nous rafraîchir la mémoire sur l'insertion / recherche dans un arbre
-  binaire.
-
-
-
-# L'insertion (1/4)
-
-* Deux parties:
-    * Recherche le parent où se passe l'insertion.
-    * Ajout du fils dans l'arbre.
-
-## Recherche du parent (pseudo-code)
-
-```
-arbre position(arbre, clé)
-    si est_non_vide(arbre)
-        si clé < clé(arbre)
-            suivant = gauche(arbre)
-        sinon
-            suivant = droite(arbre)
-        tant que clé(arbre) != clé && est_non_vide(suivant)
-            arbre = suivant
-            si clé < clé(arbre)
-                suivant = gauche(arbre)
-            sinon
-                suivant = droite(arbre)
-            
-    retourne arbre
-```
-
-# L'insertion (2/4)
-
-## Recherche du parent (code)
-
-. . .
-
-```C
-tree_t position(tree_t tree, key_t key) {
-    tree_t curr = tree;
-    if (NULL != curr) {
-        tree_t subtree = 
-            key > curr->key ? curr->right : curr->left;
-        while (key != curr->key && NULL != subtree) {
-            curr = subtree;
-            subtree = key > curr->key ? curr->right :
-            curr->left;
-        }
-    }
-    return curr;
-}
-```
-
-# L'insertion (3/4)
-
-* Deux parties:
-    * Recherche de la position.
-    * Ajout dans l'arbre.
-
-## Ajout du fils (pseudo-code)
-
-```
-rien ajout(arbre, clé)
-    si est_vide(arbre)
-        arbre = nœud(clé)
-    sinon
-        arbre = position(arbre, clé)
-        si clé < clé(arbre)
-            gauche(arbre) = nœud(clé)
-        sinon si clé > clé(arbre)
-            droite(arbre) = nœud(clé)
-        sinon
-            retourne
-```
-
-
-
-# L'insertion (4/4)
-
-## Ajout du fils (code)
-
-\scriptsize
-
-* 2 cas: arbre vide ou pas.
-* on retourne un pointeur vers le nœud ajouté (ou `NULL`)
-
-. . .
-
-```C
-tree_t add_key(tree_t *tree, key_t key) {
-    node_t *new_node = calloc(1, sizeof(*new_node));
-    new_node->key = key;
-    if (NULL == *tree) {
-        *tree = new_node;
-    } else {
-        tree_t subtree = position(*tree, key);
-        if (key == subtree->key) {
-            return NULL;
-        } else {
-            if (key > subtree->key) {
-                subtree->right = new_node;
-            } else {
-                subtree->left = new_node;
-            }
-        }
-    }
-    return new_node;
-}
-```
-
-# La version PK (1/5)
-
-```C
-typedef struct _node {
-    int info;
-    struct _node *left, *right;
-} node;
-typedef node *tree;
-void parcours_infixe(tree arbre, int n){
-    if(arbre!=NULL){
-        parcours_infixe(arbre->left, n+1);
-        for(int i=0; i<n; i++){
-            printf("   ");
-        }
-        printf("%d\n", arbre->info);
-        parcours_infixe(arbre->right, n+1);
-    }
-}
-```
-
-# La version PK (2/5)
-
-```C
-tree recherche(int cle, tree arbre){
-    while(arbre != NULL){
-        if(arbre->info == cle) return arbre;
-        if(arbre->info > cle){
-            arbre = arbre->left;
-        }else if(arbre->info < cle){
-            arbre = arbre->right;
-        }  
-    }
-    return NULL;
-}
-
-```
-
-# La version PK (3/5)
-
-\footnotesize
-
-```C
-node* parent_insertion(int donnee, tree arbre){
-    if(arbre != NULL){
-        node* suivant = NULL;
-        if(arbre->info > donnee){
-            suivant = arbre->left;
-        } else {
-            suivant = arbre->right;
-        }
-        while(suivant != NULL && arbre->info != donnee){
-            arbre = suivant;
-            if(arbre->info > donnee){
-                suivant = arbre->left;
-            } else {
-                suivant = arbre->right;
-            } 
-        }
-    }
-    return arbre;
-}
-
-```
-
-# La version PK (4/5)
-
-\footnotesize
-
-```C
-node* nouveau_noeud(int donnee){
-    node* new_node = malloc(sizeof(node));
-    new_node->info = donnee;
-    new_node->left = NULL;
-    new_node->right = NULL;
-    return new_node;
-}
-tree insertion(int donnee, tree arbre){
-    if(arbre == NULL){
-        arbre = nouveau_noeud(donnee);
-    } else {
-        node* parent = parent_insertion(donnee, arbre);
-        if(donnee > parent->info){
-            parent->right = nouveau_noeud(donnee);
-        } else if(donnee < parent->info) {
-            parent->left = nouveau_noeud(donnee);
-        } 
-    }
-    return arbre;
-}
-```
-
-# La version PK (5/5)
-
-```C
-int main(){
-    tree arbre = NULL;
-
-    arbre = insertion(2, arbre);
-    arbre = insertion(1, arbre);
-    arbre = insertion(8, arbre);
-    arbre = insertion(10, arbre);
-    arbre = insertion(5, arbre);
-
-    parcours_infixe(arbre, 0);
-}
-```
-
-# La suppression de clé
-
-
-::: columns
-
-:::: column
-
-## Cas simples: 
-
-* le nœud est absent, 
-* le nœud est une feuille
-* le nœuds a un seul fils.
-
-## Une feuille (le 19 p.ex.).
-
-```{.mermaid format=pdf width=150 loc=figs/}
-flowchart TB;
-    10-->20;
-    10-->5
-    20-->21
-    20-->19
-```
-
-::::
-
-:::: column
-
-## Un seul fils (le 20 p.ex.).
-
-```{.mermaid format=pdf width=400 loc=figs/}
-flowchart TB;
-    10-->20;
-    10-->5
-    20-->25
-    20-->18
-    25-->24
-    25-->30
-    5-->4;
-    5-->8;
-    style 18 fill:#fff,stroke:#fff,color:#fff
-```
-
-## Dans tous les cas
-
-* Chercher le nœud à supprimer: utiliser `position()`.
-
-::::
-
-:::
-
-# La suppression de clé
-
-
-::: columns
-
-:::: column
-
-## Cas compliqué
-
-* Le nœud à supprimer à (au moins) deux descendants (10).
-
-```{.mermaid format=pdf width=400 loc=figs/}
-flowchart TB;
-    10-->20;
-    10-->5
-    20-->25
-    20-->18
-    25-->24
-    25-->30
-    5-->4;
-    5-->8;
-```
-
-::::
-
-:::: column
-
-* Si on enlève 10 il se passe quoi?
-
-. . .
-
-* On peut pas juste enlever `10` et recoller...
-* Proposez une solution bon sang!
-
-. . .
-
-## Solution
-
-* Échange de la valeur à droite dans le sous-arbre de gauche ou
-  ...
-* de la valeur de gauche dans le sous-arbre de droite!
-* Puis, on retire le nœud.
-
-::::
-
-:::
-
-# Le pseudo-code  de la suppression
-
-## Pour une feuille ou absent (ensemble)
-
-```
-arbre suppression(arbre, clé)
-    sous_arbre = position(arbre, clé)
-    si est_vide(sous_arbre) ou clé(sous_arbre) != clé
-        retourne vide
-    sinon
-        si est_feuille(sous_arbre) et clé(sous_arbre) == clé
-            nouvelle_feuille = parent(arbre, sous_arbre)
-            si est_vide(nouvelle_feuille)
-                arbre = vide
-            sinon 
-                si gauche(nouvelle_feuille) == sous_arbre 
-                    gauche(nouvelle_feuille) = vide
-                sinon
-                    droite(nouvelle_feuille) = vide
-        retourne sous_arbre
-```
-
-# Il nous manque le code pour le `parent`
-## Pseudo-code pour trouver le parent (5min -> matrix)
-
-. . .
-
-```
-arbre parent(arbre, sous_arbre)
-    si est_non_vide(arbre)
-        actuel = arbre
-        parent = actuel
-        clé = clé(sous_arbre)
-        faire
-            si (clé != clé(actuel))
-                parent = actuel
-                si clé < clé(actuel)
-                    actuel = gauche(actuel)
-                sinon
-                    actuel = droite(actuel)
-            sinon
-                retour parent
-        tant_que (actuel != sous_arbre)
-    retourne vide
-```
-
-# Le pseudo-code  de la suppression
-
-\footnotesize
-
-## Pour un seul enfant (5min -> matrix)
-
-. . .
-
-```
-arbre suppression(arbre, clé)
-    sous_arbre = position(arbre, clé)
-    si est_vide(gauche(sous_arbre)) ou est_vide(droite(sous_arbre))
-        parent = parent(arbre, sous_arbre)
-        si est_vide(gauche(sous_arbre))
-            si droite(parent) == sous_arbre
-                droite(parent) = droite(sous_arbre)
-            sinon
-                gauche(parent) = droite(sous_arbre)
-        sinon
-            si droite(parent) == sous_arbreou est_
-                droite(parent) = gauche(sous_arbre)
-            sinon
-                gauche(parent) = gauche(sous_arbre)
-        retourne sous_arbre
-```
-
-
-# Le pseudo-code  de la suppression
-
-\footnotesize
-
-## Pour au moins deux enfants (ensemble)
-
-```
-arbre suppression(arbre, clé)
-    sous_arbre = position(arbre, clé) # on revérifie pas que c'est bien la clé
-    si est_non_vide(gauche(sous_arbre)) et est_non_vide(droite(sous_arbre))
-        max_gauche = position(gauche(sous_arbre), clé)
-        échange(clé(max_gauche), clé(sous_arbre))
-        suppression(gauche(sous_arbre), clé)
-```
-
-# Exercices (poster sur matrix)
-
-1. Écrire le pseudo-code de l'insertion purement en récursif.
-
-. . .
-
-```
-arbre insertion(arbre, clé)
-    si est_vide(arbre)
-        retourne nœud(clé)
-
-    si (clé < arbre->clé)
-        gauche(arbre) = insert(gauche(arbre), clé)
-    sinon
-        droite(arbre) = insert(droite(arbre), clé)
-    retourne arbre
-```
-
-# Exercices (poster sur matrix)
-
-2. Écrire le pseudo-code de la recherche purement en récursif.
-
-. . .
-
-```
-bool recherche(arbre, clé)
-    si est_vide(arbre)
-        retourne faux // pas trouvée
-    si clé(arbre) == clé
-        retourne vrai // trouvée
-    si clé < clé(arbre)
-        retourne recherche(gauche(arbre), clé)
-    sinon
-        retourne recherche(droite(arbre), clé)
-```
-
-# Exercices (à la maison)
-
-3. Écrire une fonction qui insère des mots dans un arbre et ensuite affiche
-   l'arbre.
-
-# Trier un tableau à l'aide d'un arbre binaire
-
-* Tableau représenté comme un arbre binaire.
-* Aide à comprendre "comment" trier, mais on ne construit jamais l'arbre.
-* Complexité $O(N\log_2 N)$ en moyenne et grande stabilité (pas de cas
-  dégénérés).
-
-# Lien entre arbre et tableau
-
-* La racine de l'arbre set le premier élément du tableau.
-* Les deux fils d'un nœud d'indice $i$, ont pour indices $2i+1$ et $2i+2$:
-    * Les fils du nœud $i=0$, sont à $2\cdot 0+1=1$ et $2\cdot 0+2=2$.
-    * Les fils du nœud $i=1$, sont à $2\cdot 1+1=3$ et $2\cdot 1+2=4$.
-    * Les fils du nœud $i=2$, sont à $2\cdot 2+2=5$ et $2\cdot 1+2=6$.
-    * Les fils du nœud $i=3$, sont à $2\cdot 3+1=7$ et $2\cdot 3+2=8$.
-* Un élément d'indice $i$ a pour parent l'élément $(i-1)/2$ (division entière):
-    * Le parent du nœud $i=8$ est $(8-1)/2=3$.
-    * Le parent du nœud $i=7$ est $(7-1)/2=3$.
-
-# Visuellement
-
-::: columns
-
-:::: column
-
-* Où vont les indices correspondant du tableau?
-
-```{.mermaid format=pdf width=400 loc=figs/}
-graph TD;
-    id0(( ))-->id1(( ));
-    id0-->id2(( ));
-    id1-->id3(( ));
-    id1-->id4(( ));
-    id2-->id5(( ));
-    id2-->id6(( ));
-    id3-->id7(( ));
-    id3-->id8(( ));
-    id4-->id9(( ));
-    id4-->id10(( ));    
-    style id10 fill:#fff,stroke:#fff
-```
-::::
-
-:::: column
-
-* Les flèche de gauche à droite, parent -> enfants.
-* Les flèche de droite à gauche, enfants -> parent.
-
-![Dualité tableau arbre binaire.](figs/heap_tree.svg)
-
-::::
-
-:::
-
-**Propriétés:** 
-
-1. les feuilles sont toutes sur l'avant dernier ou dernier niveau.
-2. les feuilles de profondeur maximale sont "tassée" à gauche.
-
-# Le tas (ou heap)
-
-## Définition
-
-* Un arbre est un tas, si la valeur de chacun de ses descendants est inférieure
-  ou égale à sa propre valeur.
-
-## Exemples (ou pas)
-
-```
-16  8 14 6 2 10 12 4 5 # Tas
-16 14  8 6 2 10 12 4 5 # Non-tas, 10 > 8 et 12 > 8
-```
-
-## Exercices (ou pas)
-
-```
-19 18 12 12 17 1 13 4 5 # Tas ou pas tas?
-19 18 16 12 17 1 12 4 5 # Tas ou pas tas?
-```
-
-. . .
-
-```
-19 18 12 12 17 1 13 4 5 # Pas tas! 13 > 12
-19 18 16 12 17 1 12 4 5 # Tas!
-```
-
-# Exemple de tri par tas (1/N)
-
-```
-        | 1 | 16 | 5 | 12 | 4 | 2 | 8 | 10 | 6 | 7 |
-```
-
-::: columns
-
-:::: column
-
-* Quel est l'arbre que cela représente?
-
-. . .
-
-```{.mermaid format=pdf width=400 loc=figs/}
-graph TD;
-    id0((1))-->id1((16));
-    id0-->id2((5));
-    id1-->id3((12));
-    id1-->id4((4));
-    id2-->id5((2));
-    id2-->id6((8));
-    id3-->id7((10));
-    id3-->id8((6));
-    id4-->id9((7));
-    id4-->id10(( ));    
-    style id10 fill:#fff,stroke:#fff
-```
-
-::::
-
-:::: column
-
-**But:** Transformer l'arbre en tas.
-
-* On commence à l'indice $N/2 = 5$: `4`.
-* `7 > 4` (enfant `>` parent).
-* intervertir `4` et `7`.
-
-```{.mermaid format=pdf width=400 loc=figs/}
-graph TD;
-    id0((1))-->id1((16));
-    id0-->id2((5));
-    id1-->id3((12));
-    id1-->id4((7));
-    id2-->id5((2));
-    id2-->id6((8));
-    id3-->id7((10));
-    id3-->id8((6));
-    id4-->id9((4));
-    id4-->id10(( ));    
-    style id10 fill:#fff,stroke:#fff
-```
-
-::::
-
-:::
-
-. . .
-
-```
-                            *                    *
-        | 1 | 16 | 5 | 12 | 7 | 2 | 8 | 10 | 6 | 4 |
-```
-
-# Exemple de tri par tas (2/N)
-
-```
-        | 1 | 16 | 5 | 12 | 7 | 2 | 8 | 10 | 6 | 4 |
-```
-
-::: columns
-
-:::: column
-
-**But:** Transformer l'arbre en tas.
-
-* On continue à l'indice $N/2-1 = 4$: `12`.
-* Déjà un tas, rien à faire.
-
-```{.mermaid format=pdf width=400 loc=figs/}
-graph TD;
-    id0((1))-->id1((16));
-    id0-->id2((5));
-    id1-->id3((12));
-    id1-->id4((7));
-    id2-->id5((2));
-    id2-->id6((8));
-    id3-->id7((10));
-    id3-->id8((6));
-    id4-->id9((4));
-    id4-->id10(( ));    
-    style id10 fill:#fff,stroke:#fff
-```
-
-::::
-
-:::: column
-
-**But:** Transformer l'arbre en tas.
-
-* On continue à l'indice $N/2-2 = 3$: `5`.
-* `5 < 8`, échanger `8` et `5` (aka `max(2, 5, 8)`)
-
-```{.mermaid format=pdf width=400 loc=figs/}
-graph TD;
-    id0((1))-->id1((16));
-    id0-->id2((8));
-    id1-->id3((12));
-    id1-->id4((7));
-    id2-->id5((2));
-    id2-->id6((5));
-    id3-->id7((10));
-    id3-->id8((6));
-    id4-->id9((4));
-    id4-->id10(( ));    
-    style id10 fill:#fff,stroke:#fff
-```
-
-::::
-
-:::
-
-. . .
-
-```
-        | 1 | 16 | 8 | 12 | 7 | 2 | 5 | 10 | 6 | 4 |
-```
-
-# Exemple de tri par tas (3/N)
-
-```
-        | 1 | 16 | 5 | 12 | 7 | 2 | 8 | 10 | 6 | 4 |
-```
-
-::: columns
-
-:::: column
-
-**But:** Transformer l'arbre en tas.
-
-* Indice $N/2-1 = 4$: `12`.
-* Déjà un tas, rien à faire.
-
-```{.mermaid format=pdf width=400 loc=figs/}
-graph TD;
-    id0((1))-->id1((16));
-    id0-->id2((5));
-    id1-->id3((12));
-    id1-->id4((7));
-    id2-->id5((2));
-    id2-->id6((8));
-    id3-->id7((10));
-    id3-->id8((6));
-    id4-->id9((4));
-    id4-->id10(( ));    
-    style id10 fill:#fff,stroke:#fff
-```
-
-::::
-
-:::: column
-
-**But:** Transformer l'arbre en tas.
-
-* Indice $N/2-2 = 3$: `5`.
-* `5 < 8`, `5 <=> max(2, 5, 8)`
-
-```{.mermaid format=pdf width=400 loc=figs/}
-graph TD;
-    id0((1))-->id1((16));
-    id0-->id2((8));
-    id1-->id3((12));
-    id1-->id4((7));
-    id2-->id5((2));
-    id2-->id6((5));
-    id3-->id7((10));
-    id3-->id8((6));
-    id4-->id9((4));
-    id4-->id10(( ));    
-    style id10 fill:#fff,stroke:#fff
-```
-
-::::
-
-:::
-
-```
-                   *                *
-        | 1 | 16 | 8 | 12 | 7 | 2 | 5 | 10 | 6 | 4 |
-```
-
-# Exemple de tri par tas (4/N)
-
-```
-        | 1 | 16 | 8 | 12 | 7 | 2 | 5 | 10 | 6 | 4 |
-```
-
-::: columns
-
-:::: column
-
-**But:** Transformer l'arbre en tas.
-
-* Indice $N/2-3 = 1$: `16`.
-* Déjà un tas, rien à faire.
-
-```{.mermaid format=pdf width=400 loc=figs/}
-graph TD;
-    id0((1))-->id1((16));
-    id0-->id2((8));
-    id1-->id3((12));
-    id1-->id4((7));
-    id2-->id5((2));
-    id2-->id6((5));
-    id3-->id7((10));
-    id3-->id8((6));
-    id4-->id9((4));
-    id4-->id10(( ));    
-    style id10 fill:#fff,stroke:#fff
-```
-
-::::
-
-:::: column
-
-**But:** Transformer l'arbre en tas.
-
-* Indice $N/2-4 = 1$: `1`.
-* `1 < 16 && 1 < 8`, `1 <=> max(1, 16, 8)`
-
-```{.mermaid format=pdf width=400 loc=figs/}
-graph TD;
-    id0((16))-->id1((1));
-    id0-->id2((8));
-    id1-->id3((12));
-    id1-->id4((7));
-    id2-->id5((2));
-    id2-->id6((5));
-    id3-->id7((10));
-    id3-->id8((6));
-    id4-->id9((4));
-    id4-->id10(( ));    
-    style id10 fill:#fff,stroke:#fff
-```
-
-::::
-
-:::
-
-```
-           *   *
-        | 16 | 1 | 8 | 12 | 7 | 2 | 5 | 10 | 6 | 4 |
-```
-
-
-# Exemple de tri par tas (5/N)
-
-```
-        | 16 | 1 | 8 | 12 | 7 | 2 | 5 | 10 | 6 | 4 |
-```
-
-::: columns
-
-:::: column
-
-**But:** Transformer l'arbre en tas.
-
-* Recommencer avec `1`.
-* `1 <=> max(1, 12, 7)`.
-
-```{.mermaid format=pdf width=400 loc=figs/}
-graph TD;
-    id0((16))-->id1((12));
-    id0-->id2((8));
-    id1-->id3((1));
-    id1-->id4((7));
-    id2-->id5((2));
-    id2-->id6((5));
-    id3-->id7((10));
-    id3-->id8((6));
-    id4-->id9((4));
-    id4-->id10(( ));    
-    style id10 fill:#fff,stroke:#fff
-```
-
-::::
-
-:::: column
-
-**But:** Transformer l'arbre en tas.
-
-* Recommencer avec `1`.
-* `1 <=> max(1, 10, 6)`.
-
-```{.mermaid format=pdf width=400 loc=figs/}
-graph TD;
-    id0((16))-->id1((12));
-    id0-->id2((8));
-    id1-->id3((10));
-    id1-->id4((7));
-    id2-->id5((2));
-    id2-->id6((5));
-    id3-->id7((1));
-    id3-->id8((6));
-    id4-->id9((4));
-    id4-->id10(( ));    
-    style id10 fill:#fff,stroke:#fff
-```
-
-::::
-
-:::
-
-```
-                *        *               *
-        | 16 | 12 | 8 | 10 | 7 | 2 | 5 | 1 | 6 | 4 |
-```
-
-* L'arbre est un tas.
-
-# Exemple de tri par tas (6/N)
-
-```
-        | 16 | 12 | 8 | 10 | 7 | 2 | 5 | 1 | 6 | 4 |
-```
-
-::: columns
-
-:::: column
-
-**But:** Trier les tas.
-
-* Échanger la racine, `16` (`max` de l'arbre) avec `4`.
-* Traiter la racine.
-
-```{.mermaid format=pdf width=400 loc=figs/}
-graph TD;
-    id0((4))-->id1((12));
-    id0-->id2((8));
-    id1-->id3((10));
-    id1-->id4((7));
-    id2-->id5((2));
-    id2-->id6((5));
-    id3-->id7((1));
-    id3-->id8((6));
-```
-
-::::
-
-:::: column
-
-**But:** Trier les tas.
-
-* `4 <=> max(4, 12, 8)`.
-* `4 <=> max(4, 10, 7)`.
-* `4 <=> max(4, 1, 6)`.
-
-```{.mermaid format=pdf width=400 loc=figs/}
-graph TD;
-    id0((12))-->id1((10));
-    id0-->id2((8));
-    id1-->id3((6));
-    id1-->id4((7));
-    id2-->id5((2));
-    id2-->id6((5));
-    id3-->id7((1));
-    id3-->id8((4));
-```
-
-::::
-
-:::
-
-```
-        | 12 | 10 | 8 | 6 | 7 | 2 | 5 | 1 | 4 || 16
-```
-
-
-# Exemple de tri par tas (7/N)
-
-```
-        | 12 | 10 | 8 | 6 | 7 | 2 | 5 | 1 | 4 || 16
-```
-
-::: columns
-
-:::: column
-
-**But:** Trier les tas.
-
-* Échanger la racine, `12` (`max` de l'arbre) avec `4`.
-* Traiter la racine.
-
-```{.mermaid format=pdf width=400 loc=figs/}
-graph TD;
-    id0((4))-->id1((10));
-    id0-->id2((8));
-    id1-->id3((6));
-    id1-->id4((7));
-    id2-->id5((2));
-    id2-->id6((5));
-    id3-->id7((1));
-    id3-->id8((  ));
-    style id8 fill:#fff,stroke:#fff
-```
-
-::::
-
-:::: column
-
-**But:** Trier les tas.
-
-* `4 <=> max(4, 10, 8)`.
-* `4 <=> max(4, 6, 7)`.
-
-```{.mermaid format=pdf width=400 loc=figs/}
-graph TD;
-    id0((10))-->id1((7));
-    id0-->id2((8));
-    id1-->id3((6));
-    id1-->id4((4));
-    id2-->id5((2));
-    id2-->id6((5));
-    id3-->id7((1));
-    id3-->id8((  ));
-    style id8 fill:#fff,stroke:#fff
-```
-
-::::
-
-:::
-
-```
-        | 10 | 7 | 8 | 6 | 4 | 2 | 5 | 1 || 12 | 16
-```
-
-# Exemple de tri par tas (8/N)
-
-```
-        | 10 | 7 | 8 | 6 | 4 | 2 | 5 | 1 || 12 | 16
-```
-
-::: columns
-
-:::: column
-
-**But:** Trier les tas.
-
-* Échanger la racine, `10` (`max` de l'arbre) avec `1`.
-* Traiter la racine.
-
-```{.mermaid format=pdf width=400 loc=figs/}
-graph TD;
-    id0((1))-->id1((7));
-    id0-->id2((8));
-    id1-->id3((6));
-    id1-->id4((4));
-    id2-->id5((2));
-    id2-->id6((5));
-```
-
-::::
-
-:::: column
-
-**But:** Trier les tas.
-
-* `1 <=> max(1, 7, 8)`.
-* `5 <=> max(1, 2, 5)`.
-
-```{.mermaid format=pdf width=400 loc=figs/}
-graph TD;
-    id0((8))-->id1((7));
-    id0-->id2((5));
-    id1-->id3((6));
-    id1-->id4((4));
-    id2-->id5((2));
-    id2-->id6((1));
-```
-
-::::
-
-:::
-
-```
-        | 8 | 7 | 5 | 6 | 4 | 2 | 1 || 10 | 12 | 16
-```
-
-# Exemple de tri par tas (9/N)
-
-```
-        | 8 | 7 | 5 | 6 | 4 | 2 | 1 || 10 | 12 | 16
-```
-
-::: columns
-
-:::: column
-
-**But:** Trier les tas.
-
-* Échanger la racine, `8` (`max` de l'arbre) avec `1`.
-* Traiter la racine.
-
-```{.mermaid format=pdf width=400 loc=figs/}
-graph TD;
-    id0((1))-->id1((7));
-    id0-->id2((5));
-    id1-->id3((6));
-    id1-->id4((4));
-    id2-->id5((2));
-    id2-->id6((  ));
-    style id6 fill:#fff,stroke:#fff
-```
-
-::::
-
-:::: column
-
-**But:** Trier les tas.
-
-* `1 <=> max(1, 7, 5)`.
-* `1 <=> max(1, 6, 4)`.
-
-```{.mermaid format=pdf width=400 loc=figs/}
-graph TD;
-    id0((7))-->id1((6));
-    id0-->id2((5));
-    id1-->id3((1));
-    id1-->id4((4));
-    id2-->id5((2));
-    id2-->id6((  ));
-    style id6 fill:#fff,stroke:#fff
-```
-
-::::
-
-:::
-
-```
-        | 7 | 6 | 5 | 1 | 4 | 2 || 8 | 10 | 12 | 16
-```
-
-# Exemple de tri par tas (10/N)
-
-```
-        | 7 | 6 | 5 | 1 | 4 | 2 || 8 | 10 | 12 | 16
-```
-
-::: columns
-
-:::: column
-
-**But:** Trier les tas.
-
-* Échanger la racine, `7` (`max` de l'arbre) avec `2`.
-* Traiter la racine.
-
-```{.mermaid format=pdf width=150 loc=figs/}
-graph TD;
-    id0((2))-->id1((6));
-    id0-->id2((5));
-    id1-->id3((1));
-    id1-->id4((4));
-```
-
-::::
-
-:::: column
-
-**But:** Trier les tas.
-
-* `2 <=> max(2, 6, 5)`.
-* `2 <=> max(2, 1, 4)`.
-
-```{.mermaid format=pdf width=150 loc=figs/}
-graph TD;
-    id0((6))-->id1((4));
-    id0-->id2((5));
-    id1-->id3((1));
-    id1-->id4((2));
-```
-
-::::
-
-:::
-
-```
-        | 6 | 4 | 5 | 1 | 2 || 8 | 10 | 12 | 16
-```
-
-# Exemple de tri par tas (11/N)
-
-```
-        | 6 | 4 | 5 | 1 | 2 || 8 | 10 | 12 | 16
-```
-
-::: columns
-
-:::: column
-
-**But:** Trier les tas.
-
-* Échanger la racine, `6` (`max` de l'arbre) avec `2`.
-* Traiter la racine.
-
-```{.mermaid format=pdf width=150 loc=figs/}
-graph TD;
-    id0((2))-->id1((4));
-    id0-->id2((5));
-    id1-->id3((1));
-    id1-->id4((  ));
-    style id4 fill:#fff,stroke:#fff
-```
-
-::::
-
-:::: column
-
-**But:** Trier les tas.
-
-* `2 <=> max(2, 4, 5)`.
-* `2 <=> max(2, 1, 4)`.
-
-```{.mermaid format=pdf width=400 loc=figs/}
-graph TD;
-    id0((5))-->id1((4));
-    id0-->id2((2));
-    id1-->id3((1));
-    id1-->id4((  ));
-    style id4 fill:#fff,stroke:#fff
-```
-
-::::
-
-:::
-
-```
-        | 5 | 4 | 2 | 1 || 6 | 8 | 10 | 12 | 16
-```
-
-# Exemple de tri par tas (12/N)
-
-```
-        | 5 | 4 | 2 | 1 || 6 | 8 | 10 | 12 | 16
-```
-
-::: columns
-
-:::: column
-
-**But:** Trier les tas.
-
-* Échanger la racine, `5` (`max` de l'arbre) avec `1`.
-* Traiter la racine.
-
-```{.mermaid format=pdf width=400 loc=figs/}
-graph TD;
-    id0((1))-->id1((4));
-    id0-->id2((2));
-```
-
-::::
-
-:::: column
-
-**But:** Trier les tas.
-
-* `1 <=> max(1, 4, 2)`.
-
-```{.mermaid format=pdf width=400 loc=figs/}
-graph TD;
-    id0((4))-->id1((1));
-    id0-->id2((2));
-```
-
-::::
-
-:::
-
-```
-        | 4 | 1 | 2 || 5 | 6 | 8 | 10 | 12 | 16
-```
-
-# Exemple de tri par tas (13/N)
-
-```
-        | 4 | 1 | 2 || 5 | 6 | 8 | 10 | 12 | 16
-```
-
-::: columns
-
-:::: column
-
-**But:** Trier les tas.
-
-* Échanger la racine, `4` (`max` de l'arbre) avec `2`.
-* Traiter la racine.
-
-```{.mermaid format=pdf width=400 loc=figs/}
-graph TD;
-    id0((2))-->id1((1));
-    id0-->id2(( ));
-    style id2 fill:#fff,stroke:#fff
-```
-
-::::
-
-:::: column
-
-**But:** Trier les tas. Plus rien à trier
-
-* On fait les 2 dernières étapes en vitesse.
-* Échange `2` avec `1`.
-* Il reste que `1`. GGWP!
-
-
-::::
-
-:::
-
-```
-        | 1 | 2 | 4 | 5 | 6 | 8 | 10 | 12 | 16
-```
-
-# Exercice (10min)
-
-* Trier par tas le tableau
-
-```
-        | 1 | 2 | 4 | 5 | 6 | 8 | 10 | 12 | 16
-```
-
-* Mettez autant de détails que possible.
-* Que constatez-vous?
-* Postez le résultat sur matrix.
-
-
diff --git a/slides/cours_17.md b/slides/cours_17.md
deleted file mode 100644
index 014b123..0000000
--- a/slides/cours_17.md
+++ /dev/null
@@ -1,695 +0,0 @@
----
-title: "Tri par tas et arbres AVL"
-date: "2023-03-24"
----
-
-# Questions sur les notions du dernier cours (1/2)
-
-* Comment représenter un tableau sous forme d'arbre binaire?
-
-. . .
-
-* Qu'est-ce qu'un tas?
-
-. . .
-
-```
-        | 1 | 16 | 5 | 12 | 4 | 2 | 8 | 10 | 6 | 7 |
-```
-
-* Quel est l'arbre que cela représente?
-
-
-# Questions sur les notions du dernier cours (2/2)
-
-
-```{.mermaid format=pdf width=400 loc=figs/}
-graph TD;
-    id0((1))-->id1((16));
-    id0-->id2((5));
-    id1-->id3((12));
-    id1-->id4((4));
-    id2-->id5((2));
-    id2-->id6((8));
-    id3-->id7((10));
-    id3-->id8((6));
-    id4-->id9((7));
-    id4-->id10(( ));    
-    style id10 fill:#fff,stroke:#fff
-```
-
-# Exercice
-
-* Trier par tas le tableau
-
-```
-        | 1 | 2 | 4 | 5 | 6 | 8 | 10 | 12 | 16
-```
-
-* Mettez autant de détails que possible.
-* Que constatez-vous?
-* Postez le résultat sur matrix.
-
-# L'algorithme du tri par tas (1/2)
-
-\footnotesize
-
-## Deux étapes
-
-1. Entassement: transformer l'arbre en tas.
-2. Échanger la racine avec le dernier élément et entasser la racine.
-
-## Pseudo-code d'entassement de l'arbre (15 min, matrix)
-
-. . .
-
-```python
-rien tri_par_tas(tab)
-    entassement(tab)
-    échanger(tab[0], tab[size(tab)-1])
-    pour i de size(tab)-1 à 2 
-        tamisage(tab, 0)
-        échanger(tab[0], tab[i-1])
-
-rien entassement(tab)
-    pour i de size(tab)/2-1 à 0
-        tamisage(tab, i)
-
-rien tamisage(tab, i)
-    ind_max = ind_max(tab, i, gauche(i), droite(i))
-    si i != ind_max
-        échanger(tab[i], tab[ind_max])
-        tamisage(tab, ind_max)
-```
-
-# L'algorithme du tri par tas (2/2)
-
-* Fonctions utilitaires
-
-    ```python
-    entier ind_max(tab, i, g, d)
-        ind_max = i
-        si tab[ind_max] < tab[g] && size(tab) > g
-            ind_max = g
-        si tab[ind_mx] < tab[d] && size(tab) > d
-            ind_max = d
-        retourne ind_max
-
-    entier gauche(i)
-        retourne 2 * i + 1
-    
-    entier droite(i)
-        retourne 2 * i + 2
-    ```
-
-
-<!-- # L'algorithme du tri par tas (3/4)
-
-\footnotesize
-
-## Implémenter en C l'algorithme du tri par tas (matrix, 20min)
-
-. . .
-
-```C 
-void heapsort(int size, int tab[size]) {
-    heapify(size, tab);
-    swap(tab, tab + size - 1);
-    for (int s = size - 1; s > 1; s--) {
-        sift_up(s, tab, 0);
-        swap(tab, tab + s - 1);
-    }
-}
-void heapify(int size, int tab[size]) {
-    for (int i = size / 2 - 1; i >= 0; i--) {
-        sift_up(size, tab, i);
-    }
-}
-void sift_up(int size, int tab[size], int i) {
-    int ind_max = ind_max3(size, tab, i, left(i), right(i));
-    if (i != ind_max) {
-        swap(tab + i, tab + ind_max);
-        sift_up(size, tab, ind_max);
-    }
-}
-```
-
-# L'algorithme du tri par tas (4/4)
-
-\footnotesize
-
-## Fonctions utilitaires
-
-. . .
-
-```C
-int ind_max3(int size, int tab[size], int i, int l, int r) {
-    int ind_max = i;
-    if (l < size && tab[ind_max] < tab[l]) {
-        ind_max = l;
-    }
-    if (r < size && tab[ind_max] < tab[r]) {
-        ind_max = r;
-    }
-    return ind_max;
-}
-void swap(int *a, int *b) {
-    int tmp = *a;
-    *a      = *b;
-    *b      = tmp;
-}
-int left(int i) {
-    return 2 * i + 1;
-}
-int right(int i) {
-    return 2 * i + 2;
-}
-``` -->
-
-
-# Complexités
-
-::: columns
-
-:::: column
-
-## Complexité de la recherche
-
-1. En moyenne?
-2. Dans le pire des cas?
-
-. . .
-
-1. $O(\log_2(N))$
-2. $O(N)$
-
-::::
-
-:::: column
-
-```{.mermaid format=pdf width=400 loc=figs/}
-graph TD;
-    id0((10))-->id1((9));
-    id0-->id8((  ));
-    id1-->id2((7));
-    id1-->id9((  ));
-    id2-->id3((6));
-    id2-->id10((  ));
-    id3-->id4((5));
-    id3-->id11((  ));
-    style id8 fill:#fff,stroke:#fff
-    style id9 fill:#fff,stroke:#fff
-    style id10 fill:#fff,stroke:#fff
-    style id11 fill:#fff,stroke:#fff
-```
-
-::::
-
-:::
-
-# Un meilleur arbre
-
-* Quelle propriété doit satisfaire un arbre pour être $O(\log_2(N))$?
-
-. . .
-
-* Si on a environ le même nombre de nœuds dans les sous-arbres.
-
-## Définition
-
-Un arbre binaire est parfaitement équilibré si, pour chaque
-nœud, la différence entre les nombres de nœuds des sous-
-arbres gauche et droit vaut au plus 1.
-
-* Si l'arbre est **parfaitement équilibré**, alors tout ira bien.
-* Quelle est la hauteur (profondeur) d'un arbre parfaitement équilibré?
-
-. . .
-
-* $O(\log_2(N))$.
-
-
-# Équilibre parfait ou pas?
-
-::: columns
-
-:::: column
-
-```{.mermaid format=pdf width=400 loc=figs/}
-graph TD;
-    id0((W))-->id1((B));
-    id0-->id8((Y));
-    id1-->id2((A));
-    id1-->id9((  ));
-    id8-->id10((X));
-    id8-->id11((  ));
-    style id9 fill:#fff,stroke:#fff
-    style id11 fill:#fff,stroke:#fff
-```
-
-::::
-
-:::: column
-
-. . .
-
-```
-É
-Q
-U
-I
-L
-I
-B
-R
-É
-```
-
-::::
-
-:::
-
-# Équilibre parfait ou pas?
-
-::: columns
-
-:::: column
-
-```{.mermaid format=pdf width=400 loc=figs/}
-graph TD;
-    id0((16))-->id1((10));
-    id0-->id2((19));
-    id1-->id3((8));
-    id1-->id4((12));
-    id4-->id5((11));
-    id4-->id6((  ));
-    id2-->id7((17));
-    id2-->id8((  ));
-    id7-->id9((  ));
-    id7-->id10((18));
-    style id6 fill:#fff,stroke:#fff
-    style id8 fill:#fff,stroke:#fff
-    style id9 fill:#fff,stroke:#fff
-```
-
-::::
-
-:::: column
-
-. . .
-
-```
-P 
-A
-S 
-
-É
-Q
-U
-I
-L
-I
-B
-R
-É
-```
-
-::::
-
-:::
-
-# Arbres AVL
-
-\footnotesize
-
-* Quand est-ce qu'on équilibre un arbre?
-
-. . .
-
-* A l'insertion/suppression.
-* Maintenir un arbre en état d'équilibre parfait: cher (insertion, suppression).
-* On peut "relaxer" la condition d'équilibre: profondeur (hauteur) au lieu du
-  nombre de nœuds:
-    * La hauteur $\sim\log_2(N)$.
-
-## Définition
-
-Un arbre AVL (Adelson-Velskii et Landis) est un arbre binaire de recherche dans
-lequel, pour chaque nœud, la différence de hauteur entre le sous-arbre gauche et droit vaut au plus 1.
-
-* Relation entre nœuds et hauteur:
-$$
-\log_2(1+N)\leq 1+H\leq 1.44\cdot\log_2(2+N),\quad N=10^5,\ 17\leq H \leq 25.
-$$
-* Permet l'équilibrage en temps constant: insertion/suppression $O(\log_2(N))$.
-
-# Notation
-
-* `hg`: hauteur du sous-arbre gauche.
-* `hd`: hauteur du sous-arbre droit.
-* `facteur d'équilibre = fe = hd - hg`
-* Que vaut `fe` si l'arbre est AVL?
-
-. . .
-
-* `fe = {-1, 0, 1}`
-
-
-# AVL ou pas?
-
-::: columns
-
-:::: column
-
-```{.mermaid format=pdf width=400 loc=figs/}
-graph TD;
-    id0((12))-->id1((10));
-    id0-->id2((19));
-    id2-->id3((17));
-    id2-->id4((97));
-```
-
-::::
-
-:::: column
-
-. . .
-
-```
-A
-V
-L
-```
-
-::::
-
-:::
-
-# AVL ou pas?
-
-::: columns
-
-:::: column
-
-```{.mermaid format=pdf width=400 loc=figs/}
-graph TD;
-    id0((12))-->id1((1));
-    id0-->id2((19));
-    id2-->id3((17));
-    id2-->id4((97));
-    id4-->id5((37));
-    id4-->id6((  ));
-    style id6 fill:#fff,stroke:#fff
-```
-
-::::
-
-:::: column
-
-. . .
-
-```
-P
-A
-S
-
-A
-V
-L
-```
-
-::::
-
-:::
-
-# Insertion dans un arbre AVL (1/N)
-
-1. On part d'un arbre AVL.
-2. On insère un nouvel élément.
-
-::: columns
-
-:::: column
-
-* `hd ? hg`.
-* Insertion de `4`?
-
-```{.mermaid format=pdf width=400 loc=figs/}
-graph TD;
-    id0((12))-->id1((1));
-    id0-->id2((19));
-```
-
-::::
-
-:::: column
-
-. . .
-
-* `hd = hg`
-
-```{.mermaid format=pdf width=400 loc=figs/}
-graph TD;
-    id0((12))-->id1((1));
-    id0-->id2((19));
-    id1-->id4((  ));
-    id1-->id5((4));
-    style id4 fill:#fff,stroke:#fff
-```
-
-* `fe = -1`
-
-::::
-
-:::
-
-# Insertion dans un arbre AVL (2/N)
-
-1. On part d'un arbre AVL.
-2. On insère un nouvel élément.
-
-::: columns
-
-:::: column
-
-* `hd ? hg`.
-* Insertion de `4`?
-
-```{.mermaid format=pdf width=400 loc=figs/}
-graph TD;
-    id0((12))-->id1((1));
-    id0-->id2((19));
-    id2-->id3((18));
-    id2-->id4((  ));
-    style id4 fill:#fff,stroke:#fff
-```
-
-::::
-
-:::: column
-
-. . .
-
-* `hd < hg`
-
-```{.mermaid format=pdf width=400 loc=figs/}
-graph TD;
-    id0((12))-->id1((1));
-    id0-->id2((19));
-    id2-->id3((18));
-    id2-->id4((  ));
-    id1-->id5((  ));
-    id1-->id6((4));
-    style id4 fill:#fff,stroke:#fff
-    style id5 fill:#fff,stroke:#fff
-```
-
-* `fe = 0`
-
-::::
-
-:::
-
-# Insertion dans un arbre AVL (3/N)
-
-\footnotesize
-
-1. On part d'un arbre AVL.
-2. On insère un nouvel élément.
-
-::: columns
-
-:::: column
-
-* `hd ? hg`.
-* Insertion de `4`?
-
-```{.mermaid format=pdf width=400 loc=figs/}
-graph TD;
-    id0((12))-->id1((1));
-    id0-->id2((19));
-    id1-->id3((  ));
-    id1-->id4((6));
-    id2-->id5((  ));
-    id2-->id6((  ));
-    style id3 fill:#fff,stroke:#fff
-    style id5 fill:#fff,stroke:#fff
-    style id6 fill:#fff,stroke:#fff
-```
-
-::::
-
-:::: column
-
-. . .
-
-* `hd < hg`
-
-```{.mermaid format=pdf width=400 loc=figs/}
-graph TD;
-    id0((12))-->id1((1));
-    id0-->id2((19));
-    id1-->id3((  ));
-    id1-->id4((6));
-    id4-->id5((4));
-    id4-->id6((  ));
-    id2-->id7((  ));
-    id2-->id8((  ));
-    style id3 fill:#fff,stroke:#fff
-    style id6 fill:#fff,stroke:#fff
-    style id7 fill:#fff,stroke:#fff
-    style id8 fill:#fff,stroke:#fff
-```
-
-::::
-
-:::
-
-**Déséquilibre!** Que vaut `fe`?
-
-. . .
-
-* `fe = 2`
-
-# Les cas de déséquilibre
-
-
-::: columns
-
-:::: column
-
-## Cas 1a
-
-* `u`, `v`, `w` même hauteur.
-* déséquilibre en `B` après insertion dans `u`
-
-![Après insertion](figs/cas1a_gauche.png)
-
-::::
-
-:::: column
-
-## Cas 1a
-
-* Comment rééquilibrer?
-
-. . .
-
-* ramène `u`, `v` `w` à la même hauteur.
-* `v` à droite de `A` (gauche de `B`)
-
-![Après équilibrage](figs/cas1a_droite.png)
-
-::::
-
-:::
-
-# Les cas de déséquilibre
-
-
-::: columns
-
-:::: column
-
-## Cas 1b (symétrique 1a)
-
-![Après insertion](figs/cas1b_gauche.png)
-
-::::
-
-:::: column
-
-## Cas 1b (symétrique 1a)
-
-* Comment rééquilibrer?
-
-. . .
-
-![Après équilibrage](figs/cas1b_droite.png)
-
-::::
-
-:::
-
-# Les cas de déséquilibre
-
-
-::: columns
-
-:::: column
-
-## Cas 2a
-
-* `h(v1)=h(v2), h(u)=h(w)`.
-* déséquilibre en `C` après insertion dans `v2`
-
-![Après insertion](figs/cas2a_gauche.png)
-
-::::
-
-:::: column
-
-## Cas 2a
-
-* Comment rééquilibrer?
-
-. . .
-
-* ramène `u`, `v2`, `w` à la même hauteur (`v1` pas tout à fait).
-* `v2` à droite de `B` (gauche de `C`)
-* `B` à droite de `A` (gauche de `C`)
-* `v1` à droite de `A` (gauche de `B`)
-
-![Après équilibrage](figs/cas2a_droite.png)
-
-::::
-
-:::
-
-
-# Les cas de déséquilibre
-
-
-::: columns
-
-:::: column
-
-## Cas 2b (symétrique 2a)
-
-![Après insertion](figs/cas2b_gauche.png)
-
-::::
-
-:::: column
-
-## Cas 2b (symétrique 2a)
-
-* Comment rééquilibrer?
-
-. . .
-
-![Après équilibrage](figs/cas2b_droite.png)
-
-::::
-
-:::
diff --git a/slides/cours_18.md b/slides/cours_18.md
deleted file mode 100644
index 15f609f..0000000
--- a/slides/cours_18.md
+++ /dev/null
@@ -1,947 +0,0 @@
----
-title: "Arbres AVL"
-date: "2023-03-31"
----
-
-# Questions sur les notions du dernier cours
-
-* Qu'est-ce qu'un arbre AVL?
-
-. . .
-
-* Un arbre binaire qui a la propriété suivante:
-    * La différence de hauteur de chaque noeud est d'au plus 1.
-    * Tous les noeuds ont `fe = hd - hg = {-1, 0, 1}`.
-
-* Pourquoi utiliser un arbre AVL plutôt qu'un arbre binaire de recherche?
-
-. . .
-
-* Insertion/recherche/... toujours en $O(\log_2(N))$.
-
-# AVL ou pas?
-
-\footnotesize
-
-```{.mermaid format=pdf width=400 loc=figs/}
-graph TD;
-    id0((21))-->id1((9));
-    id0-->id2((40));
-    id1-->id3((5));
-    id1-->id4((10));
-    id3-->id5((3));
-    id3-->id6((7))
-    id6-->id7((6))
-    id6-->id8((  ))
-    id2-->id9((33))
-    id2-->id10((61))
-    id9-->id11((22))
-    id9-->id12((39))
-    id10-->id13((  ))
-    id10-->id14((81))
-    style id8 fill:#fff,stroke:#fff
-    style id13 fill:#fff,stroke:#fff
-```
-
-. . .
-
-* Ajouter un noeud pour qu'il le soit plus.
-
-# Insertion dans un arbre AVL
-
-\footnotesize
-
-1. On part d'un arbre AVL.
-2. On insère un nouvel élément.
-
-::: columns
-
-:::: column
-
-* `hd ? hg`.
-* Insertion de `4`?
-
-```{.mermaid format=pdf width=400 loc=figs/}
-graph TD;
-    id0((12))-->id1((1));
-    id0-->id2((19));
-    id1-->id3((  ));
-    id1-->id4((6));
-    id2-->id5((  ));
-    id2-->id6((  ));
-    style id3 fill:#fff,stroke:#fff
-    style id5 fill:#fff,stroke:#fff
-    style id6 fill:#fff,stroke:#fff
-```
-
-::::
-
-:::: column
-
-. . .
-
-* `hd > hg`
-
-```{.mermaid format=pdf width=400 loc=figs/}
-graph TD;
-    id0((12))-->id1((1));
-    id0-->id2((19));
-    id1-->id3((  ));
-    id1-->id4((6));
-    id4-->id5((4));
-    id4-->id6((  ));
-    id2-->id7((  ));
-    id2-->id8((  ));
-    style id3 fill:#fff,stroke:#fff
-    style id6 fill:#fff,stroke:#fff
-    style id7 fill:#fff,stroke:#fff
-    style id8 fill:#fff,stroke:#fff
-```
-
-::::
-
-:::
-
-**Déséquilibre!** Que vaut `fe`?
-
-. . .
-
-* `fe = 2`
-
-# Les cas de déséquilibre
-
-
-::: columns
-
-:::: column
-
-## Cas 1a
-
-* `u`, `v`, `w` même hauteur.
-* déséquilibre en `B` après insertion dans `u`
-
-![Après insertion](figs/cas1a_gauche.png)
-
-::::
-
-:::: column
-
-## Cas 1a
-
-* Comment rééquilibrer?
-
-. . .
-
-* ramène `u`, `v` `w` à la même hauteur.
-* `v` à droite de `A` (gauche de `B`)
-
-![Après équilibrage](figs/cas1a_droite.png)
-
-::::
-
-:::
-
-# Les cas de déséquilibre
-
-
-::: columns
-
-:::: column
-
-## Cas 1b (symétrique 1a)
-
-![Après insertion](figs/cas1b_gauche.png)
-
-::::
-
-:::: column
-
-## Cas 1b (symétrique 1a)
-
-* Comment rééquilibrer?
-
-. . .
-
-![Après équilibrage](figs/cas1b_droite.png)
-
-::::
-
-:::
-
-# Les cas de déséquilibre
-
-
-::: columns
-
-:::: column
-
-## Cas 2a
-
-* `h(v1)=h(v2), h(u)=h(w)`.
-* déséquilibre en `C` après insertion dans `v2`
-
-![Après insertion](figs/cas2a_gauche.png)
-
-::::
-
-:::: column
-
-## Cas 2a
-
-* Comment rééquilibrer?
-
-. . .
-
-* ramène `u`, `v2`, `w` à la même hauteur (`v1` pas tout à fait).
-* `v2` à droite de `B` (gauche de `C`)
-* `B` à droite de `A` (gauche de `C`)
-* `v1` à droite de `A` (gauche de `B`)
-
-![Après équilibrage](figs/cas2a_droite.png)
-
-::::
-
-:::
-
-
-# Les cas de déséquilibre
-
-
-::: columns
-
-:::: column
-
-## Cas 2b (symétrique 2a)
-
-![Après insertion](figs/cas2b_gauche.png)
-
-::::
-
-:::: column
-
-## Cas 2b (symétrique 2a)
-
-* Comment rééquilibrer?
-
-. . .
-
-![Après équilibrage](figs/cas2b_droite.png)
-
-::::
-
-:::
-
-# Le facteur d'équilibre (balance factor)
-
-## Définition
-
-```
-fe(arbre) = hauteur(droite(arbre)) - hauteur(gauche(arbre))
-```
-
-## Valeurs possibles?
-
-. . .
-
-```
-fe = {-1, 0, 1} // arbre AVL
-fe = {-2, 2}    // arbre déséquilibré
-```
-
-![Illustration du `fe`](figs/facteur_equilibre.png){width=40%}
-
-# Algorithme d'insertion
-
-* Insérer le noeud comme d'habitude.
-* Mettre à jour les facteurs d'équilibre jusqu'à la racine (ou au premier
-  noeud déséquilibré).
-* Rééquilibrer le noeud si nécessaire.
-
-## Cas possibles
-
-::: columns
-
-:::: column
-
-## Sous-arbre gauche (avant)
-
-```
-fe(P) =  1 
-fe(P) =  0 
-fe(P) = -1 
-```
-
-::::
-
-:::: column
-
-## Sous-arbre gauche (après)
-
-. . .
-
-```
-=> fe(P) =  0 
-=> fe(P) = -1 
-=> fe(P) = -2 // Rééquilibrer P
-```
-
-::::
-
-:::
-
-# Algorithme d'insertion
-
-* Insérer le noeud comme d'habitude.
-* Mettre à jour les facteurs d'équilibre jusqu'à la racine (ou au premier
-  noeud déséquilibré).
-* Rééquilibrer le noeud si nécessaire.
-
-## Cas possibles
-
-::: columns
-
-:::: column
-
-## Sous-arbre droit (avant)
-
-```
-fe(P) =  1 
-fe(P) =  0 
-fe(P) = -1 
-```
-
-::::
-
-:::: column
-
-## Sous-arbre droit (après)
-
-. . .
-
-```
-=> fe(P) =  0 
-=> fe(P) = +1 
-=> fe(P) = +2 // Rééquilibrer P
-```
-
-::::
-
-:::
-
-# Rééquilibrage
-
-## Lien avec les cas vus plus tôt
-
-```
-fe(P) = -2 && fe(gauche(P)) = -1 => cas 1a
-fe(P) = -2 && fe(gauche(P)) = +1 => cas 2a
-
-fe(P) = +2 && fe(droite(P)) = -1 => cas 2b
-fe(P) = +2 && fe(droite(P)) = +1 => cas 1b
-```
-
-## Dessiner les différents cas, sur le dessin ci-dessous
-
-![On verra un peu après les rotations.](figs/rotation_gauche_droite.png)
-
-# La rotation
-
-## La rotation gauche (5min, matrix)
-
-![L'arbre de droite devient celui de gauche. Comment?](figs/rotation_gauche_droite.png)
-
-. . .
-
-\footnotesize
-```
-arbre rotation_gauche(arbre P) 
-    si est_non_vide(P)
-        Q = droite(P)
-        droite(P) = gauche(Q)
-        gauche(Q) = P
-        retourne Q
-    retourne P
-```
-
-# La rotation en C (1/2)
-
-## La rotation gauche
-
-```
-arbre rotation_gauche(arbre P) 
-    si est_non_vide(P)
-        Q = droite(P)
-        droite(P) = gauche(Q)
-        gauche(Q) = P
-        retourne Q
-    retourne P
-```
-
-## Écrire le code C correspondant (5min, matrix)
-
-1. Structure de données
-2. Fonction `tree_t rotation_left(tree_t tree)`
-
-. . .
-
-\footnotesize
-```C
-typedef struct _node {
-    int key;
-    struct _node *left, *right;
-    int bf; // balance factor
-} node;
-typedef node *tree_t;
-```
-
-# La rotation en C (2/2)
-
-\footnotesize
-
-```C
-tree_t rotation_left(tree_t tree) {
-    tree_t subtree = NULL;
-    if (NULL != tree) {
-        subtree = tree->right;
-        tree->right = subtree->left;
-        subtree->left = tree;
-    }
-    return subtree;
-}
-```
-
-. . .
-
-* Et la rotation à droite, pseudo-code (5min)?
-
-. . .
-
-```
-arbre rotation_droite(arbre P) 
-    si est_non_vide(P)
-        Q = gauche(P)
-        gauche(P) = droite(Q)
-        droite(Q) = P
-        retourne Q
-    retourne P
-```
-
-<!-- ```C
-tree_t rotation_right(tree_t tree) {
-    tree_t subtree = NULL;
-    if (NULL != tree) {
-        subtree = tree->left;
-        tree->left = subtree->right;
-        subtree->right = tree;
-    }
-    return subtree;
-}
-``` -->
-
-# Exemple de rotation (1/2)
-
-## Insertion de 9?
-
-```{.mermaid format=pdf width=400 loc=figs/}
-graph TD;
-    id0((5))-->id1((1));
-    id0-->id2((6));
-    id2-->id3((  ));
-    id2-->id4((8));
-    style id3 fill:#fff,stroke:#fff
-```
-
-# Exemple de rotation (2/2)
-
-::: columns
-
-:::: column
-
-## Quelle rotation et sur quel noeud (5 ou 6)?
-
-```{.mermaid format=pdf width=400 loc=figs/}
-graph TD;
-    id0((5))-->id1((1));
-    id0-->id2((6));
-    id2-->id3((  ));
-    id2-->id4((8));
-    id4-->id5((  ));
-    id4-->id6((9));
-    style id3 fill:#fff,stroke:#fff
-    style id5 fill:#fff,stroke:#fff
-```
-
-::::
-
-:::: column
-
-. . .
-
-## Sur le plus jeune évidemment!
-
-```{.mermaid format=pdf width=400 loc=figs/}
-graph TD;
-    id0((5))-->id1((1));
-    id0-->id2((8));
-    id2-->id3((6));
-    id2-->id4((9));
-```
-
-::::
-
-:::
-
-* Cas `1a/b` *check*!
-
-
-# La rotation gauche-droite
-
-## Là c'est plus difficile (cas 2a/b)
-
-![La double rotation de l'enfer.](figs/double_rotation_gauche_droite.png)
-
-# Exercices
-
-## Faire l'implémentation de la double rotation (pas corrigé, 5min)
-
-# Exercices
-
-::: columns
-
-:::: column
-
-## Insérer 50, ex 10min (matrix)
-
-```{.mermaid format=pdf width=400 loc=figs/}
-graph TD;
-    id0((89))-->id1((71));
-    id0-->id2((90));
-    id1-->id3((44));
-    id3-->id4((37));
-    id3-->id5((61));
-    id1-->id6((81))
-    id2-->id7((  ))
-    id2-->id8((100))
-    style id7 fill:#fff,stroke:#fff
-```
-
-::::
-
-:::: column
-
-. . .
-
-## Où se fait la rotation?
-
-```{.mermaid format=pdf width=400 loc=figs/}
-graph TD;
-    id0((89))-->id1((71));
-    id0-->id2((90));
-    id1-->id3((44));
-    id3-->id4((37));
-    id3-->id5((61));
-    id1-->id6((81))
-    id2-->id7((  ))
-    id2-->id8((100))
-    id5-->id9((50))
-    id5-->id10((  ))
-    style id7 fill:#fff,stroke:#fff
-    style id10 fill:#fff,stroke:#fff
-```
-
-::::
-
-:::
-
-# Exercices
-
-::: columns
-
-:::: column
-
-## Rotation gauche en 44
-
-```{.mermaid format=pdf width=400 loc=figs/}
-graph TD;
-    id0((89))-->id1((71));
-    id0-->id2((90));
-    id1-->id3((61));
-    id1-->id10((81));
-    id3-->id4((44));
-    id3-->id5((  ));
-    id4-->id6((37))
-    id4-->id7((50))
-    id2-->id8((  ))
-    id2-->id9((100))
-    style id5 fill:#fff,stroke:#fff
-    style id8 fill:#fff,stroke:#fff
-```
-
-::::
-
-:::: column
-
-. . .
-
-## Rotation à droite en 71
-
-```{.mermaid format=pdf width=400 loc=figs/}
-graph TD;
-    id0((89))-->id1((61));
-    id0-->id2((90));
-    id1-->id3((44));
-    id1-->id10((71));
-    id3-->id4((37));
-    id3-->id5((50));
-    id2-->id8((  ));
-    id2-->id9((100));
-    id10-->id11((  ))
-    id10-->id12((81))
-    style id8 fill:#fff,stroke:#fff
-    style id11 fill:#fff,stroke:#fff
-```
-
-::::
-
-:::
-
-# Exercice de la mort
-
-Soit l’arbre AVL suivant:
-
-::: columns
-
-:::: column
-
-```{.mermaid format=pdf width=400 loc=figs/}
-graph TD;
-    id0((60))-->id1((40));
-    id0-->id2((120));
-    id1-->id3((20));
-    id1-->id4((50));
-    id3-->id5((10));
-    id3-->id6((30));
-    id2-->id7((100));
-    id2-->id8((140));
-    id7-->id9((80))
-    id7-->id10((110))
-    id9-->id11((70))
-    id9-->id12((90))
-    id8-->id13((130))
-    id8-->id14((160))
-    id14-->id15((150))
-    id14-->id16((170))
-```
-
-::::
-
-:::: column
-
-1. Montrer les positions des insertions de feuille qui conduiront à un arbre
-   désequilibré.
-2. Donner les facteurs d’equilgaucheibre.
-3. Dessiner et expliquer les modifications de l’arbre lors de l’insertion de la
-   valeur `65`. On mentionnera les modifications des facteurs
-   d’équilibre.
-
-::::
-
-:::
-
-# Encore un petit exercice
-
-* Insérer les nœuds suivants dans un arbre AVL
-
-```
-25 | 60 | 35 | 10 | 5 | 20 | 65 | 45 | 70 | 40 
-    | 50 | 55 | 30 | 15
-```
-
-## Un à un et le/la premier/ère qui poste la bonne réponse sur matrix a un point
-
-# Suppression dans un arbre AVL
-
-
-::: columns
-
-:::: column
-
-## Algorithme par problème: supprimer 10
-
-```{.mermaid format=pdf width=400 loc=figs/}
-graph TD;
-    id0((8))-->id1((4));
-    id0-->id2((10));
-    id1-->id3((2));
-    id1-->id4((6));
-    id3-->id5((1));
-    id3-->id6((  ))
-    id4-->id7((  ))
-    id4-->id8((7))
-    id2-->id9((9))
-    id2-->id10((14))
-    id10-->id11((12))
-    id10-->id12((16))
-    style id6 fill:#fff,stroke:#fff
-    style id7 fill:#fff,stroke:#fff
-```
-
-::::
-
-:::: column
-
-. . .
-
-## Algorithme par problème: supprimer 10
-
-```{.mermaid format=pdf width=400 loc=figs/}
-graph TD;
-    id0((8))-->id1((4));
-    id0-->id2((12));
-    id1-->id3((2));
-    id1-->id4((6));
-    id3-->id5((1));
-    id3-->id6((  ))
-    id4-->id7((  ))
-    id4-->id8((7))
-    id2-->id9((9))
-    id2-->id10((14))
-    id10-->id11((  ))
-    id10-->id12((16))
-    style id6 fill:#fff,stroke:#fff
-    style id7 fill:#fff,stroke:#fff
-    style id11 fill:#fff,stroke:#fff
-```
-
-::::
-
-:::
-
-# Suppression dans un arbre AVL
-
-
-::: columns
-
-:::: column
-
-## Algorithme par problème: supprimer 8
-
-```{.mermaid format=pdf width=400 loc=figs/}
-graph TD;
-    id0((8))-->id1((4));
-    id0-->id2((12));
-    id1-->id3((2));
-    id1-->id4((6));
-    id3-->id5((1));
-    id3-->id6((  ))
-    id4-->id7((  ))
-    id4-->id8((7))
-    id2-->id9((9))
-    id2-->id10((14))
-    id10-->id11((  ))
-    id10-->id12((16))
-    style id6 fill:#fff,stroke:#fff
-    style id7 fill:#fff,stroke:#fff
-    style id11 fill:#fff,stroke:#fff
-```
-
-::::
-
-:::: column
-
-. . .
-
-## Algorithme par problème: rotation de 12
-
-```{.mermaid format=pdf width=400 loc=figs/}
-graph TD;
-    id0((9))-->id1((4));
-    id0-->id2((12));
-    id1-->id3((2));
-    id1-->id4((6));
-    id3-->id5((1));
-    id3-->id6((  ))
-    id4-->id7((  ))
-    id4-->id8((7))
-    id2-->id9((  ))
-    id2-->id10((14))
-    id10-->id11((  ))
-    id10-->id12((16))
-    style id6 fill:#fff,stroke:#fff
-    style id7 fill:#fff,stroke:#fff
-    style id9 fill:#fff,stroke:#fff
-    style id11 fill:#fff,stroke:#fff
-```
-
-::::
-
-:::
-
-# Suppression dans un arbre AVL
-
-::: columns
-
-:::: column
-
-## Algorithme par problème: rotation de 12
-
-```{.mermaid format=pdf width=400 loc=figs/}
-graph TD;
-    id0((9))-->id1((4));
-    id0-->id2((14));
-    id1-->id3((2));
-    id1-->id4((6));
-    id3-->id5((1));
-    id3-->id6((  ))
-    id4-->id7((  ))
-    id4-->id8((7))
-    id2-->id9((12))
-    id2-->id10((16))
-    style id6 fill:#fff,stroke:#fff
-    style id7 fill:#fff,stroke:#fff
-```
-
-::::
-
-:::: column
-
-. . .
-
-1. On supprime comme d'habitude.
-2. On rééquilibre si besoin à l'endroit de la suppression.
-
-* Facile non?
-
-. . .
-
-* Plus dur....
-
-::::
-
-:::
-
-# Suppression dans un arbre AVL 2.0
-
-::: columns
-
-:::: column
-
-## Algorithme par problème: suppression de 30
-
-```{.mermaid format=pdf width=400 loc=figs/}
-graph TD;
-    id0((50))-->id1((30));
-    id0-->id2((100));
-    id1-->id3((10));
-    id1-->id4((40));
-    id3-->id5((  ));
-    id3-->id6((20))
-    id2-->id7((80))
-    id2-->id8((200))
-    id7-->id9((70))
-    id7-->id10((90))
-    id9-->id11((60))
-    id9-->id12((  ))
-    id8-->id13((  ))
-    id8-->id14((300))
-    style id5 fill:#fff,stroke:#fff
-    style id12 fill:#fff,stroke:#fff
-    style id13 fill:#fff,stroke:#fff
-```
-
-::::
-
-:::: column
-
-. . .
-
-## Algorithme par problème: rotation GD autour de 40
-
-```{.mermaid format=pdf width=400 loc=figs/}
-graph TD;
-    id0((50))-->id1((40));
-    id0-->id2((100));
-    id1-->id3((10));
-    id1-->id4((  ));
-    id3-->id5((  ));
-    id3-->id6((20))
-    id2-->id7((80))
-    id2-->id8((200))
-    id7-->id9((70))
-    id7-->id10((90))
-    id9-->id11((60))
-    id9-->id12((  ))
-    id8-->id13((  ))
-    id8-->id14((300))
-    style id4 fill:#fff,stroke:#fff
-    style id5 fill:#fff,stroke:#fff
-    style id12 fill:#fff,stroke:#fff
-    style id13 fill:#fff,stroke:#fff
-```
-
-::::
-
-:::
-
-# Suppression dans un arbre AVL 2.0
-
-::: columns
-
-:::: column
-
-## Argl! 50 est déséquilibré!
-
-```{.mermaid format=pdf width=400 loc=figs/}
-graph TD;
-    id0((50))-->id1((20));
-    id0-->id2((100));
-    id1-->id3((10));
-    id1-->id4((40));
-    id2-->id7((80))
-    id2-->id8((200))
-    id7-->id9((70))
-    id7-->id10((90))
-    id9-->id11((60))
-    id9-->id12((  ))
-    id8-->id13((  ))
-    id8-->id14((300))
-    style id12 fill:#fff,stroke:#fff
-    style id13 fill:#fff,stroke:#fff
-```
-
-::::
-
-:::: column
-
-. . .
-
-## Algorithme par problème: rotation DG autour de 50
-
-```{.mermaid format=pdf width=400 loc=figs/}
-graph TD;
-    id0((80))-->id1((50));
-    id0-->id2((100));
-    id1-->id3((20));
-    id1-->id4((70));
-    id3-->id5((10));
-    id3-->id6((40));
-    id4-->id9((60))
-    id4-->id10((  ))
-    id2-->id7((90))
-    id2-->id8((200))
-    id8-->id13((  ))
-    id8-->id14((300))
-    style id10 fill:#fff,stroke:#fff
-    style id13 fill:#fff,stroke:#fff
-```
-
-::::
-
-:::
-
-# Résumé de la suppression
-
-1. On supprime comme pour un arbre binaire de recherche.
-2. Si un nœud est déséquilibré, on le rééquilibre.
-    * Cette opération peut déséquilibrer un autre nœud.
-3. On continue à rééquilibrer tant qu'il y a des nœuds à équilibrer.
diff --git a/slides/cours_19.md b/slides/cours_19.md
deleted file mode 100644
index 4394b42..0000000
--- a/slides/cours_19.md
+++ /dev/null
@@ -1,488 +0,0 @@
----
-title: "Arbres quaternaires"
-date: "2023-04-28"
----
-
-
-# Les arbres quaternaires
-
-## Définition
-
-Arbre dont chaque nœud a 4 enfants ou aucun. 
-
-![Un exemple d'arbre quaternaire.](figs/quad_ex.svg)
-
-# Les arbres quaternaires
-
-## Cas d'utilisation
-
-Typiquement utilisés pour représenter des données bidimensionnelles.
-
-Son équivalent tri-dimensionnel est l'octree (chaque nœud a 8 enfants ou aucun).
-
-## Cas d'utilisation: images
-
-* Stockage: compression.
-* Transformations: symétries, rotations, etc.
-
-## Cas d'utilisation: simulation
-
-* Indexation spatiale.
-* Détection de collisions.
-* Simulation de galaxies, Barnes-Hut.
-
-# Exemple de compression
-
-::: columns
-
-:::: {.column width=30%}
-
-## Comment représenter l'image
-
-![Image noir/blanc.](figs/board_blacked_parts.svg)
-
-::::
-
-:::: {.column width=70%}
-
-## Sous la forme d'un arbre quaternaire?
-
-. . .
-
-![L'arbre quaternaire correspondant.](figs/quad_img.svg)
-
-**Économie?**
-
-. . .
-
-Image 64 pixels, arbre 25 nœuds.
-
-::::
-
-:::
-
-
-# Structure de données
-
-::: columns
-
-:::: {.column width=50%}
-
-## Pseudo-code?
-
-. . .
-
-```python
-struct node
-    info
-    node sup_gauche, sup_droit,
-        inf_gauche, inf_droit
-```
-
-![Un nœud d'arbre quaternaire.](figs/quad_struct.svg)
-
-::::
-
-:::: {.column width=50%}
-
-## En C?
-
-. . .
-
-```C
-struct _node {
-    int info;
-    struct _node *sup_left;
-    struct _node *sup_right;
-    struct _node *inf_left;
-    struct _node *inf_right;
-};
-```
-
-* Pourquoi le `*` est important?
-
-. . .
-
-* Type récursif => taille inconnue à la compilation.
-
-::::
-
-:::
-
-# Une fonctionnalité simple
-
-\footnotesize
-
-## La fonction `est_feuille(noeud)`
-
-* Problème avec cette implémentation?
-
-```python
-bool est_feuille(noeud) 
-    retourne
-        est_vide(sup_gauche(noeud)) &&
-        est_vide(sup_droit(noeud)) &&
-        est_vide(inf_gauche(noeud)) &&
-        est_vide(inf_droit(noeud))
-```
-
-. . .
-
-* Inutile d'avoir 4 conditions (soit 4 enfants soit aucun!)
-* Facile d'en oublier un!
-* Comment changer la structure pour que ça soit moins terrible?
-
-. . .
-
-```python
-struct node
-    info
-    node enfant[4]
-```
-
-# Structure de données
-
-## En C?
-
-. . .
-
-```C 
-typedef struct _node {
-    int info;
-    struct _node *child[4];
-} node;
-```
-
-## Fonction `is_leaf(node *tree)`?
-
-. . .
-
-```C 
-bool is_leaf(node *tree) {
-    return (NULL == tree->child[0]); // only first matters
-}
-```
-
-# Problème à résoudre
-
-* Construire un arbre quaternaire à partir d'une image:
-    * Créer l'arbre (allouer la mémoire pour tous les nœuds),
-    * Le remplir avec les valeurs des pixels.
-* Compression de l'image:
-    * Si les pixels sont les mêmes dans le quadrant on supprime le sous-arbre (sans perte)
-    * Si les pixels dévient pas trop on supprime le quadrant (avec perte)
-
-# Création de l'arbre
-
-## Comment créer un arbre de profondeur `prof` (3min)?
-
-. . .
-
-```python
-arbre creer_arbre(prof)
-    n = nouveau_noeud() # alloue la mémoire
-    si prof > 0
-        pour i = 0 à 3
-            n.enfant[i] = creer_arbre(prof-1)
-    retourne n
-```
-
-## En `C` (3 min, matrix)?
-
-. . .
-
-```C
-node *qt_create(int depth) {
-    node *n = calloc(1, sizeof(node));
-    if (depth > 0) {
-        for (int i = 0; i < 4; ++i) {
-            n->child[i] = qt_create(depth-1);
-        }
-    }
-    return n;
-}
-```
-
-# Le nombre de nœuds?
-
-## Comment implémenter la fonction (pseudo-code, 5min, matrix)?
-
-. . .
-
-```C
-entier nombre_nœuds(arbre)
-    si est_feuille(arbre)
-        retourne 1
-    sinon
-        somme = 1
-        pour i de 0 à 3
-            somme += nombre_nœuds(arbre.enfant[i])
-        retourne somme
-```
-
-# Le nombre de nœuds?
-
-## Comment implémenter la fonction en C (3min, matrix)?
-
-. . .
-
-```C
-int size(node *qt) {
-    if (is_leaf(qt)) {
-        return 1;
-    } else {
-        int sum = 1;
-        for (int i = 0; i < 4; ++i) {
-            sum += size(qt->child[i]);
-        }
-        return sum;
-    }
-}
-```
-
-# La profondeur en C?
-
-## Implémentation (5min, matrix)
-
-. . .
-
-\footnotesize
-
-```C
-int max(int x, int y) {
-   return  (x >= y ? x : y);
-}
-int max_depth(int depths[4]) {
-    int m = depths[0];
-    for (int i = 1; i < 4; ++i) {
-        m = max(m, depths[i]);
-    }
-    return m;
-}
-int depth(node *qt) {
-    int depths[] = {0, 0, 0, 0};
-    if (is_leaf(qt)) {
-        return 0;
-    } else {
-        for (int i = 0; i < 4; ++i) {
-            depths[i] = depth(qt->child[i]);
-        }
-        return 1 + max_depth(depths);
-    }
-}
-```
-
-# Fonctions utiles (1/4)
-
-## Comment remplir un arbre depuis une matrice?
-
-```
-   SG=0  |  SD=1
- 21 | 12 | 4 |  4
-  9 |  7 | 4 |  4
------------------
-  1 |  1 | 0 | 31
-  1 |  1 | 3 | 27
-   IG=2  |  ID=3
-```
-
-## Quel arbre cela représente?
-
-. . .
-
-![L'arbre correspondant](figs/quad_img_simple.svg)
-
-# Fonctions utiles (2/4)
-
-* On veut transformer une ligne/colonne en feuille.
-* Comment?
-
-::: columns
-
-:::: {.column width=40%}
-
-## Soit `ligne=2`, `colonne=3`
-
-```
-   SG=0  |  SD=1
- 21 | 12 | 4 |  4
-  9 |  7 | 4 |  4
------------------
-  1 |  1 | 0 | 31
-  1 |  1 | 3 | 27
-   IG=2  |  ID=3
-```
-
-::::
-
-:::: {.column width=70%}
-
-## Trouver un algorithme
-
-![Déterminer un algorithme.](figs/quad_img_simple.svg)
-
-* Quelle feuille pour 31 (`li=2`, `co=3`)?
-* Plus important: quel chemin?
-
-. . .
-
-* `co -> G/D`, `li -> S/I`,
-* `2 * (li / 2) + co / 2 -> 2 * 1 + 1 = 3`
-* `2 * ((li % 2) / 1) + (co % 2) / 1 -> 2 * 0 + 1 = 1`
-* Comment généraliser?
-
-::::
-
-:::
-
-# Fonctions utiles (3/4)
-
-::: columns
-
-:::: {.column width=40%}
-
-## Soit `ligne=2`, `colonne=3`
-
-```
-   SG=0  |  SD=1
- 21 | 12 | 4 |  4
-  9 |  7 | 4 |  4
------------------
-  1 |  1 | 0 | 31
-  1 |  1 | 3 | 27
-   IG=2  |  ID=3
-```
-
-::::
-
-:::: {.column width=70%}
-
-## Trouver un algorithme (prendre plusieurs exemples, 15min, matrix)
-
-![Déterminer un algorithme.](figs/quad_img_simple.svg)
-
-* Comment généraliser?
-
-. . .
-
-```C
-noeud position(li, co, arbre)
-    d = profondeur(arbre);
-    tant_que (d >= 1)
-        index = 2 * ((li % 2^d) / 2^(d-1)) +
-            (col % 2^d) / 2^(d-1)
-        arbre = arbre.enfant[index]
-        d -= 1
-    retourne arbre
-```
-
-
-::::
-
-:::
-
-# Fonctions utiles (4/4)
-
-\footnotesize
-
-## Pseudo-code
-
-```C
-noeud position(li, co, arbre)
-    d = profondeur(arbre);
-    tant_que (d >= 1)
-        index = 2 * ((li % 2^d) / 2^(d-1)) +
-            (col % 2^d) / 2^(d-1)
-        arbre = arbre.enfant[index]
-        d -= 1
-    retourne arbre
-```
-
-## Écrire le code `C` correspondant (5min, matrix)
-
-```C
-
-
-
-
-
-
-
-
-
-
-
-```
-
-# Remplir l'arbre
-
-## A partir d'une matrice (pseudo-code, 5min, matrix)?
-
-. . .
-
-```C
-arbre matrice_à_arbre(matrice)
-    arbre = creer_arbre(profondeur)
-    pour li de 0 à nb_lignes(matrice)
-        pour co de 0 à nb_colonnes(matrice)
-            noeud = position(li, co, arbre)
-            noeud.info = matrice[co][li]
-    retourne arbre
-```
-
-. . .
-
-## A partir d'une matrice (C, 5min, matrix)?
-
-. . .
-
-\footnotesize
-
-```C
-node *matrix_to_qt(int nb_li, int nb_co, int matrix[nb_li][nb_co], int depth)
-{
-    node *qt = qt_create(depth);
-    for (int li = 0; li < nd_li; ++li) {
-        for (int co = 0; co < nd_co; ++co) {
-            node *current = position(li, co, qt);
-            current->info = matrix[li][co];
-        }
-    }
-    return qt;
-}
-```
-
-
-# Remplir la matrice
-
-## A partir de l'arbre (pseudo-code, 3min, matrix)?
-
-. . .
-
-```C
-matrice arbre_à_matrice(arbre)
-    matrice = creer_matrice(nb_lignes(arbre), nb_colonnes(arbre))
-    pour li de 0 à nb_lignes(matrice)
-        pour co de 0 à nb_colonnes(matrice)
-            noeud = position(li, co, arbre)
-            matrice[co][li] = noeud.info
-    retourne matrice
-```
-
-. . .
-
-## A partir de l'arbre (C, 3min, matrix)?
-
-. . .
-
-\footnotesize
-
-```C
-void qt_to_matrix(node *qt, int nb_li, int nb_co, int matrix[nb_li][nb_co])
-    for (int li = 0; li < nd_li; ++li) {
-        for (int co = 0; co < nd_co; ++co) {
-            node *current = position(li, co, qt);
-            matrix[li][co] = current->info;
-        }
-    }
-```
diff --git a/slides/cours_2.md b/slides/cours_2.md
deleted file mode 100644
index 660bf81..0000000
--- a/slides/cours_2.md
+++ /dev/null
@@ -1,317 +0,0 @@
----
-title: "Introduction aux algorithmes"
-date: "2022-09-28"
----
-
-# Rappel (1/2)
-
-* Quel est l'algorithme pour le calcul des nombres 1ers?
-
-. . .
-
-```C
-bool est_premier(int nombre) {
-    int i = 2; // bonne pratique!
-    while (i < nombre) { // penser à bien indenter!
-        if (0 == nombre % i) { // ça rend le code LISIBLE!
-            return false;
-        }
-        i += 1;
-    }
-    return true;
-}
-```
-
-# Rappel (2/2)
-
-* Quelles structures de contrôles avons nous vues?
-
-. . .
-
-* La boucle `while`,
-* La boucle `do ... while`,
-* La boucle `for`,
-* La condition `if ... else if ... else`,
-
-# Exercice: la factorielle
-
-Écrire un programme qui calcule la factorielle d'un nombre
-$$
-N! = 1\cdot 2\cdot ... \cdot (N-1)\cdot N.
-$$
-
-## Par groupe de 3: écrire un pseudo-code
-
-. . .
-
-```python
-entier factorielle(entier n)
-    i = 1
-    fact = 1
-    tant que i <= n
-        fact *= i
-        i += 1
-    retourne fact
-```
-
-# Exercice: la factorielle
-
-\footnotesize
-
-Écrire un programme qui calcule la factorielle d'un nombre
-$$
-N! = 1\cdot 2\cdot ... \cdot (N-1)\cdot N.
-$$
-
-## Par groupe de 3: écrire un code en C
-
-Quand vous avez fini postez le code sur le salon matrix.
-
-. . .
-
-```C
-#include <stdio.h>
-int main() {
-   int nb = 10;
-   int fact = 1;
-   int iter = 2;
-   while (iter <= nb) {
-      fact *= iter;
-      iter++;
-   }
-   printf("La factorielle de %d est %d\n", nb, fact);
-}
-```
-
-. . .
-
-## Comment améliorer ce code? (notez ça sur une feuille)
-
-
-# Exercice: la factorielle en mieux
-
-## Individuellement
-
-1. Écrivez l'algorithme de calcul de deux façon différentes.
-2. Que se passe-t-il si $n>=15$?
-3. Pour celles et ceux qui ont fini pendant que les autres essaient: faites-le 
-   en récursif (sans aide).
-
-. . .
-
-## Postez vos solutions sur **matrix**!
-
-# Exercice: test si un nombre est premier
-
-## Avec tout ce que vous avez appris jusqu'ici:
-
-* Écrivez le code testant si un nombre est premier.
-* Quels sont les ajouts possibles par rapport au code de la semaine passée?
-* Rencontrez-vous des problèmes éventuels de compilation?
-* Voyez-vous une façon de générer des nombres premiers avec votre programme?
-
-. . .
-
-## Implémentez-la et postez votre code sur le salon matrix (10 min).
-
-# Corrigé: enfin pas vraiment mais juste un possible
-
-\footnotesize 
-
-```C
-#include <stdio.h>
-#include <stdlib.h>
-#include <math.h>
-#include <stdbool.h>
-int main() {
-   int nb = 1;
-   printf("Entrez un nombre: ");
-   scanf("%d", &nb);
-   bool premier = true;
-   for (int div = 2; div <= sqrt(nb); div++) {
-      if (nb % div == 0) {
-         premier = false;
-         break;
-      }
-   }
-   if (premier) {
-      printf("Le nombre %d est premier\n", nb);
-   } else {
-      printf("Le nombre %d n'est pas premier\n", nb);
-   }
-   return 0;
-}
-```
-
-# Quelques algorithmes simples
-
-## Voyons quelques algorithmes supplémentaires
-
-- Plus petit commun multiple (PPCM) de deux nombres
-- Autre algorithme de calcul du PPCM de deux nombres
-- Plus grand commun diviseur (PGCD) de deux nombres
-
-# Le calcul du PPCM (1/5)
-
-## Définition
-
-Le plus petit commun multiple (PPCM), `p`, de deux entiers non nuls, `a` et `b`,
-est le plus petit entier strictement positif qui soit multiple de ces deux
-nombres.
-
-Exemples:
-
-```C
-PPCM(3, 4) = 12,
-PPCM(4, 6) = 12,
-PPCM(5, 15) = 15.
-```
-
-. . .
-
-## Mathématiquement
-
-Décomposition en nombres premiers:
-
-$$
-36 = 2^2\cdot 3^2,\quad 90=2\cdot 5\cdot 3^2,
-$$
-On garde tous les premiers à la puissance la plus élevée
-$$
-PPCM(36, 90)=2^2\cdot 3^2\cdot 5=180.
-$$
-
-# Le calcul du PPCM (2/5)
-
-## Exemple d'algorithme
-
-```C
-PPCM(36, 90):
-36  < 90  // 36  + 36
-72  < 90  // 72  + 36
-108 > 90  // 90  + 90
-108 < 180 // 108 + 36
-144 < 180 // 144 + 36
-180 = 180 // The End!
-```
-
-* 5 additions, 5 assignations, et 6 comparaisons.
-
-. . .
-
-## Transcrivez cet exemple en algorithme (groupe de 3), 5min
-
-. . .
-
-## et codez-le!
-
-
-# Le calcul du PPCM (3/5)
-
-## Tentative de correction
-
-```C
-int main() { 
-    int m = 15, n = 12;
-    int mult_m = m, mult_n = n;
-    while (mult_m != mult_n) {
-        if (mult_m > mult_n) {
-            mult_n += n;
-        } else {
-            mult_m += m;
-        }
-    }
-    printf("Le ppcm de %d et %d est %d\n", n, m, mult_m);
-}
-```
-
-. . .
-
-* Combien d'additions / comparaisons au pire?
-
-# Le calcul du PPCM (4/5)
-
-## Réusinage: Comment décrire une fonction qui ferait ce calcul (arguments, sorties)?
-
-. . .
-
-En `C` on pourrait la décrire comme
-
-```C
-int ppcm(int a, int b); // La **signature** de cette fonction
-```
-
-. . .
-
-## Algorithme
-
-Par groupe de 3 (5-10min):
-
-* réfléchissez à un algorithme alternatif donnant le PPCM de deux nombres;
-* écrivez l'algorithme en pseudo-code.
-
-# Le calcul du PPCM (5/5)
-
-## Indication
-
-Si un nombre, `p`, est multiple de `a` et de `b` alors il peut s'écrire `p = a
-* i = b * j`  ou encore `p / a = i` et `p / b = j`.
-
-. . .
-
-## Pseudo-code
-
-```C
-int ppcm(int a, int b) {
-    for (i in [1, b]) {
-        if a * i est divisible par b {
-            return a * i
-        }
-    }
-}
-```
-
-# Le code du PPCM de 2 nombres (1/2)
-
-## Implémentez le pseudo-code et postez le code sur matrix (5min).
-
-. . .
-
-## Un corrigé possible
-
-
-```C
-#include <stdio.h>
-#include <stdlib.h> 
-int main() { 
-   int n = 15, m = 12;
-   int i = 1;
-   while (n * i % m != 0) {
-      i++;
-   }
-   printf("Le ppcm de %d et %d est %d\n", n, m, n*i);
-}
-```
-
-# Le code du PPCM de 2 nombres (2/2)
-
-## Corrigé alternatif
-
-```C
-#include <stdio.h>
-#include <stdlib.h> 
-int main() { 
-   int res = n*m;
-   for (int i = 2; i <= m; i++) {
-     if (n * i % m == 0) {
-        res = n * i;
-        break;
-     }
-   }
-   printf("Le ppcm de %d et %d est %d\n", n, m, res);
-}
-```
-
-
-
-
diff --git a/slides/cours_20.md b/slides/cours_20.md
deleted file mode 100644
index 5fbbc84..0000000
--- a/slides/cours_20.md
+++ /dev/null
@@ -1,795 +0,0 @@
----
-title: "Arbres quarternaires, compression et Barnes-Hut"
-date: "2023-05-05"
----
-
-# Le cours précédent (1/2)
-
-## Questions
-
-* Qu'est-ce qu'un arbre quaternaire?
-
-. . .
-
-* Un arbre où chaque nœud a soit **4 enfants** soit **aucun**.
-* A quoi peut servir un arbre quaternaire?
-
-. . .
-
-* Compression
-
-# Le cours précédent (2/2)
-
-## Questions
-
-
-* Structure de données d'un arbre quaternaire?
-
-. . .
-
-```C
-typedef struct _node {
-    int info;
-    struct _node *child[4];
-} node;
-```
-
-. . .
-
-* Dessin d'un nœud d'arbre quaternaire (avec correspondance `node`)?
-
-. . .
-
-```{.mermaid format=pdf width=400 loc=figs/}
-graph TD;
-    id0(("    "))-->|"child[0]"| id1(("info"));
-    id0-->|"child[1]"| id2(("info"));
-    id0-->|"child[2]"| id3(("info"));
-    id0-->|"child[3]"| id4(("info"));
-```
-
-# Transformations avec un arbre quaternaire
-
-## A faire
-
-* Symétrie axiale (horizontale/verticale).
-* Rotation quart de cercle (gauche/droite).
-* Compression.
-
-# La symétrie verticale
-
-## Que donne la symétrie verticale de
-
-```
-   SG=0  |  SD=1
- 21 | 12 | 4 |  4
-  9 |  7 | 4 |  4
------------------
-  1 |  1 | 0 | 31
-  1 |  1 | 3 | 27
-   IG=2  |  ID=3
-```
-
-. . .
-
-```
-   SG=0  |  SD=1
-  4 |  4 | 12 | 21
-  4 |  4 |  7 |  9
-------------------
- 31 |  0 |  1 |  1
- 27 |  3 |  1 |  1
-   IG=2  |  ID=3
-```
-
-# La symétrie d'axe vertical
-
-## Comment faire sur une matrice (3min, matrix)?
-
-. . .
-
-\footnotesize
-
-```C
-matrice symétrie(matrice)
-    pour i de 0 à nb_colonnes(matrice) / 2
-        pour j de 0 à nb_lignes(matrice)
-            échanger(matrice[i][j], matrice[nb_colonnes(matrice)-1-i][j])
-    retourne matrice
-```
-
-# La symétrie d'axe vertical
-
-## Comment faire sur un arbre?
-
-* Faire un dessin de l'arbre avant/après (5min, matrix)
-
-    ```
-       SG=0  |  SD=1        SG=0  |  SD=1        
-     21 | 12 | 4 |  4       4 | 4 | 12 | 21
-      9 |  7 | 4 |  4       4 | 4 |  7 |  9
-    -----------------  =>  ----------------
-      1 |  1 | 0 | 31      31 | 0 |  1 |  1
-      1 |  1 | 3 | 27      27 | 3 |  1 |  1
-       IG=2  |  ID=3        IG=2  |  ID=3
-    ```
-
-* Écrire le pseudo-code (3min, matrix)
-
-. . .
-
-\footnotesize
-
-```C
-arbre symétrie(arbre)
-    si !est_feuille(arbre)
-        échanger(arbre.enfant[0], arbre.enfant[1])
-        échanger(arbre.enfant[2], arbre.enfant[3])
-        pour i de 0 à 3
-            symétrie(arbre.enfant[i])
-    retourne arbre
-```
-
-# La symétrie d'axe horizontal
-
-* Trivial de faire l'axe horizontal (exercice à la maison)
-
-# Rotation d'un quart de cercle
-
-## Comment faire sur un arbre?
-
-* Faire un dessin de l'arbre avant/après (5min, matrix)
-
-    ```
-       SG=0  |  SD=1        SG=0  |  SD=1   
-     21 | 12 | 4 |  4      4 |  4 | 31 | 27
-      9 |  7 | 4 |  4      4 |  4 |  0 |  3
-    -----------------  => ----------------- 
-      1 |  1 | 0 | 31     12 |  7 |  1 |  1
-      1 |  1 | 3 | 27     21 |  9 |  1 |  1
-       IG=2  |  ID=3        IG=2  |  ID=3
-
-    ```
-
-* Écrire le pseudo-code (3min, matrix)
-
-. . .
-
-```C
-rien rotation_gauche(arbre) 
-    si !est_feuille(arbre)
-        échange_cyclique_gauche(arbre.enfant)
-        pour i de 0 à 3
-            rotation_gauche(arbre.enfant[i])
-```
-
-# Rotation d'un quart de cercle
-
-\footnotesize
-
-## Comment faire sur un arbre?
-
-```
-   SG=0  |  SD=1        SG=0  |  SD=1   
- 21 | 12 | 4 |  4      4 |  4 | 31 | 27
-  9 |  7 | 4 |  4      4 |  4 |  0 |  3
------------------  => ----------------- 
-  1 |  1 | 0 | 31     12 |  7 |  1 |  1
-  1 |  1 | 3 | 27     21 |  9 |  1 |  1
-   IG=2  |  ID=3        IG=2  |  ID=3
-```
-
-* Écrire le vrai (5min, matrix)
-
-. . .
-
-```C
-void rotate(node *qt) {
-    if (!is_leaf(qt)) {
-        node *tmp = qt->child[2];
-        qt->child[2] = qt->child[0];
-        qt->child[0] = qt->child[1];
-        qt->child[1] = qt->child[3];
-        qt->child[3] = tmp;
-        for (int i=0;i < 4; i++) { 
-            rotate(qt->child[i]);
-        }
-    }
-}
-```
-
-# Compression sans perte (1/5)
-
-## Idée générale
-
-* Regrouper les pixels par valeur
-
-```
-   SG=0  |  SD=1        SG=0   |  SD=1   
- 21 | 12 | 4 |  4      21 | 12 |   4
-  9 |  7 | 4 |  4       9 |  7 |  
------------------  => ----------------- 
-  1 |  1 | 0 | 31         1    |  0 | 31
-  1 |  1 | 3 | 27              |  3 | 27
-   IG=2  |  ID=3        IG=2   |  ID=3
-```
-
-* Comment faire?
-
-# Compression sans perte (2/5)
-
-## Que devient l'arbre suivant?
-
-![](figs/quad_img_simple.svg)
-
-. . . 
-
-## Arbre compressé
-
-![](figs/quad_img_simple_comp.svg)
-
-# Compression sans perte (3/5)
-
-* Si un nœud a tous ses enfants égaux:
-    * Donner la valeur au nœud,
-    * Supprimer les enfants.
-* Remonter jusqu'à la racine.
-
-## Écrire le pseudo-code (5min, matrix)
-
-. . .
-
-```C
-rien compression_sans_pertes(arbre)
-    si !est_feuille(arbre)
-        pour i de 0 à 3
-            compression_sans_pertes(arbre.enfant[i])
-        si derniere_branche(arbre)
-            valeur, toutes_égales = valeur_enfants(arbre)
-            si toutes_egales
-                arbre.info = valeur
-                detruire_enfants(arbre)
-```
-
-# Compression sans perte (4/5)
-
-\footnotesize
-
-## Écrire le code C (5min, matrix)
-
-. . .
-
-```C
-void lossless_compression(node *qt) {
-    if (!is_leaf(qt)) {
-        for (int i = 0; i < CHILDREN; i++) {
-            lossless_compression(qt->child[i]);
-        }
-        if (is_last_branch(qt)) {
-            int val = -1;
-            if (last_value(qt, &val)) {
-                qt->info = val;
-                for (int i = 0; i < 4; ++i) {  
-                    free(qt->child[i]);
-                    qt->child[i] = NULL;
-                }
-            }
-        }
-    }
-}
-```
-
-# Compression sans perte (5/5)
-
-\footnotesize
-
-```C
-bool is_last_branch(node *qt) {
-    for (int i = 0; i < 4; ++i) {
-        if (!is_leaf(qt)) {
-            return false;
-        }
-    }
-    return true;
-}
-bool last_value(node *qt, int *val) {
-    int info = qt->child[0];
-    for (int i = 1; i < 4; ++i) {
-        if (info != qt->child[i]) {
-            return false;
-        }
-    }
-    *val = info;
-    return true;
-}
-```
-
-
-# Compression avec perte (1/5)
-
-## Idée générale
-
-* Regrouper les pixels par valeur sous certaines conditions
-
-```
-   SG=0  |  SD=1        SG=0   |  SD=1   
- 21 | 12 | 4 |  3      21 | 12 |    4
-  9 |  7 | 4 |  4       9 |  7 |  
------------------  => ------------------
-  1 |  1 | 0 | 31         1    |  0 | 31
-  2 |  1 | 3 | 27              |  3 | 27
-   IG=2  |  ID=3        IG=2   |  ID=3
-```
-
-* On enlève si l'écart à la moyenne est "petit"?
-
-# Compression avec perte (2/5)
-
-## Que devient l'arbre suivant si l'écart est petit?
-
-![](figs/quad_img_simple_variation.svg)
-
-. . . 
-
-## Arbre compressé
-
-![](figs/quad_img_simple_comp_loss.svg)
-
-# Compression avec perte (3/5)
-
-## Comment mesurer l'écart à la moyenne?
-
-. . .
-
-* Avec l'écart-type
-
-\begin{equation*}
-\mu = \frac{1}{4}\sum_{i=0}^{3} p[i],\quad \sigma = \sqrt{\frac{1}{4}\sum_{i=0}^3 (\mu-p[i])
-^2} = \sqrt{\frac{1}{4}\left(\sum_{i=0}^3p[i]^2\right)-\mu^2}
-\end{equation*}
-
-## Que devient l'algorithme?
-
-. . .
-
-* Si $\sigma<\theta$, $\theta$ est la **tolérance**:
-    * Remplacer la valeur du pixel par la moyenne des enfants.
-    * Remonter les valeurs dans l'arbre.
-
-## Quelle influence de la valeur de $\theta$ sur la compression?
-
-. . .
-
-* Plus $\theta$ est grand, plus l'image sera compressée.
-
-# Compression avec perte (4/5)
-
-## Que devient l'arbre avec $\theta=0.5$?
-
-![L'arbre original.](figs/quad_img_simple_variation.svg)
-
-. . .
-
-![Arbre compressé.](figs/quad_img_simple_comp_avg.svg)
-
-# Compression avec perte (5/5)
-
-## Modifications sur la structure de données?
-
-. . .
-
-* On stocke la moyenne, et la moyenne des carrés.
-
-```C
-struct noeud
-    flottant moyenne, moyenne_carre
-    node enfants[4]
-```
-
-* Comment on calcule `moyenne` et `moyenne_carre` sur chaque nœud (pseudo-code)?
-
-# Calcul de la moyenne
-
-## Pseudo-code (5min, matrix)
-
-. . .
-
-```C
-rien moyenne(arbre) {
-    si !est_feuille(arbre)
-        pour enfant dans arbre.enfants
-            moyenne(enfant)
-        pour enfant dans arbre.enfants
-            arbre.moyenne += enfant.moyenne
-            arbre.moyenne_carre += enfant.moyenne_carre
-        arbre.moyenne /= 4
-        arbre.moyenne_carre /= 4
-```
-
-# La compression avec pertes
-
-\footnotesize
-
-## Pseudo-code (5min, matrix)
-
-. . .
-
-```C
-rien compression_avec_pertes(arbre, theta)
-    si !est_feuille(arbre)
-        pour i de 0 à 3
-            compression_avec_pertes(arbre.enfant[i])
-        si derniere_branche(arbre)
-            si racine(arbre.moyenne_carre - arbre.moyenne^2) < theta
-                detruire_enfants(arbre)
-```
-
-## Le code en entier
-
-```C
-arbre = matrice_à_arbre(matrice)
-moyenne(arbre)
-compression_sans_pertes(arbre)
-```
-
-# La dynamique des corps célestes
-
-## Slides très fortement inspirés du cours de J. Latt, Unige
-
-## Simulation du problème à $N$-corps
-
-* Prédiction du mouvement d'un grand nombre de corps célestes.
-* Modélisation:
-    * On se limite aux étoiles;
-    * Chaque étoile est caractérisée par un point (coordonnées) et une masse;
-    * On simule en deux dimensions.
-    * Interactions uniquement par les lois de la gravitation Newtonienne (oui-oui c'est de la **physique**!).
-
-
-# Les équations du mouvement
-
-## Mouvement de la $i$-ème étoile
-
-* Algorithme de Verlet ($t_{n+1}=t_n+\delta t$)
-
-    $$
-   \vec x_i(t_{n+1})= 2\vec x_i(t_n)-\vec x_i(t_{n-1})+\vec a_i(t_n)\delta t^2.
-   $$
-
-## Force de gravitation
-
-* $\vec a_i(t_n)=\vec F_i/m_i$.
-* Sur l'étoile $i$, la force résultante est donnée par
-
-    $$
-    \vec F_i=\sum_{j=1,j\neq i}^N \vec F_{ij}.
-    $$
-    avec
-    $$
-    \vec F_{ij}=\frac{G m_i m_j(\vec x_j-\vec x_i)}{||\vec x_j-\vec x_i||^3}.
-    $$
-
-# Algorithme du problème à $n$-corps
-
-## Pseudo-code: structure de données
-
-```C
-struct étoile
-    flottant m
-    vec x, x_precedent, f
-```
-
-## Pseudo-code: itération temporelle
-
-```C
-rien iteration_temporelle(étoiles, dt)
-    pour étoile_une dans étoiles
-        étoile_une.f = 0
-        pour étoile_deux dans étoiles
-            si (étoile_un != étoile_deux)
-                étoile_une.f += 
-                    force(étoile_une, étoile_deux)
-    pour étoile dans étoiles
-        étoile.x, étoile.x_precedent = 
-            verlet(étoile.x, étoile.x_precedent, 
-                   étoile.f / étoile.m, dt)
-```
-
-# Algorithme du problème à $n$-corps
-
-## Complexité
-
-* Complexité de chacune des parties?
-
-. . .
-
-* $\mathcal{O}(N^2)$, $\mathcal{O}(N)$.
-
-## En temps CPU pour **une itération**
-
-\footnotesize
-
-* Si temps pour $N=1$ on calcule en $1\mu s$:
-
-+--------+-------+-------+-----------+
-|     N  |  N^2  | t [s] | t [réel]  |
-+--------+-------+-------+-----------+
-|    10  |  10^2 | 1e-4  |           |
-+--------+-------+-------+-----------+
-|  10^4  |  10^8 | 1e+2  | ~1min     |
-+--------+-------+-------+-----------+
-|  10^6  | 10^12 | 1e+6  | ~11j      |
-+--------+-------+-------+-----------+
-|  10^9  | 10^18 | 1e+12 | ~30k ans  |
-+--------+-------+-------+-----------+
-|  10^11 | 10^22 | 1e+16 | ~300M ans |
-+--------+-------+-------+-----------+
-
-* Typiquement il y a des milliers-millions d'itérations.
-* Il y a $10^{11}$ étoiles dans la galaxie.
-* Houston we have a problem.
-
-# Question
-
-## Comment faire mieux, des idées?
-
-. . .
-
-* Si un groupe d'étoiles est suffisamment loin, on le modélise comme un corps unique situé en son centre de masse.
-* Exemple: Si on simule plusieurs galaxies, on considère chaque galaxie comme un corps unique!
-* Un arbre quaternaire est une structure parfaite pour regrouper les étoiles.
-
-# Le cas à 10 corps
-
-::: columns
-
-:::: {.column width=50%}
-
-## Illustration: le cas à 10 corps
-
-![](figs/nbody_bare.png){width=60%}
-
-::::
-
-:::: {.column width=50%}
-
-## Problématique
-
-* On veut calculer la force sur $1$.
-
-::::
-
-:::
-
-. . .
-
-
-::: columns
-
-:::: {.column width=50%}
-
-## Illustration: le cas à 10 corps
-
-![](figs/nbody_n2.png){width=60%}
-
-
-::::
-
-:::: {.column width=50%}
-
-## Résultat
-
-* Calcul et somme des forces venant des $9$ autre corps.
-
-::::
-
-:::
-
-# Le cas à 10 corps
-
-::: columns
-
-:::: {.column width=50%}
-
-## Réduction d'un groupe à un seul corps
-
-![](figs/nbody_group.png){width=100%}
-
-::::
-
-:::: {.column width=50%}
-
-## Idée
-
-* On accélère le calcul en traitant un groupe comme un seul corps.
-* Fonctionne uniquement si le groupe est assez loin.
-* Autrement l'approximation est trop grossière.
-
-::::
-
-:::
-
-# Solution: l'arbre quaternaire
-
-## Corps célestes - arbre
-
-![](figs/nbody_qt_withtree.png)
-
-* On omet les nœuds vides pour éviter la surcharge.
-* La numérotation est:
-    * 0: ID
-    * 1: SD
-    * 2: IG
-    * 3: SG
-
-# Exemple d'insertion
-
-::: columns
-
-:::: {.column width=50%}
-
-## Insertion corps 1
-
-![](figs/corps1.png){width=100%}
-
-::::
-
-:::: {.column width=50%}
-
-## Arbre, niveau 1
-
-![](figs/arbre1.png){width=100%}
-
-* Quadrant ID.
-* La feuille est vide, on insère.
-
-::::
-
-:::
-
-# Exemple d'insertion
-
-::: columns
-
-:::: {.column width=50%}
-
-## Insertion corps 2
-
-![](figs/corps2.png){width=100%}
-
-::::
-
-:::: {.column width=50%}
-
-## Arbre, niveau 1
-
-![](figs/arbre2.png){width=100%}
-
-* Quadrant SD.
-* La feuille est vide, on insère.
-
-::::
-
-:::
-
-# Exemple d'insertion
-
-::: columns
-
-:::: {.column width=50%}
-
-## Insertion corps 3 (1/N)
-
-![](figs/corps3_1.png){width=100%}
-
-::::
-
-:::: {.column width=50%}
-
-## Arbre, niveau 1
-
-![](figs/arbre3_1.png){width=100%}
-
-* Quadrant SD.
-* La feuille est prise par 2.
-
-::::
-
-:::
-
-# Exemple d'insertion
-
-::: columns
-
-:::: {.column width=50%}
-
-## Insertion corps 3 (2/N)
-
-![](figs/corps3_2.png){width=100%}
-
-::::
-
-:::: {.column width=50%}
-
-## Arbre, niveau 2
-
-![](figs/arbre3_2.png){width=100%}
-
-* On crée un nouveau nœud.
-* Deux corps dans le nœud ID.
-* On crée un nouveau nœud.
-
-::::
-
-:::
-
-# Exemple d'insertion
-
-::: columns
-
-:::: {.column width=50%}
-
-## Insertion corps 3 (3/N)
-
-![](figs/corps3_3.png){width=100%}
-
-::::
-
-:::: {.column width=50%}
-
-## Arbre, niveau 3
-
-![](figs/arbre3_3.png){width=100%}
-
-* 2 va dans ID.
-* 3 va dans SG.
-* C'est des feuilles vides, tout va bien.
-
-::::
-
-:::
-
-# Exemple d'insertion
-
-::: columns
-
-:::: {.column width=50%}
-
-## Que fait-on avec les nœuds intérieurs?
-
-* On les utilise pour:
-    * stocker la masse totale;
-    * stocker le centre de masse.
-
-\begin{align}
-m&=m_2+m_3,\\
-\vec x &= \frac{m_2\vec x_2+m_3\vec x_3}{m}.
-\end{align}
-
-## Chaque feuille contient **une étoile**
-
-::::
-
-:::: {.column width=50%}
-
-## Arbre
-
-![](figs/arbre3_3.png){width=100%}
-
-::::
-
-:::
-
-# Résumé
-
-* Insertion du corps `c` dans le nœud `n` en partant de la racine.
-* Si le nœud `n`
-    * ne contient pas de corps, on y dépose `c`,
-    * est interne, on met à jour masse et centre de masse. `c` est inséré récursivement dans le bon quadrant.
-    * est externe, on subdivise `n`, on met à jour la masse et centre de masse, on insère récursivement les deux nœuds dans les quadrants appropriés.
-
-## Remarque
-
-* Il faut stocker les coordonnées des quadrants.
-* Un nœud a un comportement différent s'il est interne ou externe.
-
diff --git a/slides/cours_21.md b/slides/cours_21.md
deleted file mode 100644
index 0b06c90..0000000
--- a/slides/cours_21.md
+++ /dev/null
@@ -1,731 +0,0 @@
----
-title: "Barnes-Hut et B-arbres"
-date: "2023-05-12"
----
-
-# Le cours précédent
-
-## A quoi sert l'algorithme de Barnes-Hut?
-
-. . .
-
-* A accélérer la résolution du problème à $n$-corps avec la gravitation,
-* si on peut vivre avec une réduction de précision.
-
-## Sur quelle structure de données se base l'algorithme?
-
-* L'arbre quaternaire.
-
-. . .
-
-## Quelle est l'idée générale?
-
-. . .
-
-* Si un groupe d'étoiles est suffisamment loin, on le modélise comme un corps unique situé en son centre de masse.
-* Exemple: Si on simule plusieurs galaxies, on considère chaque galaxie comme un corps unique!
-* Un arbre quaternaire est une structure parfaite pour regrouper les étoiles.
-
-
-# Le cas à 10 corps
-
-::: columns
-
-:::: {.column width=50%}
-
-## Illustration: le cas à 10 corps
-
-![](figs/nbody_bare.png){width=60%}
-
-::::
-
-:::: {.column width=50%}
-
-## Problématique
-
-* On veut calculer la force sur $1$.
-
-::::
-
-:::
-
-. . .
-
-
-::: columns
-
-:::: {.column width=50%}
-
-## Illustration: le cas à 10 corps
-
-![](figs/nbody_n2.png){width=60%}
-
-
-::::
-
-:::: {.column width=50%}
-
-## Résultat
-
-* Calcul et somme des forces venant des $9$ autre corps.
-
-::::
-
-:::
-
-# Le cas à 10 corps
-
-::: columns
-
-:::: {.column width=50%}
-
-## Réduction d'un groupe à un seul corps
-
-![](figs/nbody_group.png){width=100%}
-
-::::
-
-:::: {.column width=50%}
-
-## Idée
-
-* On accélère le calcul en traitant un groupe comme un seul corps.
-* Fonctionne uniquement si le groupe est assez loin.
-* Autrement l'approximation est trop grossière.
-
-::::
-
-:::
-
-# Solution: l'arbre quaternaire
-
-## Corps célestes - arbre
-
-![](figs/nbody_qt_withtree.png)
-
-* On omet les nœuds vides pour éviter la surcharge.
-* La numérotation est:
-    * 0: ID
-    * 1: SD
-    * 2: IG
-    * 3: SG
-
-# Exemple d'insertion
-
-::: columns
-
-:::: {.column width=50%}
-
-## Insertion corps 1
-
-![](figs/corps1.png){width=100%}
-
-::::
-
-:::: {.column width=50%}
-
-## Arbre, niveau 1
-
-![](figs/arbre1.png){width=100%}
-
-* Quadrant ID.
-* La feuille est vide, on insère.
-
-::::
-
-:::
-
-# Exemple d'insertion
-
-::: columns
-
-:::: {.column width=50%}
-
-## Insertion corps 2
-
-![](figs/corps2.png){width=100%}
-
-::::
-
-:::: {.column width=50%}
-
-## Arbre, niveau 1
-
-![](figs/arbre2.png){width=100%}
-
-* Quadrant SD.
-* La feuille est vide, on insère.
-
-::::
-
-:::
-
-# Exemple d'insertion
-
-::: columns
-
-:::: {.column width=50%}
-
-## Insertion corps 3 (1/N)
-
-![](figs/corps3_1.png){width=100%}
-
-::::
-
-:::: {.column width=50%}
-
-## Arbre, niveau 1
-
-![](figs/arbre3_1.png){width=100%}
-
-* Quadrant SD.
-* La feuille est prise par 2.
-
-::::
-
-:::
-
-# Exemple d'insertion
-
-::: columns
-
-:::: {.column width=50%}
-
-## Insertion corps 3 (2/N)
-
-![](figs/corps3_2.png){width=100%}
-
-::::
-
-:::: {.column width=50%}
-
-## Arbre, niveau 2
-
-![](figs/arbre3_2.png){width=100%}
-
-* On crée un nouveau nœud.
-* Deux corps dans le nœud ID.
-* On crée un nouveau nœud.
-
-::::
-
-:::
-
-# Exemple d'insertion
-
-::: columns
-
-:::: {.column width=50%}
-
-## Insertion corps 3 (3/N)
-
-![](figs/corps3_3.png){width=100%}
-
-::::
-
-:::: {.column width=50%}
-
-## Arbre, niveau 3
-
-![](figs/arbre3_3.png){width=100%}
-
-* 2 va dans ID.
-* 3 va dans SG.
-* C'est des feuilles vides, tout va bien.
-
-::::
-
-:::
-
-# Exemple d'insertion
-
-::: columns
-
-:::: {.column width=50%}
-
-## Que fait-on avec les nœuds intérieurs?
-
-* On les utilise pour:
-    * stocker la masse totale;
-    * stocker le centre de masse.
-
-\begin{align}
-m&=m_2+m_3,\\
-\vec x &= \frac{m_2\vec x_2+m_3\vec x_3}{m}.
-\end{align}
-
-## Chaque feuille contient **une étoile**
-
-::::
-
-:::: {.column width=50%}
-
-## Arbre
-
-![](figs/arbre3_3.png){width=100%}
-
-::::
-
-:::
-
-# Résumé
-
-* Insertion du corps `c` dans le nœud `n` en partant de la racine.
-* Si le nœud `n`
-    * ne contient pas de corps, on y dépose `c`,
-    * est interne, on met à jour masse et centre de masse. `c` est inséré récursivement dans le bon quadrant.
-    * est externe, on subdivise `n`, on met à jour la masse et centre de masse, on insère récursivement les deux nœuds dans les quadrants appropriés.
-
-## Remarque
-
-* Il faut stocker les coordonnées des quadrants.
-* Un nœud a un comportement différent s'il est interne ou externe.
-
-# Algorithme d'insertion
-
-## Structure de données
-
-```C
-struct node
-    etoile e // externe: pour stocker 
-    etoile sup_etoile // interne: pour stocker m, x
-    quadrant q  // coordonnées du quadrant
-    node enfants[4]
-```
-
-## Remarque: 
-
-* On fait une simplification "moche": `sup_etoile` pourrait juste avoir une masse et une position.
-
-# Algorithme d'insertion
-
-\footnotesize
-
-## Algorithme d'insertion, pseudo-code (15min, matrix)
-
-. . .
-
-```C
-rien insertion_etoile(arbre, e)  
-    si (!est_vide(arbre) && dans_le_quadrant(arbre.q, e.x)) {
-        si (est_feuille(arbre))
-            si (!contient_etoile(arbre))
-                arbre.e = e
-            sinon
-                // on crée enfants et arbre.sup_etoile est initialisée
-                subdivision_arbre(arbre, e) 
-                pour enfant dans arbre.enfants
-                    insertion_etoile(enfant, arbre.e)
-                pour enfant dans arbre.enfants
-                    insertion_etoile(enfant, e)
-                destruction(arbre.e)
-        sinon
-            maj_masse_cdm(arbre.sup_etoile, e)
-            pour enfant dans arbre.enfants
-                insertion_etoile(enfant, e)
-```
-
-# Utilisation de l'arbre
-
-* L'arbre est rempli: comment on calcule la force sur le corps 1?
-* Parcours de l'arbre: 
-    * si la distance entre 1 et le centre de masse est suffisante, on utilise la masse totale et centre de masse pour calculer la force.
-    * sinon, on continue le parcours
-
-# Calcul de la force
-
-## Calcul de la force sur `1`
-
-![](figs/force_1.png)
-
-* Le cadrant ID ne contient que `1`, rien à faire.
-
-# Calcul de la force
-
-## Calcul de la force sur `1`
-
-![](figs/force_2.png)
-
-* Le cadrant SG ne contient `5` corps.
-
-# Calcul de la force
-
-## Calcul de la force sur `1`
-
-![](figs/force_3.png)
-
-* La distance entre `1` et le centre de masse de SG est `d`.
-
-# Calcul de la force
-
-## Calcul de la force sur `1`
-
-![](figs/force_4.png)
-
-* La distance entre `1` et le centre de masse de SG est `d`.
-* Est-ce que `d` est assez grand?
-* On va comparer avec la distance `d` avec la taille du quadrant `s`.
-
-# Critère $\theta$
-
-* On compare $d=||\vec x_1-\vec x_{cm}||$ avec $s$ la taille du quadrant.
-* Le domain est assez éloigné si
-
-    $$
-    \frac{s}{d}<\theta,
-    $$
-* $\theta$ est la valeur de seuil.
-* Une valeur typique est $\theta=0.5$, donc la condition devient
-
-    $$
-    d>2s.
-    $$
-
-# Calcul de la force
-
-## Calcul de la force sur `1`
-
-![](figs/force_4.png)
-
-* Ici $d<2s$, domaine rejeté.
-* ON descend dans l'arbre.
-
-# Calcul de la force
-
-## Calcul de la force sur `1`
-
-![](figs/force_5.png)
-
-* `s` est plus petit, mais....
-* Cela ne suffit pas $d<2s$, domaine rejeté.
-
-# Calcul de la force
-
-## Calcul de la force sur `1`
-
-![](figs/force_6.png)
-
-* Les nœuds sont des feuilles, on calcule la force.
-* On ajoute la force qu'ils exercent sur `1`.
-
-# Algorithme pour le calcul de la force
-
-Pour calculer la force sur un corps `c`, on parcourt l'arbre en commençant par la racine:
-
-* Si le nœud `n` est une feuille et n'est pas `c`, on ajoute la force dûe à `n` sur `c`;
-* Sinon si $s/d<\theta$, on traite `n` comme une feuille et on ajoute la force dûe à `n` sur `c`;
-* Sinon on continue sur les enfants récursivement.
-
-
-## Continuons notre exemple précédent!
-
-# Calcul de la force
-
-## Calcul de la force sur `1`
-
-![](figs/force_7.png)
-
-* Il y a deux corps dans le quadrant vert.
-* Quel est le critère pour remplacer les étoiles par leur centre de masse?
-
-. . .
-
-* Et oui! $d>2s$ on peut remplacer les étoiles par leur centre de masse!
-
-# Algorithme du calcul de force
-
-## Écrire le pseudo-code-code du calcul de la force
-
-\footnotesize
-
-```C
-rien maj_force_sur_etoile(arbre, e, theta)
-    si est_vide(arbre)
-        retourne
-
-    si est_feuille(arbre) && contient_etoile(arbre) && dans_le_quadrant(arbre.q, e.x)
-        maj_force(e, arbre.e)
-    sinon si noeud_assez_loin(arbre, e, theta)
-        maj_force(e, arbre.sup_etoile)
-    sinon
-        pour enfant dans enfants
-            maj_force_sur_etoile(enfant, e, theta)
-```
-
-# Les B-arbres
-
-## Problématique
-
-* Grands jeux de données (en 1970).
-* Stockage dans un arbre, mais l'arbre tiens pas en mémoire.
-* Regrouper les sous-arbres en **pages** qui tiennent en mémoire.
-
-## Exemple
-
-* 100 nœuds par page et l'arbre comporte $10^6$ nœuds:
-    * Recherche B-arbre: $\log_{100}(10^6)=3$;
-    * Recherche ABR: $\log_2(10^6)=20$.
-* Si on doit lire depuis le disque: $10\mathrm{ms}$ par recherche+lecture:
-    * $30\mathrm{ms}$ (lecture beaucoup plus rapide que recherche) vs $200\mathrm{ms}=0.2\mathrm{s}$.
-
-## Remarques
-
-* On sait pas ce que veut dire `B`: Bayer, Boeing, Balanced?
-* Variante plus récente B+-arbres.
-
-# Les B-arbres
-
-## Illustration, arbre divisé en pages de 3 nœuds
-
-![Arbre divisé en pages de 3 nœuds](figs/barbres_page3.png)
-
-. . .
-
-## Utilisation
-
-* Bases de données (souvent très grandes donc sur le disque);
-* Système de fichier.
-
-# Les B-arbres
-
-## Avantages
-
-* Arbres moins profonds;
-* Diminue les opération de rééquilibrage;
-* Complexité toujours en $\log(N)$;
-
-. . .
-
-## Définition: B-arbre d'ordre $n$
-
-* Chaque page d'un arbre contient au plus $2\cdot n$ *clés*;
-* Chaque page (excepté la racine) contient au moins $n$ clés;
-* Chaque page qui contient $m$ clés contient soit:
-    * $0$ descendants;
-    * $m+1$ descendants.
-* Toutes les pages terminales apparaissent au même niveau.
-
-# Les B-arbres
-
-## Est-ce un B-arbre?
-
-![B-arbre d'ordre 2.](figs/barbres_exemple.png)
-
-. . .
-
-## Oui!
-
-* Dans chaque nœud les clés sont **triées**.
-* Chaque page contient au plus $n$ nœuds: check;
-* Chaque nœud avec $m$ clés a $m+1$ descendants;
-* Toutes les feuilles apparaissent au même niveau.
-
-# Les B-arbres
-
-## Exemple de recherche: trouver `32`
-
-![B-arbre d'ordre 2.](figs/barbres_exemple.png)
- 
-. . .
-
-* Si `n` plus petit que la 1e clé ou plus grand que la dernière descendre.
-* Sinon parcourir (par bissection ou séquentiellement) jusqu'à trouver ou descendre entre 2 éléments.
-
-# Les B-arbres
-
-## La recherche de la clé `C` algorithme 
-
-0. En partant de la racine.
-1. Si on est dans une feuille:
-    * Si la `C` est dans une page, retourner la page;
-    * Sinon c'est perdu.
-2. Sinon:
-    * Tant que `C > page` passer à la page suivante
-    * Descendre
-
-# Les B-arbres
-
-## Disclaimer
-
-* Inspiration de <https://en.wikipedia.org/wiki/B-tree>
-
-## Exemples d'insertion: `1`
-
-![B-arbre d'ordre 1.](figs/barbres_1.svg)
- 
-. . .
-
-* L'arbre est vide, on insère juste dans la première page.
-
-# Les B-arbres
-
-## Exemples d'insertion: `2`
-
-![B-arbre d'ordre 1. Nombre pages max = 2.](figs/barbres_2.svg)
- 
-. . .
-
-* La première page est pas pleine, on insère dans l'ordre (après 1).
-
-# Les B-arbres
-
-## Exemples d'insertion: `3`
-
-![B-arbre d'ordre 1.](figs/barbres_2.svg){width=50%}
-
-* Comment on insère (1min de réflexion avant de donner une réponse!)?
-
-# Les B-arbres
-
-## Exemples d'insertion: `3`
-
-![B-arbre d'ordre 1. Nombre pages max = 2.](figs/barbres_3.svg){width=50%}
- 
-. . .
-
-* La page est pleine, on crée deux enfants.
-* On choisit, `2`, la médiane de `1, 2, 3` et il est inséré à la racine.
-* `1` descend à gauche, `3` descend à droite.
-
-# Les B-arbres
-
-## Exemples d'insertion: `4`
-
-![B-arbre d'ordre 1.](figs/barbres_3.svg){width=50%}
- 
-* Comment on insère (1min de réflexion avant de donner une réponse!)?
-
-# Les B-arbres
-
-## Exemples d'insertion: `4`
-
-![B-arbre d'ordre 1. Nombre enfants 0 ou 2.](figs/barbres_4.svg){width=50%}
- 
-. . .
-
-* On pourrait insérer à droite de `2`, mais... ça ferait 2 parents pour 2 enfants (mais `m` parents => `m+1` enfants ou `0`);
-* On descend à droite (`4 > 2`);
-* On insère à droite de `3`.
-
-# Les B-arbres
-
-## Exemples d'insertion: `5`
-
-![B-arbre d'ordre 1.](figs/barbres_4.svg){width=50%}
- 
-* Comment on insère (1min de réflexion avant de donner une réponse!)?
-
-# Les B-arbres
-
-## Exemples d'insertion: `5`
-
-![B-arbre d'ordre 1.](figs/barbres_5.svg)
- 
-. . .
-
-* On descend à droite (on peut pas insérer à la racine comme pour `4`);
-* On dépasse la capacité de l'enfant droite;
-* `4`, médiane de `3, 4, 5`, remonte à la racine;
-* On crée un nouveau nœud à droite de `4`;
-* La règle `m => m+1` est ok.
-
-# Les B-arbres
-
-## Exemples d'insertion: `6`
-
-![B-arbre d'ordre 1.](figs/barbres_5.svg){width=50%}
- 
-* Comment on insère (1min de réflexion avant de donner une réponse!)?
-
-# Les B-arbres
-
-## Exemples d'insertion: `6`
-
-![B-arbre d'ordre 1.](figs/barbres_6.svg)
- 
-. . .
-
-* `6 > 4` on descend à droite;
-* `6 > 5` et on a à la place à droite, on insère.
-
-# Les B-arbres
-
-## Exemples d'insertion: `7`
-
-![B-arbre d'ordre 1.](figs/barbres_6.svg){width=50%}
- 
-* Comment on insère (1min de réflexion avant de donner une réponse!)?
-
-# Les B-arbres
-
-## Exemples d'insertion: `7`
-
-![B-arbre d'ordre 1.](figs/barbres_7.svg){width=50%}
- 
-. . .
-
-* `7 > 4` on descend à droite;
-* `7 > 6` mais on a dépassé la capacité;
-* `6` est la médiane de `5, 6, 7`, remonte à la racine;
-* `5` reste à gauche, `7` à droite, mais `6` fait dépasser la capacité de la racine;
-* `4` est la médiane de `2, 4, 6`, `4` remonte, `2` reste à gauche, `6` à droite.
-
-# Les B-arbres
-
-## L'algorithme d'insertion
-
-0. Rechercher la feuille (la page a aucun enfant) où insérer;
-1. Si la page n'est pas pleine insérer dans l'ordre croissant.
-2. Si la page est pleine, on sépare la page en son milieu :
-    1. On trouve la médiane, `M`, de la page;
-    2. On met les éléments `< M` dans la page de gauche de `M` et les `> M` dans la page de droite de `M`;
-    3. `M` est insérée récursivement dans la page parent.
-
-# Les B-arbres
-
-## Exercice: insérer `22, 45, 50` dans l'arbre d'ordre 2 (3min matrix)
-
-![](figs/barbres_ex1.png)
-
-. . .
-
-![](figs/barbres_ex2.png)
-
-
-# Les B-arbres
-
-## Exercice: insérer `5` dans l'arbre d'ordre 2 (3min matrix)
-
-![](figs/barbres_ex2.png)
-
-. . .
-
-![](figs/barbres_ex3.png)
-
-# Les B-arbres
-
-## Exercice: insérer `32, 55, 60` dans l'arbre d'ordre 2 (3min matrix)
-
-![](figs/barbres_ex3.png)
-
-. . .
-
-![](figs/barbres_ex4.png)
-
-# Les B-arbres
-
-## Exercice: insérer `41` dans l'arbre d'ordre 2 (3min matrix)
-
-![](figs/barbres_ex4.png)
-
-. . .
-
-![](figs/barbres_ex5.png)
-
-# Les B-arbres
-
-## Exercice (matrix, 15min)
-
-* Insérer 20, 40, 10, 30, 15, 35, 7, 26, 18, 22, 5, 42, 13, 46, 27, 8, 32, 38, 24, 45, 25, 2, 14, 28, 32, 41,
-* Dans un B-arbre d'ordre 2.
-
diff --git a/slides/cours_22.md b/slides/cours_22.md
deleted file mode 100644
index 3940c6d..0000000
--- a/slides/cours_22.md
+++ /dev/null
@@ -1,351 +0,0 @@
----
-title: "B-arbres"
-date: "2023-05-19"
----
-
-# Rappel: Les B-arbres
-
-## Pourquoi utiliser un B-arbre?
-
-. . .
-
-## À quoi ressemble un B-arbre?
-
-. . .
-
-## Qu'est-ce qu'un B-arbre d'ordre $n$
-
-* Chaque page d'un arbre contient au plus $2\cdot n$ *clés*;
-* Chaque page (excepté la racine) contient au moins $n$ clés;
-* Chaque page qui contient $m$ clés contient soit:
-    * $0$ descendants;
-    * $m+1$ descendants.
-* Toutes les pages terminales apparaissent au même niveau.
-
-
-# Rappel: Les B-arbres
-
-## Quelques propriétés
-
-* Dans chaque nœud les clés sont **triées**.
-* Chaque page contient au plus $n$ nœuds;
-* Chaque nœud avec $m$ clés a $m+1$ descendants;
-* Toutes les feuilles apparaissent au même niveau.
-
-# Les B-arbres
-
-\footnotesize
-
-## Structure de données
-
-* Chaque page a une contrainte de remplissage, par rapport à l'ordre de l'arbre;
-* Un nœud (page) est composé d'un tableau de clés/pointeurs vers les enfants;
-
-```
-P_0 | K_1 | P_1 | K_2 | .. | P_i | K_{i+1} | .. | P_{m-1} | K_m | P_m
-```
-
-* `P_0`, ..., `P_m` pointeurs vers enfants;
-* `K_1`, ..., `K_m` les clés.
-* Il y a `m+1` pointeurs mais `m` clés.
-* Comment faire pour gérer l'insertion?
-
-# Les B-arbres
-
-## Faire un dessin de la structure de données (3min matrix)?
-
-. . .
-
-![Structure d'une page de B-arbre d'ordre 2.](figs/barbres_struct.png)
-
-1. On veut un tableau de `P_i, K_i => struct`;
-2. `K_0` va être en "trop";
-3. Pour simplifier l'insertion dans une page, on ajoute un élément de plus.
-
-# Les B-arbres
-
-## L'insertion cas nœud pas plein, insertion `4`?
-
-![](figs/barbres_insert_easy.svg){width=50%}
-
-. . .
-
-## Solution
-
-![](figs/barbres_insert_easy_after.svg){width=50%}
-
-# Les B-arbres
-
-## L'insertion cas nœud pas plein, insertion `N`
-
-* On décale les éléments plus grand que `N`;
-* On insère `N` dans la place "vide";
-* Si la page n'est pas pleine, on a terminé.
-
-# Les B-arbres
-
-## L'insertion cas nœud plein, insertion `2`?
-
-![](figs/barbres_insert_hard_before.svg){width=50%}
-
-. . .
-
-## Solution
-
-![](figs/barbres_insert_hard_during.svg){width=50%}
-
-# Les B-arbres
-
-## L'insertion cas nœud plein, promotion `3`?
-
-![](figs/barbres_insert_hard_during.svg){width=50%}
-
-. . .
-
-## Solution
-
-![](figs/barbres_insert_hard_after.svg)
-
-# Les B-arbres
-
-## L'insertion cas nœud plein, insertion `N`
-
-* On décale les éléments plus grand que `N`;
-* On insère `N` dans la place "vide";
-* Si la page est pleine:
-    * On trouve la valeur médiane `M` de la page (quel indice?);
-    * On crée une nouvelle page de droite;
-    * On copie les valeur à droite de `M` dans la nouvelle page;
-    * On promeut `M` dans la page du dessus;
-    * On connecte le pointeur de gauche de `M` et de droite de `M` avec l'ancienne et la nouvelle page respectivement.
-
-# Les B-arbres
-
-## Pseudo-code structure de données (3min, matrix)?
-
-. . .
-
-```C
-struct page
-    entier ordre, nb
-    element tab[2*ordre + 2]
-```
-
-```C
-struct element
-    entier clé
-    page pg
-```
-
-# Les B-arbres
-
-\footnotesize
-
-## Les fonctions utilitaires (5min matrix)
-
-```C
-booléen est_feuille(page)     // la page est elle une feuille?
-entier position(page, valeur) // à quelle indice on insère?
-booléen est_dans_page(page, valeur) // la valeur est dans la page
-```
-
-. . .
-
-```C
-booléen est_feuille(page) 
-    retourne (page.tab[0].pg == vide)
-
-entier position(page, valeur)
-    i = 0
-    tant que i < page.nb && val >= page.tab[i+1].clef
-        i += 1
-    retourne i
-
-booléen est_dans_page(page, valeur)
-    i = position(page, valeur)
-    retourne (page.nb > 0 && page.tab[i].val == valeur)
-```
-
-# Les B-arbres
-
-\footnotesize
-
-## Les fonctions utilitaires (5min matrix)
-
-```C
-page nouvelle_page(ordre)  // créer une page
-rien liberer_memoire(page) // libérer tout un arbre!
-```
-. . .
-
-```C
-page nouvelle_page(ordre)
-    page = allouer(page)
-    page.ordre = ordre
-    page.nb = 0
-    page.tab = allouer(2*ordre+2)
-    retourner page
-
-rien liberer_memoire(page)
-    si est_feuille(page)
-        liberer(page.tab)
-        liberer(page)
-    sinon
-        pour fille dans page.tab
-            liberer_memoire(fille)
-        liberer(page.tab)
-        liberer(page)
-```
-
-# Les B-arbres
-
-## Les fonctions (5min matrix)
-
-```C
-page recherche(page, valeur) // retourner la page contenant
-                             // la valeur ou vide 
-```
-
-. . .
-
-```C
-page recherche(page, valeur)
-    si est_dans_page(page, valeur)
-        retourne page
-    sinon si est_feuille(page) 
-        retourne vide
-    sinon
-        recherche(page.tab[position(page, valeur) - 1], valeur)
-```
-
-# Les B-arbres
-
-## Les fonctions
-
-```C
-page inserer_valeur(page, valeur) // insérer une valeur
-```
-
-. . .
-
-```C
-page inserer_valeur(page, valeur)
-    element = nouvel_element(valeur)
-    // ici élément est modifié pour savoir 
-    // s'il faut le remonter
-    inserer_element(page, element) 
-    si element.page != vide && page.nb > 2*page.ordre
-        // si on atteint le sommet!
-        page = ajouter_niveau(page, element) 
-    retourne page
-```
-
-# Les B-arbres
-
-## Les fonctions
-
-```C
-rien inserer_element(page, element) // insérer un element 
-                                    // et voir s'il remonte
-```
-
-. . .
-
-```C
-rien inserer_element(page, element)
-    si est_feuille(page)
-        placer(page, element)
-    sinon
-        sous_page = page.tab[position(page, element.clé) - 1].page
-        inserer_element(sous_page, element)
-        // un element a été promu
-        si element.page != vide
-            placer(page, element)
-```
-
-# Les B-arbres
-
-## Les fonctions (5min matrix)
-
-```C
-rien placer(page, element) // inserer un élément
-```
-
-. . .
-
-```C
-rien placer(page, element)
-    pos = position(page, element.clé)
-    pour i de 2*page.ordre à pos+1
-        page.tab[i+1] = page.tab[i]
-    page.tab[pos+1] = element
-    page.nb += 1
-    si page.nb > 2*page.ordre
-        scinder(page, element)
-```
-
-# Les B-arbres
-
-## Les fonctions (5min matrix)
-
-```C
-rien scinder(page, element) // casser une page et remonter
-```
-
-. . .
-
-```C
-rien scinder(page, element)
-    nouvelle_page = nouvelle_page(page.ordre)
-    nouvelle_page.nb = page.ordre
-    pour i de 0 à ordre inclu
-        nouvelle_page.tab[i] = page.tab[i+ordre+1]
-    element.clé = page.tab[ordre+1].clé
-    element.page = nouvelle_page
-```
-
-# Les B-arbres
-
-## Les fonctions (5min matrix)
-
-```C
-page ajouter_niveau(page, element) // si on remonte à la 
-                                   // racine, on doit créer
-                                   // une nouvelle racine
-```
-
-. . .
-
-```C
-page ajouter_niveau(page, element) 
-    tmp = nouvelle_page(page.ordre)
-    tmp.tab[0].page = page
-    tmp.tab[1].clé = element.clé
-    tmp.tab[1].page = element.page
-    retourne tmp
-```
-
-
-
-
-
-<!-- # Les B-arbres -->
-
-<!-- ## Structure de données en C (3min, matrix) -->
-
-<!-- . . . -->
-
-<!-- ```C -->
-<!-- typedef struct _page { -->
-<!--     int order, nb; -->
-<!--     struct _element *tab; -->
-<!-- } page; -->
-<!-- ``` -->
-
-<!-- ```C -->
-<!-- typedef struct element { -->
-<!--     int key; -->
-<!--     struct _page *pg; -->
-<!-- } element; -->
-<!-- ``` -->
-
diff --git a/slides/cours_23.md b/slides/cours_23.md
deleted file mode 100644
index 60f01e4..0000000
--- a/slides/cours_23.md
+++ /dev/null
@@ -1,1013 +0,0 @@
----
-title: "B-arbres et Graphes"
-date: "2023-05-24"
-patat:
-  eval:
-    tai:
-      command: fish
-      fragment: false
-      replace: true
-    ccc:
-      command: fish
-      fragment: false
-      replace: true
-  images:
-    backend: auto
----
-
-
-# Les B-arbres: suppression
-
-## Cas simplissime
-
-![Suppression de 25.](figs/barbres_ordre2_supp1.svg){width=80%}
-
-. . .
-
-![25 supprimé, on décale juste 27.](figs/barbres_ordre2_supp2.svg){width=80%}
-
-# Les B-arbres: suppression
-
-\footnotesize
-
-## Cas simple
-
-
-![Suppression de 27.](figs/barbres_ordre2_supp2.svg){width=60%}
-
-. . .
-
-* On retire 27, mais....
-    * Chaque page doit avoir au moins 2 éléments.
-    * On doit déplacer des éléments dans une autre feuille! Mais comment?
-
-. . .
-
-![La médiane de la racine descend, fusion de 20 à gauche, et suppression à droite.](figs/barbres_ordre2_supp3.svg){width=60%}
-
-# Les B-arbres: suppression
-
-## Cas moins simple
-
-![Suppression de 5.](figs/barbres_ordre2_supp4.svg){width=60%}
-
-. . .
-
-* Un élément à droite, comment on fait?
-    * Remonter `7`, serait ok si racine, mais... c'est pas forcément.
-    * On redistribue les feuilles.
-
-. . .
-
-![Descente de `3`, remontée médiane des feuilles `2`.](figs/barbres_ordre2_supp5.svg){width=60%}
-
-# Les B-arbres: suppression
-
-\footnotesize
-
-## Cas ultra moins simple
-
-![Suppression de 3.](figs/barbres_ordre2_supp6.svg){width=60%}
-
-. . .
-
-* `7` seul:
-    * Fusionner les feuilles et redistribuer, comment?
-
-. . .
-
-![Descendre `-1`, déplacer `7` à gauche, et décaler les éléments de droite au milieu.](figs/barbres_ordre2_supp7.svg){width=60%}
-
-# Les B-arbres: suppression
-
-## Cas ultra moins simple
-
-![On a pas fini...](figs/barbres_ordre2_supp7.svg){width=60%}
-
-. . .
-
-* `8` est seul, c'est plus un B-arbre :
-    * Fusionner le niveau 2 et redistribuer, comment?
-
-. . .
-
-![Fusionner `8`, `17`, `22` et descendre `12`.](figs/barbres_ordre2_supp8.svg){width=40%}
-
-. . .
-
-* La profondeur a diminué de 1.
-
-# Les B-arbres: suppression
-
-## Algorithme pour les feuilles!
-
-* Si la clé est supprimée d'une feuille:
-    * Si on a toujours `n` (ordre de l'arbre) clés dans la feuille on décale simplement les clés.
-    * Sinon on combine (récursivement) avec le nœud voisin et on descend la clé médiane.
-
-# Les B-arbres: suppression
-
-## Cas non-feuille!
-
-![Suppression de 8.](figs/barbres_ordre2_supp9.svg){width=60%}
-
-. . .
-
-* On sait comment effacer une valeur d'une feuille, donc?
-
-. . .
-
-![Échanger le `8` avec le plus grand du sous-arbre de gauche.](figs/barbres_ordre2_supp10.svg){width=60%}
-
-* Ensuite?
-
-# Les B-arbres: suppression
-
-## Cas non-feuille!
-
-![Suppression de 8.](figs/barbres_ordre2_supp10.svg){width=60%}
-
-. . .
-
-* On sait comment effacer une valeur d'une feuille!
-
-. . .
-
-![Yaka enlever le 8 de la feuille comme avant!](figs/barbres_ordre2_supp11.svg){width=60%}
-
-# Les B-arbres: suppression
-
-## Algorithme pour les non-feuilles!
-
-* Si la clé est supprimée d'une page qui n'est pas une feuille:
-    * On échange la valeur avec la valeur de droite de la page de gauche
-    * On supprime comme pour une feuille!
-
-## Et maintenant des exercices par millions!
-
-# Les graphes! Historique
-
-**Un mini-peu d'histoire...**
-
-## L. Euler et les 7 ponts de Koenigsberg:
-
-* Existe-t-il une promenade sympa, passant **une seule fois** par les 7 ponts et revenant au point de départ?
-
-![Les ponts c'est beau. Source: Wikipédia, <https://bit.ly/37h0yOG>](figs/Konigsberg_bridges.png){width=50%}
-
-. . .
-
-* Réponse: ben non!
-
-# Utilisation quotidienne
-
-## Réseau social
-
-![Source, Wikipedia: <https://bit.ly/3kG6cgo>](figs/Social_Network.svg){width=40%}
-
-* Chaque sommet est un individu.
-* Chaque trait une relation d'amitié.
-* Miam, Miam, Facebook.
-
-# Utilisation quotidienne
-
-## Moteurs de recherche
-
-![Source, Wikipedia: <https://bit.ly/3kG6cgo>](figs/PageRanks-Example.svg){width=40%}
-
-* Sommet est un site.
-* Liens sortants;
-* Liens entrants;
-* Notion d'importance d'un site: combien de liens entrants, pondérés par l'importance du site.
-* Miam, Miam, Google (PageRank).
-
-# Introduction
-
-## Définition, plus ou moins
-
-* Un graphe est un ensemble de sommets, reliés par des lignes ou des flèches.
-
-![Deux exemples de graphes.](figs/ex_graphes.png)
-
-* Des sommets (numérotés 1 à 6);
-* Connectés ou pas par des traits ou des flèches!
-
-# Généralités
-
-## Définitions
-
-* Un **graphe** $G(V, E)$ est constitué
-    * $V$: un ensemble de sommets;
-    * $E$: un ensemble d'arêtes.
-* Une **arête** relie une **paire** de sommets de $V$.
-
-## Remarques
-
-* Il y a **au plus** une arête $E$ par paire de sommets de $V$.
-* La **complexité** d'un algorithme dans un graphe se mesure en terme de $|E|$ et $|V|$, le nombre d'éléments de $E$ et $V$ respectivement.
-
-# Généralités
-
-## Notations
-
-* Une arête d'un graphe **non-orienté** est représentée par une paire **non-ordonnée** $(u,v)=(v,u)$, avec $u,v\in V$.
-* Les arêtes ne sont pas orientées dans un graphe non-orienté (elles sont bi-directionnelles, peuvent être parcourues dans n'importe quel ordre).
-
-## Exemple
-
-
-::: columns
-
-:::: column
-
-![Un graphe non-orienté.](figs/ex_graphe_non_oriente.svg)
-
-
-::::
-
-:::: column
-
-## Que valent $V$, $|V|$, $E$, et $|E|$?
-
-. . .
-
-\begin{align*}
-V&=\{1, 2, 3, 4\},\\
-|V|&=4,\\
-E&=\{(1,2),(2,3),(2,4),(4,1)\},\\
-|E|&=4.
-\end{align*}
-
-::::
-
-:::
-
-# Généralités
-
-## Notations
-
-* Une arête d'un graphe **orienté** est représentée par une paire **ordonnée** $(u,v)\neq(v,u)$, avec $u,v\in V$.
-* Les arêtes sont orientées dans un graphe orienté (étonnant non?).
-
-## Exemple
-
-
-::: columns
-
-:::: column
-
-![Un graphe orienté.](figs/ex_graphe_oriente.svg)
-
-
-::::
-
-:::: column
-
-## Que valent $V$, $|V|$, $E$, et $|E|$?
-
-. . .
-
-\begin{align*}
-V&=\{1, 2, 3, 4\},\\
-|V|&=4,\\
-E&=\{(1,2),(2,3),(2,4),(4,1),(4,2)\},\\
-|E|&=5.
-\end{align*}
-
-::::
-
-:::
-
-# Généralités
-
-## Définition
-
-* Le somme $v$ est **adjacent** au sommet $u$, si et seulement si $(u,v)\in E$;
-* Si un graphe non-orienté contient une arête $(u,v)$, $v$ est adjacent à $u$ et $u$ et adjacent à $v$.
-
-## Exemple
-
-::: columns
-
-:::: column
-
-![Sommet $a$  adjacent à $c$, $c$ adjacent à $a$.](figs/ex_adj_non_or.svg){width=80%}
-
-::::
-
-:::: column
-
-![Sommet $a$  adjacent à $c$.](figs/ex_adj_or.svg){width=80%}
-
-::::
-
-:::
-
-# Généralités
-
-## Définition
-
-* Un **graphe pondéré** ou **valué** est un graphe dont chaque arête a un
-  poids associé, habituellement donné par une fonction de pondération $w:E\rightarrow\mathbb{R}$.
-
-## Exemples
-
-![Graphe pondéré orienté (gauche) et non-orienté (droite).](figs/ex_graph_pond.pdf){width=80%}
-
-
-# Généralités
-
-## Définition
-
-* Dans un graphe $G(V,E)$, une **chaîne** reliant un sommet $u$ à un sommet $v$ est une suite d'arêtes entre les sommets, $w_0$, $w_1$, ..., $w_k$, telles que 
-$$
-(w_i, w_{i+1})\in E,\quad u=w_0,\quad v=w_k,\quad \mbox{pour }0\leq i< k,
-$$
-avec $k$ la longueur de la chaîne (le nombre d'arêtes du chemin).
-
-## Exemples
-
-![Illustration d'une chaîne, ou pas chaîne dans un graphe.](figs/ex_graphe_chaine.pdf){width=80%}
-
-# Généralités
-
-## Définition
-
-* Une **chaîne élémentaire** est une chaîne dont tous les sommets sont distincts, sauf les extrémités qui peuvent être égales
-
-## Exemples
-
-![Illustration d'une chaîne élémentaire.](figs/ex_graphe_chaine_elem.pdf){width=80%}
-
-# Généralités
-
-## Définition
-
-* Une **boucle** est une arête $(v,v)$ d'un sommet vers lui-même.
-
-## Exemples
-
-![Illustration d'une boucle.](figs/ex_graphe_boucle.pdf){width=40%}
-
-# Généralités
-
-## Définition
-
-* Un graphe non-orienté est dit **connexe**, s'il existe un chemin reliant n'importe quelle paire de sommets distincts.
-
-## Exemples
-
-\
-
-::: columns
-
-:::: column
-
-![Graphe connexe. Source, Wikipédia: <https://bit.ly/3yiUzUv>](figs/graphe_connexe.svg){width=80%}
-
-::::
-
-:::: column
-![Graphe non-connexe avec composantes connexes. Source, Wikipédia: <https://bit.ly/3KJB76d>](figs/composantes_connexes.svg){width=60%}
-
-::::
-
-:::
-
-# Généralités
-
-## Définition
-
-* Un graphe orienté est dit **fortement connexe**, s'il existe un chemin reliant n'importe quelle paire de sommets distincts.
-
-## Exemples
-
-\
-
-::: columns
-
-:::: column
-
-![Graphe fortement connexe.](figs/ex_graph_fort_connexe.pdf){width=60%}
-
-::::
-
-:::: column
-
-![Composantes fortement connexes. Source, Wikipédia: <https://bit.ly/3w5PL2l>](figs/composantes_fortement_connexes.svg){width=100%}
-
-::::
-
-:::
-
-# Généralités
-
-## Définition
-
-* Un **cycle** dans un graphe *non-orienté* est une chaîne de longueur $\geq 3$ telle que le 1er sommet de la chaîne est le même que le dernier, et dont les arêtes sont distinctes.
-* Pour un graphe *orienté* on parle de **circuit**.
-* Un graphe sans cycles est dit **acyclique**.
-
-## Exemples
-
-![Illustration de cycles, ou pas.](figs/ex_graphe_cycle.pdf){width=100%}
-
-# Question de la mort
-
-* Qu'est-ce qu'un graphe connexe acyclique?
-
-. . .
-
-* Un arbre!
-
-# Représentations
-
-* La complexité des algorithmes sur les graphes s'expriment en fonction du nombre de sommets $V$, et du nombre d'arêtes $E$:
-    * Si $|E|\sim |V|^2$, on dit que le graphe est **dense**.
-    * Si $|E|\sim |V|$, on dit que le graphe est **peu dense**.
-* Selon qu'on considère des graphes denses ou peu denses, différentes structure de données peuvent être envisagées.
-
-## Question
-
-* Comment peut-on représenter un graphe informatiquement? Des idées (réflexion de quelques minutes)?
-
-. . .
-
-* Matrice/liste d'adjacence.
-
-# Matrice d'adjacence
-
-* Soit le graphe $G(V,E)$, avec $V=\{1, 2, 3, ..., n\}$;
-* On peut représenter un graphe par une **matrice d'adjacence**, $A$, de dimension $n\times n$ définie par
-$$
-A_{ij}=\left\{ \begin{array}{ll}
-         1 & \mbox{si } i,j\in E,\\
-         0 & \mbox{sinon}.
-         \end{array} \right.
-$$
-
-
-::: columns
-
-:::: column
-
-## Exemple
-
-```{.mermaid format=pdf width=400 loc=figs/}
-graph LR;
-    1---2;
-    1---4;
-    2---5;
-    4---5;
-    5---3;
-```
-
-::::
-
-:::: column
-
-\footnotesize
-
-## Quelle matrice d'adjacence? 
-
-. . .
-
-```
-   || 1 | 2 | 3 | 4 | 5
-===||===|===|===|===|===
- 1 || 0 | 1 | 0 | 1 | 0
----||---|---|---|---|---
- 2 || 1 | 0 | 0 | 0 | 1
----||---|---|---|---|---
- 3 || 0 | 0 | 0 | 0 | 1
----||---|---|---|---|---
- 4 || 1 | 0 | 0 | 0 | 1
----||---|---|---|---|---
- 5 || 0 | 1 | 1 | 1 | 0
-```
-
-::::
-
-:::
-
-# Matrice d'adjacence
-
-## Remarques
-
-* Zéro sur la diagonale.
-* La matrice d'un graphe non-orienté est symétrique
-
-$$
-A_{ij}=A_{ji}, \forall i,j\in[1,n]
-$$.
-
-::: columns
-
-:::: column
-
-```{.mermaid format=pdf width=400 loc=figs/}
-graph LR;
-    1---2;
-    1---4;
-    2---5;
-    4---5;
-    5---3;
-```
-
-::::
-
-:::: column
-
-\footnotesize
-
-```
-   || 1 | 2 | 3 | 4 | 5
-===||===|===|===|===|===
- 1 || 0 | 1 | 0 | 1 | 0
----||---|---|---|---|---
- 2 || 1 | 0 | 0 | 0 | 1
----||---|---|---|---|---
- 3 || 0 | 0 | 0 | 0 | 1
----||---|---|---|---|---
- 4 || 1 | 0 | 0 | 0 | 1
----||---|---|---|---|---
- 5 || 0 | 1 | 1 | 1 | 0
-```
-
-::::
-
-:::
-
-# Matrice d'adjacence
-
-* Pour un graphe orienté (digraphe)
-
-::: columns
-
-:::: column
-
-## Exemple
-
-```{.mermaid format=pdf width=400 loc=figs/}
-graph LR;
-    2-->1;
-    1-->4;
-    2-->5;
-    5-->2;
-    4-->5;
-    5-->3;
-```
-
-::::
-
-:::: column
-
-\footnotesize
-
-## Quelle matrice d'adjacence? 
-
-. . .
-
-```
-   || 1 | 2 | 3 | 4 | 5
-===||===|===|===|===|===
- 1 || 0 | 0 | 0 | 1 | 0
----||---|---|---|---|---
- 2 || 1 | 0 | 0 | 0 | 1
----||---|---|---|---|---
- 3 || 0 | 0 | 0 | 0 | 0
----||---|---|---|---|---
- 4 || 0 | 0 | 0 | 0 | 1
----||---|---|---|---|---
- 5 || 0 | 1 | 1 | 0 | 0
-```
-
-::::
-
-:::
-
-* La matrice d'adjacence n'est plus forcément symétrique
-$$
-A_{ij}\neq A_{ji}.
-$$
-
-# Stockage
-
-* Quel est l'espace nécessaire pour stocker une matrice d'adjacence pour un graphe orienté?
-
-. . .
-
-* $\mathcal{O}(|V|^2)$.
-* Quel est l'espace nécessaire pour stocker une matrice d'adjacence pour un graphe non-orienté?
-
-. . .
-
-* $\mathcal{O}(|V|-1)|V|/2$.
-
-# Considérations d'efficacité
-
-* Dans quel type de graphes la matrice d'adjacence est utile?
-
-. . .
-
-* Dans les graphes denses.
-* Pourquoi?
-
-. . .
-
-* Dans les graphes peu denses, la matrice d'adjacence est essentiellement composée de `0`.
-
-## Remarque
-
-* Dans la majorité des cas, les grands graphes sont peu denses.
-* Comment représenter un graphe autrement?
-
-# La liste d'adjacence (non-orienté)
-
-* Pour chaque sommet $v\in V$, stocker les sommets adjacents à $v$-
-* Quelle structure de données pour la liste d'adjacence?
-
-. . .
-
-* Tableau de liste chaînée, vecteur (tableau dynamique), etc.
-
-
-::: columns
-
-:::: column
-
-## Exemple
-
-![Un graphe non-orienté.](figs/ex_graph_adj.pdf){width=80%}
-
-::::
-
-:::: column
-
-
-## Quelle liste d'adjacence? 
-
-. . .
-
-![La liste d'adjacence.](figs/ex_graph_list_adj.pdf)
-
-
-::::
-
-:::
-
-# La liste d'adjacence (orienté)
-
-
-::: columns
-
-:::: column
-
-## Quelle liste d'adjacence pour...
-
-* Matrix (2min)
-
-```{.mermaid format=pdf width=400 loc=figs/}
-graph LR;
-    0-->1;
-    0-->2;
-    1-->2;
-    3-->0;
-    3-->1;
-    3-->2;
-```
-
-::::
-
-:::: column
-
-```
-
-
-
-
-
-
-
-
-
-
-
-```
-
-
-::::
-
-:::
-
-# Complexité
-
-## Stockage
-
-* Quelle espace est nécessaire pour stocker une liste d'adjacence (en fonction de $|E|$ et $|V|$)?
-
-. . .
-
-$$
-\mathcal{O}(|E|)
-$$
-
-* Pour les graphes *non-orientés*: $\mathcal{O}(2|E|)$.
-* Pour les graphes *orientés*: $\mathcal{O}(|E|)$.
-
-## Définition
-
-* Le **degré** d'un sommet $v$, est le nombre d'arêtes incidentes du sommet (pour les graphes orientés on a un degré entrant ou sortant).
-* Comment on retrouve le degré de chaque sommet avec la liste d'adjacence?
-
-. . .
-
-* C'est la longueur de la liste chaînée.
-
-
-# Parcours
-
-* Beaucoup d'applications nécessitent de parcourir des graphes:
-    * Trouver un chemin d'un sommet à un autre;
-    * Trouver si le graphe est connexe;
-* Il existe *deux* parcours principaux:
-    * en largeur (Breadth-First Search);
-    * en profondeur (Depth-First Search).
-* Ces parcours créent *un arbre* au fil de l'exploration (si le graphe est non-connexe cela crée une *forêt*, un ensemble d'arbres).
-
-# Illustration: parcours en largeur
-
-![Le parcours en largeur.](figs/parcours_larg.pdf){width=80%}
-
-# Exemple
-
-## Étape par étape (blanc non-visité)
-
-![Initialisation.](figs/parcours_larg_0.pdf){width=50%}
-
-## Étape par étape (gris visité)
-
-![On commence en `x`.](figs/parcours_larg_1.pdf){width=50%}
-
-# Exemple
-
-## Étape par étape
-
-![On commence en `x`.](figs/parcours_larg_1.pdf){width=50%}
-
-## Étape par étape (vert à visiter)
-
-![Vister `w`, `t`, `y`.](figs/parcours_larg_2.pdf){width=50%}
-
-# Exemple
-
-## Étape par étape
-
-![Vister `w`, `t`, `y`.](figs/parcours_larg_2.pdf){width=50%}
-
-## Étape par étape
-
-![`w`, `t`, `y` visités. `u`, `s` à visiter.](figs/parcours_larg_3.pdf){width=50%}
-
-# Exemple
-
-## Étape par étape
-
-![`w`, `t`, `y` visités. `u`, `s` à visiter.](figs/parcours_larg_3.pdf){width=50%}
-
-## Étape par étape
-
-![`u`, `s`, visités. `r` à visiter.](figs/parcours_larg_4.pdf){width=50%}
-
-# Exemple
-
-## Étape par étape
-
-![`u`, `s`, visités. `r` à visiter.](figs/parcours_larg_4.pdf){width=50%}
-
-## Étape par étape
-
-![`r` visité. `v` à visiter.](figs/parcours_larg_5.pdf){width=50%}
-
-# Exemple
-
-## Étape par étape
-
-![`r` visité. `v` à visiter.](figs/parcours_larg_5.pdf){width=50%}
-
-## Étape par étape
-
-![The end. Plus rien à visiter!](figs/parcours_larg_6.pdf){width=50%}
-
-# En faisant ce parcours...
-
-
-::: columns
-
-:::: column
-
-## Du parcours de l'arbre
-
-![](figs/parcours_larg_6.pdf){width=100%}
-
-::::
-
-:::: column
-
-## Quel arbre est créé par le parcours (2min)?
-
-. . .
-
-```{.mermaid format=pdf width=400 loc=figs/}
-graph LR;
-    0[x]-->1[w];
-    0-->2[t];
-    0-->3[y];
-    2-->9[u];
-    1-->4[s];
-    4-->5[r];
-    5-->6[v];
-```
-
-::::
-
-:::
-
-## Remarques
-
-* Le parcours dépend du point de départ dans le graphe.
-* L'arbre sera différent en fonction du noeud de départ, et de l'ordre de parcours des voisins d'un noeud.
-
-# Le parcours en largeur
-
-## L'algorithme, idée générale (3min, matrix)?
-
-. . .
-
-```C
-v = un sommet du graphe
-i = 1
-pour sommet dans graphe et sommet non-visité
-    visiter(v, sommet, i) // marquer sommet à distance i visité 
-    i += 1
-```
-
-## Remarque
-
-* `i` est la distance de plus cours chemin entre `v` et les sommets en cours de visite.
-
-
-# Le parcours en largeur
-
-## L'algorithme, pseudo-code (3min, matrix)?
-
-* Comment garder la trace de la distance?
-
-. . .
-
-* Utilisation d'une **file**
-
-. . .
-
-```C
-initialiser(graphe) // tous sommets sont non-visités
-file = visiter(sommet, vide) // sommet est un sommet du graphe au hasard
-tant que !est_vide(file)
-    v = défiler(file)
-    file = visiter(v, file)
-```
-
-## Que fait visiter?
-
-```
-file visiter(sommet, file)
-    sommet = visité
-    pour w = chaque arête de sommet
-        si w != visité
-            file = enfiler(file, w)
-    retourne file
-```
-
-# Exercice (5min)
-
-## Appliquer l'algorithme sur le graphe
-
-![](figs/parcours_larg_0.pdf){width=50%}
-
-* En partant de `v`, `s`, ou `u` (par colonne de classe).
-* Bien mettre à chaque étape l'état de la file.
-
-# Complexité du parcours en largeur
-
-## Étape 1
-
-* Extraire un sommet de la file;
-
-## Étape 2
-
-* Traîter tous les sommets adjacents.
-
-## Quelle est la complexité?
-
-. . .
-
-* Étape 1: $\mathcal{O}(|V|)$,
-* Étape 2: $\mathcal{O}(2|E|)$,
-* Total: $\mathcal{O}(|V| + |2|E|)$.
-
-# Exercice
-
-* Établir la liste d'adjacence et appliquer l'algorithme de parcours en largeur au graphe
-
-```{.mermaid format=pdf width=400 loc=figs/}
-graph LR;
-    1---2;
-    1---3;
-    1---4;
-    2---3;
-    2---6;
-    3---6;
-    3---4;
-    3---5;
-    4---5;
-```
-
-
-# Illustration: parcours en profondeur
-
-![Le parcours en profondeur. À quel parcours d'arbre cela ressemble-t-il?](figs/parcours_prof.pdf){width=80%}
-
-# Parcours en profondeur
-
-## Idée générale
-
-* Initialiser les sommets comme non-lus
-* Visiter un sommet
-* Pour chaque sommet visité, on visite un sommet adjacent s'il est pas encore visité récursivement.
-
-## Remarque
-
-* La récursivité est équivalent à l'utilisation d'une **pile**.
-
-# Parcours en profondeur
-
-## Pseudo-code (5min)
-
-. . .
-
-```C
-initialiser(graphe) // tous sommets sont non-visités
-pile = visiter(sommet, vide) // sommet est un sommet du graphe au hasard
-tant que !est_vide(pile)
-    v = dépiler(pile)
-    pile = visiter(v, pile)
-```
-
-## Que fait visiter?
-
-. . .
-
-```C
-pile visiter(sommet, pile)
-    sommet = visité
-    pour w = chaque arête de sommet
-        si w != visité
-            pile = empiler(pile, w)
-    retourne pile
-```
-
-
-# Exercice
-
-* Établir la liste d'adjacence et appliquer l'algorithme de parcours en profondeur au graphe
-
-```{.mermaid format=pdf width=400 loc=figs/}
-graph LR;
-    1---2;
-    1---3;
-    1---4;
-    2---3;
-    2---6;
-    3---6;
-    3---4;
-    3---5;
-    4---5;
-```
-
-# Interprétation des parcours
-
-* Un graphe vu comme espace d'états (sommet: état, arête: action);
-    * Labyrinthe;
-    * Arbre des coups d'un jeu.
-
-. . .
-
-* BFS (Breadth-First) ou DFS (Depth-First) parcourent l'espace des états à la recherche du meilleur mouvement.
-    * Les deux parcourent *tout* l'espace;
-    * Mais si l'arbre est grand, l'espace est gigantesque!
-
-. . .
-
-* Quand on a un temps limité
-    * BFS explore beaucoup de coups dans un futur proche;
-    * DFS explore peu de coups dans un futur lointain.
diff --git a/slides/cours_24.md b/slides/cours_24.md
deleted file mode 100644
index 7fa2fa9..0000000
--- a/slides/cours_24.md
+++ /dev/null
@@ -1,709 +0,0 @@
----
-title: "Graphes - Plus court chemin"
-date: "2023-06-02"
----
-
-# Rappel du dernier cours
-
-* Qu'est-ce qu'un graphe? Un graphe orienté? Un graphe pondéré?
-
-. . .
-
-* Ensemble de sommets et arêtes, avec une direction, possédant une pondération.
-* Comment représenter un graphe informatiquement?
-
-. . .
-
-* Liste ou matrice d'adjacence.
-* Quel est le parcours que nous avons vu?
-
-. . .
-
-* Le parcours en largeur.
-
-# Le parcours en largeur
-
-## Le pseudo-code
-
-* Utilisation d'une **file**
-
-```C
-initialiser(graphe) // tous sommets sont non-visités
-file = visiter(sommet, vide) // sommet est un sommet 
-                             // du graphe
-tant que !est_vide(file)
-    v = defiler(file)
-    file = visiter(v, file)
-
-file visiter(sommet, file)
-    sommet = visité
-    pour w = chaque arête de sommet
-        si w != visité
-            file = enfiler(file, w)
-    retourne file
-```
-
-# Complexité du parcours en largeur
-
-## Étape 1
-
-* Extraire un sommet de la file;
-
-## Étape 2
-
-* Traîter tous les sommets adjacents.
-
-## Quelle est la complexité?
-
-. . .
-
-* Étape 1: $\mathcal{O}(|V|)$,
-* Étape 2: $\mathcal{O}(2|E|)$,
-* Total: $\mathcal{O}(|V| + 2|E|)$.
-
-# Exercice
-
-* Établir la liste d'adjacence et appliquer l'algorithme de parcours en largeur au graphe
-
-```{.mermaid format=pdf width=400 loc=figs/}
-graph LR;
-    1---2;
-    1---3;
-    1---4;
-    2---3;
-    2---6;
-    3---6;
-    3---4;
-    3---5;
-    4---5;
-```
-
-
-# Illustration: parcours en profondeur
-
-![Le parcours en profondeur. À quel parcours d'arbre cela ressemble-t-il?](figs/parcours_prof.pdf){width=80%}
-
-# Parcours en profondeur
-
-## Idée générale
-
-* Initialiser les sommets comme non-lus
-* Visiter un sommet
-* Pour chaque sommet visité, on visite un sommet adjacent s'il est pas encore visité récursivement.
-
-## Remarque
-
-* La récursivité est équivalent à l'utilisation d'une **pile**.
-
-# Parcours en profondeur
-
-## Pseudo-code (5min)
-
-. . .
-
-```C
-initialiser(graphe) // tous sommets sont non-visités
-pile = visiter(sommet, vide) // sommet est un 
-                             // sommet du graphe
-tant que !est_vide(pile)
-    v = dépiler(pile)
-    pile = visiter(v, pile)
-```
-
-## Que fait visiter?
-
-. . .
-
-```C
-pile visiter(sommet, pile)
-    sommet = visité
-    pour w = chaque arête de sommet
-        si w != visité
-            pile = empiler(pile, w)
-    retourne pile
-```
-
-
-# Exercice
-
-* Établir la liste d'adjacence et appliquer l'algorithme de parcours en profondeur au graphe
-
-```{.mermaid format=pdf width=400 loc=figs/}
-graph LR;
-    1---2;
-    1---3;
-    1---4;
-    2---3;
-    2---6;
-    3---6;
-    3---4;
-    3---5;
-    4---5;
-```
-
-# Interprétation des parcours
-
-* Un graphe vu comme espace d'états (sommet: état, arête: action);
-    * Labyrinthe;
-    * Arbre des coups d'un jeu.
-
-. . .
-
-* BFS (Breadth-First) ou DFS (Depth-First) parcourent l'espace des états à la recherche du meilleur mouvement.
-    * Les deux parcourent *tout* l'espace;
-    * Mais si l'arbre est grand, l'espace est gigantesque!
-
-. . .
-
-* Quand on a un temps limité
-    * BFS explore beaucoup de coups dans un futur proche;
-    * DFS explore peu de coups dans un futur lointain.
-
-
-## Contexte: les réseaux (informatique, transport, etc.)
-
-* Graphe orienté;
-* Source: sommet `s`;
-* Destination: sommet `t`;
-* Les arêtes ont des poids (coût d'utilisation, distance, etc.);
-* Le coût d'un chemin est la somme des poids des arêtes d'un chemin.
-
-## Problème à résoudre
-
-* Quel est le plus court chemin entre `s` et `t`.
-
-# Exemples d'application de plus court chemin
-
-## Devenir riches!
-
-* On part d'un tableau de taux de change entre devises.
-* Quelle est la meilleure façon de convertir l'or en dollar?
-
-![Taux de change.](figs/taux_change.pdf){width=80%}
-
-. . .
-
-* 1kg d'or => 327.25 dollars
-* 1kg d'or => 208.1 livres => 327 dollars
-* 1kg d'or => 455.2 francs => 304.39 euros => 327.28 dollars
-
-# Exemples d'application de plus court chemin
-
-## Formulation sous forme d'un graphe: Comment (3min)?
-
-![Taux de change.](figs/taux_change.pdf){width=80%}
-
-
-# Exemples d'application de plus court chemin
-
-## Formulation sous forme d'un graphe: Comment (3min)?
-
-![Graphes des taux de change.](figs/taux_change_graphe.pdf){width=60%}
-
-* Un sommet par devise;
-* Une arête orientée par transaction possible avec le poids égal au taux de change;
-* Trouver le chemin qui maximise le produit des poids.
-
-. . .
-
-## Problème
-
-* On aimerait plutôt avoir une somme...
-
-
-# Exemples d'application de plus court chemin
-
-## Conversion du problème en plus court chemin
-
-* Soit `taux(u, v)` le taux de change entre la devise `u` et `v`.
-* On pose `w(u,w)=-log(taux(u,v))`
-* Trouver le chemin poids minimal pour les poids `w`.
-
-![Graphe des taux de change avec logs.](figs/taux_change_graphe_log.pdf){width=60%}
-
-* Cette conversion se base sur l'idée que
-
-$$
-\log(u\cdot v)=\log(u)+\log(v).
-$$
-
-# Applications de plus courts chemins
-
-## Quelles applications voyez-vous?
-
-. . .
-
-* Déplacement d'un robot;
-* Planificaiton de trajet / trafic urbain;
-* Routage de télécommunications;
-* Réseau électrique optimal;
-* ...
-
-# Plus courts chemins à source unique
-
-* Soit un graphe, $G=(V, E)$, une fonction de pondération $w:E\rightarrow\mathbb{R}$, et un sommet $s\in V$
-  * Trouver pour tout sommet $v\in V$, le chemin de poids minimal reliant $s$ à $v$.
-* Algorithmes standards:
-  * Dijkstra (arêtes de poids positif seulement);
-  * Bellman-Ford (arêtes de poids positifs ou négatifs, mais sans cycles).
-* Comment résoudre le problèmes si tous les poids sont les mêmes?
-
-. . .
-
-* Un parcours en largeur!
-
-# Algorithme de Dijkstra
-
-## Comment chercher pour un plus court chemin?
-
-. . .
-
-```
-si distance(u,v) > distance(u,w) + distance(w,v)
-    on passe par w plutôt qu'aller directement
-```
-
-# Algorithme de Dijkstra (1 à 5)
-
-* $D$ est le tableau des distances au sommet $1$: $D[7]$ est la distance de 1 à 7.
-* Le chemin est pas forcément direct.
-* $S$ est le tableau des sommets visités.
-
-::: columns
-
-:::: column
-
-![Initialisation.](figs/dijkstra_0.png)
-
-::::
-
-:::: column
-
-. . .
-
-![1 visité, `D[2]=1`, `D[4]=3`.](figs/dijkstra_1.png)
-
-::::
-
-:::
-
-# Algorithme de Dijkstra (1 à 5)
-
-::: columns
-
-:::: column
-
-![Plus court est 2.](figs/dijkstra_1.png)
-
-
-::::
-
-:::: column
-
-. . .
-
-![2 visité, `D[3]=2`, `D[7]=3`.](figs/dijkstra_2.png)
-
-::::
-
-:::
-
-# Algorithme de Dijkstra (1 à 5)
-
-::: columns
-
-:::: column
-
-![Plus court est 3.](figs/dijkstra_2.png)
-
-
-::::
-
-:::: column
-
-. . .
-
-![3 visité, `D[7]=3` inchangé, `D[6]=6`.](figs/dijkstra_3.png)
-
-::::
-
-:::
-
-# Algorithme de Dijkstra (1 à 5)
-
-
-::: columns
-
-:::: column
-
-![Plus court est 4 ou 7.](figs/dijkstra_3.png)
-
-
-::::
-
-:::: column
-
-. . .
-
-![4 visité, `D[7]=3` inchangé, `D[5]=9`.](figs/dijkstra_4.png)
-
-::::
-
-:::
-
-# Algorithme de Dijkstra (1 à 5)
-
-::: columns
-
-:::: column
-
-![Plus court est `7`.](figs/dijkstra_4.png)
-
-
-::::
-
-:::: column
-
-. . .
-
-![7 visité, `D[5]=7`, `D[6]=6` inchangé.](figs/dijkstra_5.png)
-
-::::
-
-:::
-
-# Algorithme de Dijkstra (1 à 5)
-
-::: columns
-
-:::: column
-
-![Plus court est 6.](figs/dijkstra_5.png)
-
-
-::::
-
-:::: column
-
-. . .
-
-![`6` visité, `D[5]=7` inchangé.](figs/dijkstra_6.png)
-
-::::
-
-:::
-
-# Algorithme de Dijkstra (1 à 5)
-
-::: columns
-
-:::: column
-
-![Plus court est 5 et c'est la cible.](figs/dijkstra_6.png)
-
-::::
-
-:::: column
-
-. . .
-
-![The end, tous les sommets ont été visités.](figs/dijkstra_7.png)
-
-::::
-
-:::
-
-# Algorithme de Dijkstra
-
-## Idée générale
-
-* On assigne à chaque noeud une distance $0$ pour $s$, $\infty$ pour les autres.
-* Tous les noeuds sont marqués non-visités.
-* Depuis du noeud courant, on suit chaque arête du noeud vers un sommet non visité et on calcule le poids du chemin à chaque voisin et on met à jour sa distance si elle est plus petite que la distance du noeud.
-* Quand tous les voisins du noeud courant ont été visités, le noeud est mis à visité (il ne sera plus jamais visité).
-* Continuer avec le noeud à la distance la plus faible.
-* L'algorithme est terminé losrque le noeud de destination est marqué comme visité, ou qu'on a plus de noeuds qu'on peut visiter et que leur distance est infinie.
-
-# Algorithme de Dijkstra
-
-## Pseudo-code (5min, matrix)
-
-\footnotesize
-
-. . .
-
-```C
-tab dijkstra(graph, s, t)
-    pour chaque v dans graphe
-        distance[v] = infini
-        q = ajouter(q, v)
-    distance[s] = 0
-    tant que non_vide(q)
-    // sélection de u t.q. la distance dans q est min
-        u = min(q, distance)
-        si u == t // on a atteint la cible
-            retourne distance
-        q = remove(q, u)
-        // voisin de u encore dans q
-        pour chaque v dans voisinage(u, q)
-        // on met à jour la distance du voisin en passant par u 
-            n_distance = distance[u] + w(u, v)
-            si n_distance < distance[v]
-                distance[v] = n_distance
-    retourne distance
-```
-
-# Algorithme de Dijkstra
-
-* Cet algorithme, nous donne le plus court chemin mais...
-* ne nous donne pas le chemin!
-
-## Comment modifier l'algorithme pour avoir le chemin?
-
-. . .
-
-* Pour chaque nouveau noeud à visiter, il suffit d'enregistrer d'où on est venu!
-* On a besoin d'un tableau `precedent`.
-
-## Modifier le pseudo-code ci-dessus pour ce faire (3min matrix)
-
-# Algorithme de Dijkstra
-
-\footnotesize
-
-```C
-tab, tab dijkstra(graph, s, t)
-    pour chaque v dans graphe
-        distance[v] = infini
-        precedent[v] = indéfini
-        q = ajouter(q, v)
-    distance[s] = 0
-    tant que non_vide(q)
-    // sélection de u t.q. la distance dans q est min
-        u = min(q, distance) 
-        si u == t
-            retourne distance
-        q = remove(q, u)
-        // voisin de u encore dans q
-        pour chaque v dans voisinage(u, q) 
-            n_distance = distance[u] + w(u, v)
-            si n_distance < distance[v]
-                distance[v] = n_distance
-                precedent[v] = u
-    retourne distance, precedent
-```
-
-# Algorithme de Dijkstra
-
-## Comment reconstruire un chemin ?
-
-. . .
-
-```C
-pile parcours(precedent, s, t)
-    sommets = vide
-    u = t
-    // on a atteint t ou on ne connait pas de chemin
-    si u != s && precedent[u] != indéfini 
-        tant que vrai 
-            sommets = empiler(sommets, u)
-            u = precedent[u]
-            si u == s // la source est atteinte
-                retourne sommets
-    retourne sommets
-```
-
-# Algorithme de Dijkstra amélioré
-
-## On peut améliorer l'algorithme
-
-* Avec une file de priorité!
-
-## Une file de priorité est
-
-* Une file dont chaque élément possède une priorité,
-* Elle existe en deux saveurs: `min` ou `max`:
-    * File `min`: les éléments les plus petits sont retirés en premier.
-    * File `max`: les éléments les plus grands sont retirés en premier.
-* On regarde l'implémentation de la `max`.
-
-## Comment on fait ça?
-
-. . .
-
-* On insère les éléments à haute priorité tout devant dans la file!
-
-# Les files de priorité
-
-## Trois fonction principales
-
-```C
-booléen est_vide(element) // triviale
-element enfiler(element, data, priorite)
-data defiler(element)
-rien changer_priorite(element, data, priorite)
-nombre priorite(element) // utilitaire
-```
-
-## Pseudo-implémentation: structure (1min)
-
-. . .
-
-```C
-struct element
-    data
-    priorite
-    element suivant
-```
-
-# Les files de priorité
-
-## Pseudo-implémentation: enfiler (2min)
-
-. . .
-
-```C
-element enfiler(element, data, priorite)
-    n_element = creer_element(data, priorite)
-    si est_vide(element)
-        retourne n_element
-    si priorite(n_element) > priorite(element)
-        n_element.suivant = element
-        retourne n_element
-    sinon
-        tmp = element
-        prec = element
-        tant que !est_vide(tmp) && priorite < priorite(tmp)
-            prec = tmp
-            tmp = tmp.suivant
-        prev.suivant = n_element
-        n_element.suivant = tmp
-        retourne element           
-```
-
-# Les files de priorité
-
-## Pseudo-implémentation: defiler (2min)
-
-. . .
-
-```C
-data, element defiler(element)
-    si est_vide(element)
-        retourne AARGL!
-    sinon
-        tmp = element.data
-        n_element = element.suivant
-        liberer(element)
-        retourne tmp, n_element
-```
-
-# Algorithme de Dijkstra avec file de priorité min
-
-```C
-distance, precedent dijkstra(graphe, s, t):
-    distance[source] = 0
-    fp = file_p_vide()
-    pour v dans sommets(graphe)
-        si v != s
-            distance[v] = infini
-            precedent[v] = indéfini
-        fp = enfiler(fp, v, distance[v])
-    tant que !est_vide(fp)
-        u, fp = defiler(fp)
-        pour v dans voisinage de u
-            n_distance = distance[u] + w(u, v)
-            si n_distance < distance[v]
-                distance[v] = n_distance
-                precedent[v] = u
-                fp = changer_priorite(fp, v, n_distance)
-    retourne distance, precedent
-```
-
-# Algorithme de Dijkstra avec file
-
-\footnotesize
-
-```C
-distance dijkstra(graphe, s, t)
----------------------------------------------------------
-    pour v dans sommets(graphe)
-O(V)    si v != s
-            distance[v] = infini
-O(V)        fp = enfiler(fp, v, distance[v]) // notre impl est nulle
-------------------O(V * V)-------------------------------
-    tant que !est_vide(fp)
-O(1)    u, fp = defiler(fp)
----------------------------------------------------------
-O(E)    pour v dans voisinage de u
-            n_distance = distance[u] + w(u, v)
-            si n_distance < distance[v]
-                distance[v] = n_distance
-O(V)            fp = changer_priorite(fp, v, n_distance)
----------------------------------------------------------
-    retourne distance
-```
-
-* Total: $\mathcal{O}(|V|^2+|E|\cdot |V|)$:
-    * Graphe dense: $\mathcal{O}(|V|^3)$ 
-    * Graphe peu dense: $\mathcal{O}(|V|^2)$ 
-
-# Algorithme de Dijkstra avec file
-
-## On peut faire mieux
-
-* Avec une meilleure implémentation de la file de priorité:
-    * Tas binaire: $\mathcal{O}(|V|\log|V|+|E|\log|V|)$.
-    * Tas de Fibonnacci: $\mathcal{O}(|V|+|E|\log|V|)$
-* Graphe dense: $\mathcal{O}(|V|^2\log|V|)$.
-* Graphe peu dense: $\mathcal{O}(|V|\log|V|)$.
-
-# Algorithme de Dijkstra (exercice, 5min) 
-
-![L'exercice.](figs/dijkstra_exo.png){width=60%}
-
-* Donner la liste de priorité, puis...
-
-## A chaque étape donner:
-
-* Le tableau des distances à `a`;
-* Le tableau des prédécesseurs;
-* L'état de la file de priorité.
-
-# Algorithme de Dijkstra (corrigé) 
-
-![Le corrigé partie 1.](figs/dijkstra_ex_0.png)
-
-# Algorithme de Dijkstra (corrigé) 
-
-![Le corrigé partie 2.](figs/dijkstra_ex_1.png)
-
-# Algorithme de Dijkstra (corrigé) 
-
-![Le corrigé partie 3.](figs/dijkstra_ex_2.png)
-
-# Algorithme de Dijkstra (corrigé) 
-
-![Le corrigé partie 4.](figs/dijkstra_ex_3.png)
-
-# Algorithme de Dijkstra (corrigé) 
-
-![Le corrigé partie 5.](figs/dijkstra_ex_4.png)
-
-# Algorithme de Dijkstra (corrigé) 
-
-![Le corrigé partie 6.](figs/dijkstra_ex_5.png)
-
-# Limitation de l'algorithme de Dijkstra
-
-## Que se passe-t-il pour?
-
-![Exemple.](figs/exemple_neg.png){width=50%}
-
-## Quel est le problème?
-
-. . .
-
-* L'algorithme n'essaiera jamais le chemin `s->x->y->v` et prendra direct `s->v`.
-* Ce problème n'apparaît que s'il y a des poids négatifs.
-
diff --git a/slides/cours_25.md b/slides/cours_25.md
deleted file mode 100644
index 8deb43b..0000000
--- a/slides/cours_25.md
+++ /dev/null
@@ -1,1077 +0,0 @@
----
-title: "Graphes - Plus court chemin suite"
-date: "2023-06-23"
----
-
-# Questions
-
-* A quoi sert l'algorithme de Dijkstra?
-
-. . .
-
-* A trouver le plus court chemin entre un sommet, $s$, d'un graphe pondéré et tous les autres sommets.
-* Quelle est la limitation de l'algorithme de Dijkstra?
-
-. . .
-
-* Les poids doivent être positifs.
-* Résumer les étapes de l'algorithme de Dijkstra.
-
-. . .
-
-* `distance[source] = 0`, `distance[reste]=inf`;
-* enfiler tous les sommets, `distance <=> priorité`;
-* tant qu'il y a des sommets dans la file:
-    * u = défiler;
-    * pour tous les sommets `v` dans le voisinage de `u`;
-    * mettre à jour `distance[v]` (priorité et précédence) si `distance[v] > distance[u] + w(u,v)`.
-
-
-# Plus cours chemin pour toute paire de sommets
-
-## Comment faire pour avoir toutes les paires?
-
-. . .
-
-* Appliquer Dijkstra sur tous les sommets d'origine.
-* Complexité:
-    * Graphe dense: $\mathcal{O}(|V|)\mathcal{O}(|V|^2\log|V|)=\mathcal{O}(|V|^3\log|V|)$.
-    * Graphe peu dense: $\mathcal{O}(|V|)\mathcal{O}(|V|\log|V|)=\mathcal{O}(|V|^2\log|V|)$.
-
-. . .
-
-## Solution alternative: Floyd--Warshall
-
-* Pour toutes paires de sommets $u,v\in V$, trouver le chemin de poids minimal reliant $u$ à $v$.
-* Complexité $\mathcal{O}(|V|^3)$, indiqué pour graphes denses.
-* Fonctionne avec la matrice d'adjacence.
-
-# Algorithme de Floyd--Warshall
-
-## Idée générale
-
-* Soit l'ensemble de sommets $V=\{1, 2, 3, 4, ..., n\}$.
-* Pour toute paire de sommets, $i,j$, on considère tous les chemins passant par les sommets intermédiaires $\in\{1, 2, ..., k\}$ avec $k\leq n$.
-* On garde pour chaque $k$ la plus petite valeur.
-
-## Principe
-
-* A chaque étape, $k$, on vérifie s'il est plus court d'aller de $i$ à $j$ en passant par le sommet $k$.
-* Si à l'étape $k-1$, le coût du parcours est $p$, on vérifie si $p$ est plus petit que $p_1+p_2$, le chemin de $i$ à $k$, et $k$ à $j$ respectivement.
-
-# Algorithme de Floyd--Warshall
-
-## The algorithme
-
-Soit $d_{ij}(k)$ le plus court chemin de $i$ à $j$ passant par les sommets $\in\{1,2,...,k\}$
-
-$$
-d_{ij}(k)=\left\{
-\begin{array}{ll}
-         w(i,j), & \mbox{si } k=0,\\
-         \min(d_{ij}(k-1),d_{ik}(k-1)+d_{kj}(k-1)), & \mbox{sinon}.
-\end{array}
-\right.
-$$
-
-# Algorithme de Floyd--Warshall (exemple)
-
-
-::: columns
-
-:::: column
-
-![Le graphe, $D=w$.](figs/floyd_exemple.png)
-
-
-::::
-
-:::: column
-
-## Que vaut $D^{(0)}$ (3min)?
-
-. . .
-
-$$
-D^{(0)}=\begin{bmatrix}
-0      & 2      & 4      & \infty & 3 \\
-2      & 0      & 8      & \infty & 1 \\
-6      & 2      & 0      & 4      & 3 \\
-1      & \infty & \infty & 0      & 5 \\
-\infty & \infty & \infty & 1      & 0 \\
-\end{bmatrix}
-$$
-
-::::
-
-:::
-
-# Algorithme de Floyd--Warshall (exemple)
-
-
-::: columns
-
-:::: column
-
-## On part de $D^{(0)}$?
-
-$$
-D^{(0)}=\begin{bmatrix}
-0      & 2      & 4      & \infty & 3 \\
-2      & 0      & 8      & \infty & 1 \\
-6      & 2      & 0      & 4      & 3 \\
-1      & \infty & \infty & 0      & 5 \\
-\infty & \infty & \infty & 1      & 0 \\
-\end{bmatrix}
-$$
-
-
-::::
-
-:::: column
-
-## Que vaut $D^{(1)}$ (3min)?
-
-. . .
-
-$$
-D^{(0)}=\begin{bmatrix}
-0      & 2          & 4               & \infty & 3 \\
-2      & 0          & \mathbf{6}      & \infty & 1 \\
-6      & 2          & 0               & 4      & 3 \\
-1      & \mathbf{3} & \mathbf{5}      & 0      & \mathbf{4} \\
-\infty & \infty     & \infty          & 1      & 0 \\
-\end{bmatrix}
-$$
-
-::::
-
-:::
-
-# Algorithme de Floyd--Warshall (exemple)
-
-
-::: columns
-
-:::: column
-
-## On part de $D^{(0)}$
-
-$$
-D^{(0)}=\begin{bmatrix}
-0      & 2      & 4      & \infty & 3 \\
-2      & 0      & 8      & \infty & 1 \\
-6      & 2      & 0      & 4      & 3 \\
-1      & \infty & \infty & 0      & 5 \\
-\infty & \infty & \infty & 1      & 0 \\
-\end{bmatrix}
-$$
-
-
-::::
-
-:::: column
-
-## Que vaut $D^{(1)}$ (3min)?
-
-. . .
-
-$$
-D^{(1)}=\begin{bmatrix}
-0      & 2          & 4               & \infty & 3 \\
-2      & 0          & \mathbf{6}      & \infty & 1 \\
-6      & 2          & 0               & 4      & 3 \\
-1      & \mathbf{3} & \mathbf{5}      & 0      & \mathbf{4} \\
-\infty & \infty     & \infty          & 1      & 0 \\
-\end{bmatrix}
-$$
-
-## Exemple
-
-$$
-D_{42}^{(1)}=D_{41}^{(0)}+D_{12}^{(0)}=1+2<\infty.
-$$
-
-::::
-
-:::
-
-# Algorithme de Floyd--Warshall (exemple)
-
-::: columns
-
-:::: column
-
-## On part de $D^{(1)}$
-
-$$
-D^{(1)}=\begin{bmatrix}
-0      & 2          & 4      & \infty & 3 \\
-2      & 0          & 6      & \infty & 1 \\
-6      & 2          & 0      & 4      & 3 \\
-1      & 3          & 5      & 0      & 4 \\
-\infty & \infty     & \infty & 1      & 0 \\
-\end{bmatrix}
-$$
-
-
-::::
-
-:::: column
-
-## Que vaut $D^{(2)}$ (3min)?
-
-. . .
-
-$$
-D^{(2)}=\begin{bmatrix}
-0          & 2          & 4      & \infty & 3 \\
-2          & 0          & 6      & \infty & 1 \\
-\mathbf{4} & 2          & 0      & 4      & 3 \\
-1          & 3          & 5      & 0      & 4 \\
-\infty     & \infty     & \infty & 1      & 0 \\
-\end{bmatrix}
-$$
-
-::::
-
-:::
-
-# Algorithme de Floyd--Warshall (exemple)
-
-::: columns
-
-:::: column
-
-## On part de $D^{(2)}$
-
-$$
-D^{(2)}=\begin{bmatrix}
-0          & 2          & 4      & \infty & 3 \\
-2          & 0          & 6      & \infty & 1 \\
-4          & 2          & 0      & 4      & 3 \\
-1          & 3          & 5      & 0      & 4 \\
-\infty     & \infty     & \infty & 1      & 0 \\
-\end{bmatrix}
-$$
-
-
-::::
-
-:::: column
-
-## Que vaut $D^{(3)}$ (3min)?
-
-. . .
-
-$$
-D^{(3)}=\begin{bmatrix}
-0          & 2          & 4      & \mathbf{8}  & 3 \\
-2          & 0          & 6      & \mathbf{10} & 1 \\
-4          & 2          & 0      & 4           & 3 \\
-1          & 3          & 5      & 0           & 4 \\
-\infty     & \infty     & \infty & 1           & 0 \\
-\end{bmatrix}
-$$
-
-::::
-
-:::
-
-# Algorithme de Floyd--Warshall (exemple)
-
-::: columns
-
-:::: column
-
-## On part de $D^{(3)}$
-
-$$
-D^{(3)}=\begin{bmatrix}
-0          & 2          & 4      & 8  & 3 \\
-2          & 0          & 6      & 10 & 1 \\
-4          & 2          & 0      & 4  & 3 \\
-1          & 3          & 5      & 0  & 4 \\
-\infty     & \infty     & \infty & 1  & 0 \\
-\end{bmatrix}
-$$
-
-::::
-
-:::: column
-
-## Que vaut $D^{(4)}$ (3min)?
-
-. . .
-
-$$
-D^{(4)}=\begin{bmatrix}
-0          & 2          & 4         & 8  & 3 \\
-2          & 0          & 6         & 10 & 1 \\
-4          & 2          & 0         & 4  & 3 \\
-1          & 3          & 5         & 0  & 4 \\
-\mathbf{2} & \mathbf{4} & \mathbf{6} & 1  & 0 \\
-\end{bmatrix}
-$$
-
-::::
-
-:::
-
-# Algorithme de Floyd--Warshall (exemple)
-
-::: columns
-
-:::: column
-
-## On part de $D^{(4)}$
-
-$$
-D^{(4)}=\begin{bmatrix}
-0          & 2          & 4         & 8  & 3 \\
-2          & 0          & 6         & 10 & 1 \\
-4          & 2          & 0         & 4  & 3 \\
-1          & 3          & 5         & 0  & 4 \\
-2          & 4          & 6         & 1  & 0 \\
-\end{bmatrix}
-$$
-
-::::
-
-:::: column
-
-## Que vaut $D^{(5)}$ (3min)?
-
-. . .
-
-$$
-D^{(5)}=\begin{bmatrix}
-0          & 2          & 4         & \mathbf{4} & 3 \\
-2          & 0          & 6         & \mathbf{2} & 1 \\
-4          & 2          & 0         & 4          & 3 \\
-1          & 3          & 5         & 0          & 4 \\
-2          & 4          & 6         & 1          & 0 \\
-\end{bmatrix}
-$$
-
-::::
-
-:::
-
-# Algorithme de Floyd--Warshall
-
-## The pseudo-code (10min)
-
-* Quelle structure de données?
-* Quelle initialisation?
-* Quel est le code pour le calcul de la matrice $D$?
-
-# Algorithme de Floyd--Warshall
-
-## The pseudo-code
-
-* Quelle structure de données?
-
-```C
-int distance[n][n];
-```
-
-. . .
-
-* Quelle initialisation?
-
-```C
-matrice ini_floyd_warshall(distance, n, w)
-    pour i de 1 à n
-        pour j de 1 à n
-            distance[i][j] = w(i,j)
-    retourne distance
-```
-
-# Algorithme de Floyd--Warshall
-
-## The pseudo-code
-
-* Quel est le code pour le calcul de la matrice $D$?
-
-```C
-matrice floyd_warshall(distance, n, w)
-    pour k de 1 à n
-        pour i de 1 à n
-            pour j de 1 à n
-                distance[i][j] = min(distance[i][j], 
-                    distance[i][k] + distance[k][j])
-    retourne distance
-```
-
-# Algorithme de Floyd--Warshall
-
-## La matrice de précédence
-
-* On a pas encore vu comment reconstruire le plus court chemin!
-* On définit, $P_{ij}^{(k)}$, qui est le prédécesseur du sommet $j$ depuis $i$ avec les sommets intermédiaires $\in\{1, 2, ..., k\}$.
-$$
-P^{(0)}_{ij}=\left\{
-\begin{array}{ll}
-         \mbox{vide}, & \mbox{si } i=j\mbox{, ou }w(i,j)=\infty\\
-         i, & \mbox{sinon}.
-\end{array}
-\right.
-$$
-
-* Mise à jour
-$$
-P^{(k)}_{ij}=\left\{
-\begin{array}{ll}
-         P^{(k-1)}_{\mathbf{i}j}, & \mbox{si } d_{ij}^{(k)}\leq d_{ik}^{(k-1)}+d_{kj}^{(k-1)}\\
-         P^{(k-1)}_{\mathbf{k}j}, & \mbox{sinon}.
-\end{array}
-\right.
-$$
-
-. . .
-
-* Moralité: si le chemin est plus court en passant par $k$, alors il faut utiliser son prédécesseur!
-
-# Algorithme de Floyd--Warshall
-
-## La matrice de précédence (pseudo-code, 3min)
-
-. . .
-
-```C
-matrice, matrice floyd_warshall(distance, n, w)
-    pour k de 1 à n
-        pour i de 1 à n
-            pour j de 1 à n
-                n_distance = distance[i][k] + distance[k][j]
-                if n_distance < distance[i][j]
-                    distance[i][j] = n_distance
-                    précédence[i][j] = précédence[k][j]
-    retourne distance, précédence
-```
-
-# Algorithme de Floyd--Warshall (exercice)
-
-
-::: columns
-
-:::: column
-
-![Le graphe, $D=w$.](figs/floyd_exemple.png)
-
-
-::::
-
-:::: column
-
-## Que vaut $P^{(0)}$ (3min)?
-
-. . .
-
-$$
-P^{(0)}=\begin{bmatrix}
--          & 1          & 1         & -          & 1 \\
-2          & -          & 2         & -          & 2 \\
-3          & 3          & -         & 3          & 3 \\
-4          & -          & -         & -          & 4 \\
--          & -          & -         & 5          & - \\
-\end{bmatrix}
-$$
-
-::::
-
-:::
-
-# Algorithme de Floyd--Warshall (exercice)
-
-
-::: columns
-
-:::: column
-
-![Le graphe, $D=w$.](figs/floyd_exemple.png)
-
-
-::::
-
-:::: column
-
-## Que vaut $P^{(5)}$ (10min)?
-
-. . .
-
-$$
-P^{(5)}=\begin{bmatrix}
--          & 1          & 1         & 5          & 1 \\
-2          & -          & 1         & 5          & 2 \\
-2          & 3          & -         & 3          & 3 \\
-4          & 1          & 1         & -          & 1 \\
-4          & 1          & 1         & 5          & - \\
-\end{bmatrix}
-$$
-
-::::
-
-:::
-
-# Exercice: retrouver le chemin entre 1 et 4 (5min)
-
-$$
-P=\begin{bmatrix}
--          & 1          & 1         & 5          & 1 \\
-2          & -          & 1         & 5          & 2 \\
-2          & 3          & -         & 3          & 3 \\
-4          & 1          & 1         & -          & 4 \\
-4          & 1          & 1         & 5          & - \\
-\end{bmatrix}
-$$
-
-. . .
-
-## Solution
-
-* Le sommet $5=P_{14}$, on a donc, $5\rightarrow 4$, on veut connaître le prédécesseur de 5.
-* Le sommet $1=P_{15}$, on a donc, $1\rightarrow 5\rightarrow 4$. The end.
-
-# Exercice complet
-
-## Appliquer l'algorithme de Floyd--Warshall au graphe suivant
-
-![The exorcist.](figs/floyd_exercice.png){width=50%}
-
-* Bien indiquer l'état de $D$ et $P$ à chaque étape!
-* Ne pas oublier de faire la matrice d'adjacence évidemment...
-
-# La suite
-
-* Sans transition.... la suite!
-
-# Trouver un réseau électrique pour
-
-![Ces maisons n'ont pas d'électricité.](figs/arbre_couvrant_vide.png)
-
-# Solution: pas optimale
-
-![Le réseau simple, mais nul.](figs/arbre_couvrant_mal.png)
-
-* La longueur totale des câbles est super longue!
-
-# Solution: optimale
-
-![Le meilleur réseau.](figs/arbre_couvrant_bien.png)
-
-# Formalisation: Les arbres couvrants
-
-## Application: minimisation des coûts
-
-* Équipement d'un lotissement avec des lignes électriques/téléphoniques, des canalisations, ...
-
-. . .
-
-* Pour réduire les coûts, on cherche à minimiser la longueur totale des câbles/tuyaux.
-
-. . .
-
-* Les lignes/tuyaux forment un *arbre couvrant*.
-
-. . .
-
-* La meilleure option est un *arbre couvrant minimal*.
-
-
-# Formalisation: Les arbres couvrants
-
-* Qu'est-ce qu'un arbre couvrant? Des idées? De quel objet on part? Où va-t-on?
-
-. . .
-
-* Un arbre couvrant d'un graphe non-orienté et connexe est:
-    * un arbre inclus dans le graphe qui connecte tous les sommets du graphe.
-
-. . .
-
-![Exemple d'arbres couvrants d'un graphe connexe.](figs/arbre_couvrant_exemples.png)
-
-# Arbres couvrants
-
-* Quels algorithmes que nous avons déjà vus permettent de construire des arbres couvrants?
-
-. . .
-
-* Les parcours en largeur et en profondeur!
-
-. . .
-
-![Graphe, et parcours comme arbres couvrants.](figs/arbres_couvrants_parcours.png)
-
-# Arbres couvrants minimaux
-
-* Un *arbre couvrant minimal* est un sous-graphe d'un graphe non-orienté pondéré $G(V,E)$, tel quel:
-    * C'est un arbre (graphe acyclique);
-    * Il couvre tous les sommets de $G$ et contient $|V|-1$ arêtes;
-    * Le coût total associé aux arêtes de l'arbre est minimum parmi tous les arbres couvrants possibles.
-
-. . .
-
-* Est-il unique?
-
-. . .
-
-* Pas forcément.
-
-# Arbres couvrants minimaux
-
-* Comment générer un arbre couvrant minimal?
-
-![Un graphe, connexe, non-orienté, pondéré, et son arbre couvrant minimal.](figs/arbre_couvrant_minimal_exemple.png)
-
-# Algorithme de Prim
-
-::: columns
-
-:::: column
-
-## Un exemple
-
-![Le graphe de départ.](figs/prim_0.png)
-
-::::
-
-:::: column
-
-## On part de `e` (au hasard)
-
-![Le sommet `e` est couvert.](figs/prim_1.png)
-
-::::
-
-:::
-
-# Algorithme de Prim
-
-::: columns
-
-:::: column
-
-## On choisit comment? 
-
-![Quelle arête choisir?](figs/prim_1.png)
-
-. . .
-
-* L'arête la plus courte sortant d'un sommet déjà visité, et entrant dans un sommet non-visité.
-
-::::
-
-:::: column
-
-. . .
-
-## L'arête `e->d`
-
-![Le sommet `d` est couvert.](figs/prim_2.png)
-
-::::
-
-:::
-
-# Algorithme de Prim
-
-::: columns
-
-:::: column
-
-## On choisit comment? 
-
-![Quelle arête choisir?](figs/prim_2.png)
-
-. . .
-
-* L'arête la plus courte sortant d'un sommet déjà visité, et entrant dans un sommet non-visité.
-
-::::
-
-:::: column
-
-. . .
-
-## L'arête `d->a`
-
-![Le sommet `a` est couvert.](figs/prim_3.png)
-
-::::
-
-:::
-
-# Algorithme de Prim
-
-::: columns
-
-:::: column
-
-## On choisit comment? 
-
-![Quelle arête choisir?](figs/prim_3.png)
-
-. . .
-
-* L'arête la plus courte sortant d'un sommet déjà visité, et entrant dans un sommet non-visité.
-
-::::
-
-:::: column
-
-. . .
-
-## L'arête `d->c`
-
-![Le sommet `c` est couvert.](figs/prim_4.png)
-
-::::
-
-:::
-
-# Algorithme de Prim
-
-::: columns
-
-:::: column
-
-## On choisit comment? 
-
-![Quelle arête choisir?](figs/prim_4.png)
-
-. . .
-
-* L'arête la plus courte sortant d'un sommet déjà visité, et entrant dans un sommet non-visité.
-
-::::
-
-:::: column
-
-. . .
-
-## L'arête `e->b`
-
-![Le sommet `b` est couvert.](figs/prim_5.png)
-
-* Game over!
-
-::::
-
-:::
-
-# Algorithme de Prim
-
-## Structures de données
-
-* Dans quoi allons nous stocker les sommets?
-
-. . .
-
-* File de priorité min.
-* Autre chose?
-
-. . .
-
-* Tableau des distances (comme pour Dijkstra).
-* Autre chose?
-
-. . .
-
-* Tableau des parents (presque comme pour Dijkstra).
-* Autre chose?
-
-. . .
-
-* Non.
-
-# Algorithme de Prim
-
-## Initialisation: Pseudo-code (2min)
-
-. . .
-
-```C
-file_priorité, distance, parent initialisation(graphe)
-    r = aléatoire(graphe)
-    distance[r] = 0
-    parent[r] = indéfini
-    fp = file_p_vide()
-    pour v dans sommets(graphe)
-        si v != r
-            distance[v] = infini
-            parent[v]   = indéfini
-        fp = enfiler(fp, v, distance[v])
-    retourne fp, distance, parent
-```
-
-# Algorithme de Prim
-
-## Algorithme: Pseudo-code (5min)
-
-. . .
-
-```C
-sommets, parent prim(file_priorité, distance, parent)
-    sommets = vide
-    tant que !est_vide(file_priorité)
-        u, fp = défiler(file_priorité)
-        sommets = insérer(sommets, u)
-        pour v dans voisinage de u et pas dans sommets 
-        // ou dans file_priorité
-            si w(u, v) < distance[v]
-                parent[w] = u
-                distance[w] = w(u, v)
-                fp = changer_priorité(fp, w, w(u, v))
-    retourne sommets, parent
-```
-
-# Exemple d'algorithme de Prim
-
-::: columns
-
-:::: {.column width="40%"}
-
-## Un exemple
-
-![Étape 1.](figs/prim_1.png)
-
-::::
-
-:::: column
-
-```
-FP |  e  |  d  |  b  |  c  |  a  |
-----------------------------------
-D  |  0  | inf | inf | inf | inf |
-
-   |  e  |  d  |  b  |  c  |  a  |
-----------------------------------
-P  |  -  |  -  |  -  |  -  |  -  |
-```
-
-## Devient?
-
-. . .
-
-```
-FP |  d  |  b  |  c  |  a  |
-----------------------------
-D  |  4  |  5  |  5  | inf |
-
-   |  e  |  d  |  b  |  c  |  a  |
-----------------------------------
-P  |  -  |  e  |  e  |  e  |  -  |
-```
-
-::::
-
-:::
-
-# Exemple d'algorithme de Prim
-
-::: columns
-
-:::: {.column width="40%"}
-
-## Un exemple
-
-![Étape 2.](figs/prim_2.png)
-
-::::
-
-:::: column
-
-```
-FP |  d  |  b  |  c  |  a  |
-----------------------------
-D  |  4  |  5  |  5  | inf |
-
-   |  e  |  d  |  b  |  c  |  a  |
-----------------------------------
-P  |  -  |  e  |  e  |  e  |  -  |
-```
-
-## Devient?
-
-. . .
-
-```
-FP |  a  |  c  |  b  |
-----------------------
-D  |  2  |  4  |  5  |
-
-   |  e  |  d  |  b  |  c  |  a  |
-----------------------------------
-P  |  -  |  e  |  e  |  d  |  d  |
-```
-
-::::
-
-:::
-
-# Exemple d'algorithme de Prim
-
-::: columns
-
-:::: {.column width="40%"}
-
-## Un exemple
-
-![Étape 3.](figs/prim_3.png)
-
-::::
-
-:::: column
-
-```
-FP |  a  |  c  |  b  |
-----------------------
-D  |  2  |  4  |  5  |
-
-   |  e  |  d  |  b  |  c  |  a  |
-----------------------------------
-P  |  -  |  e  |  e  |  d  |  d  |
-```
-
-## Devient?
-
-. . .
-
-```
-FP |  c  |  b  |
-----------------
-D  |  4  |  5  |
-
-   |  e  |  d  |  b  |  c  |  a  |
-----------------------------------
-P  |  -  |  e  |  e  |  d  |  d  |
-```
-
-::::
-
-:::
-
-# Exemple d'algorithme de Prim
-
-::: columns
-
-:::: {.column width="40%"}
-
-## Un exemple
-
-![Étape 4.](figs/prim_4.png)
-
-::::
-
-:::: column
-
-```
-FP |  c  |  b  |
-----------------
-D  |  4  |  5  |
-
-   |  e  |  d  |  b  |  c  |  a  |
-----------------------------------
-P  |  -  |  e  |  e  |  d  |  d  |
-```
-
-## Devient?
-
-. . .
-
-```
-FP |  b  |
-----------
-D  |  5  |
-
-   |  e  |  d  |  b  |  c  |  a  |
-----------------------------------
-P  |  -  |  e  |  e  |  d  |  d  |
-```
-
-::::
-
-:::
-
-# Exemple d'algorithme de Prim
-
-::: columns
-
-:::: {.column width="40%"}
-
-## Un exemple
-
-![Étape 5.](figs/prim_4.png)
-
-::::
-
-:::: column
-
-```
-FP |  b  |
-----------
-D  |  5  |
-
-   |  e  |  d  |  b  |  c  |  a  |
-----------------------------------
-P  |  -  |  e  |  e  |  d  |  d  |
-```
-
-## Devient?
-
-. . .
-
-```
-FP |
-----
-D  |
-
-   |  e  |  d  |  b  |  c  |  a  |
-----------------------------------
-P  |  -  |  e  |  e  |  d  |  d  |
-```
-
-::::
-
-:::
-
-# Exercice: algorithme de Prim
-
-## Appliquer l'algorithme de Prim à (15min):
-
-![En démarrant du sommet $V_1$.](figs/prim_exercice.png)
-
-# Exercice: algorithme de Prim
-
-## Solution
-
-![](figs/prim_solution.png)
-
-# Complexité de l'algorithme de Prim
-
-\footnotesize
-
-```C
-file_priorité, distance, parent initialisation(graphe)
-    // choix r et initialisation
-    pour v dans sommets(graphe)
-O(|V|)  // initialisation distance et parent
-        fp = enfiler(fp, v, distance[v])
-    retourne fp, distance, parent
-sommets, parent prim(file_priorité, distance, parent)
-    sommets = vide
-    tant que !est_vide(file_priorité)
-O(|V|)  u, fp = défiler(file_priorité)
-        sommets = insérer(sommets, u)
-        pour v dans voisinage de u et pas dans sommets
-    O(|E|)  si w(u, v) < distance[v]
-                // màj dista + parent
-        O(|V|)  fp = changer_priorité(fp, w, w(u, v))
-    retourne sommets, parent
-```
-
-* $O(|V|)+O(|E|)+O(|V|^2)=O(|E|+|V|^2)$
-* Remarque: $O(|E|)$ n'est pas mutliplié par $O(|V|)$, car les arêtes parcourues qu'une fois en **tout**.
diff --git a/slides/cours_3.md b/slides/cours_3.md
deleted file mode 100644
index f2f3788..0000000
--- a/slides/cours_3.md
+++ /dev/null
@@ -1,339 +0,0 @@
----
-title: "Introduction aux algorithmes"
-date: "2022-10-05"
-patat:
-  eval:
-    tai:
-      command: fish
-      fragment: false
-      replace: true
-    ccc:
-      command: fish
-      fragment: false
-      replace: true
-  images:
-    backend: auto
----
-
-# Rappel (1/2)
-
-## Quels algos avons-nous vu la semaine passée?
-
-. . .
-
-* L'algorithme de la factorielle.
-* L'algorithme du PPCM.
-* Le début de l'algorithme du PGCD.
-
-# Rappel (2/2)
-
-## Algorithme du PPCM?
-
-. . .
-
-```C
-int main() { 
-    int m = 15, n = 12;
-    int mult_m = m, mult_n = n;
-    while (mult_m != mult_n) {
-        if (mult_m > mult_n) {
-            mult_n += n;
-        } else {
-            mult_m += m;
-        }
-    }
-    printf("Le ppcm de %d et %d est %d\n", n, m, mult_m);
-}
-```
-
-# Le calcul du PGCD (1/5)
-
-## Définition
-
-Le plus grand commun diviseur (PGCD) de deux nombres entiers non nuls est le
-plus grand entier qui les divise en même temps. 
-
-## Exemples:
-
-```C
-PGCD(3, 4) = 1,
-PGCD(4, 6) = 2,
-PGCD(5, 15) = 5.
-```
-
-. . .
-
-## Mathématiquement
-
-Décomposition en nombres premiers:
-
-$$
-36 = 2^2\cdot 3^2,\quad 90=2\cdot 5\cdot 3^2,
-$$
-On garde tous les premiers à la puissance la plus basse
-$$
-PGCD(36, 90)=2^{\min{1,2}}\cdot 3^{\min{2,2}}\cdot 5^{\min{0,1}}=18.
-$$
-
-# Le calcul du PGCD (2/5)
-
-## Algorithme
-
-Par groupe de 3 (5-10min):
-
-* réfléchissez à un algorithme alternatif donnant le PGCD de deux nombres;
-* écrivez l'algorithme en pseudo-code.
-
-. . .
-
-## Exemple d'algorithme
-
-```C
-PGCD(36, 90):
-90 % 36 != 0 // otherwise 36 would be PGCD
-90 % 35 != 0 // otherwise 35 would be PGCD
-90 % 34 != 0 // otherwise 34 would be PGCD
-...
-90 % 19 != 0 // otherwise 19 would be PGCD
-90 % 18 == 0 // The end!
-```
-
-* 18 modulos, 18 assignations, et 18 comparaisons.
-
-# Le calcul du PGCD (3/5)
-
-## Transcrivez cet exemple en algorithme (groupe de 3) et codez-le (5-10min)!
-
-. . .
-
-## Optimisation
-
-* Combien d'additions / comparaisons au pire?
-* Un moyen de le rendre plus efficace?
-
-. . .
-
-## Tentative de correction
-
-```C
-void main() {
-   int n = 90, m = 78;
-   int gcd = 1;
-   for (int div = n; div >= 2; div--) { // div = m, sqrt(n)
-      if (n % div == 0 && m % div == 0) {
-         gcd = div;
-         break;
-      }
-   }
-   printf("Le pgcd de %d et %d est %d\n", n, m, gcd);
-}
-```
-
-# Le calcul du PGCD (4/5)
-
-## Réusinage: l'algorithme d'Euclide
-
-`Dividende = Diviseur * Quotient + Reste`
-
-```C
-PGCD(35, 60):
-35 = 60 * 0 + 35 // 60 -> 35, 35 -> 60
-60 = 35 * 1 + 25 // 35 -> 60, 25 -> 35
-35 = 25 * 1 + 10 // 25 -> 35, 20 -> 25
-25 = 10 * 2 +  5 // 10 -> 25, 5  -> 10
-10 =  5 * 2 +  0 // PGCD = 5!
-```
-
-. . .
-
-## Algorithme
-
-Par groupe de 3 (5-10min):
-
-* analysez l'exemple ci-dessus;
-* transcrivez le en pseudo-code.
-
-# Le calcul du PGCD (5/5)
-
-## Pseudo-code
-
-```C
-entier pgcd(m, n) {
-    tmp_n = n
-    tmp_m = m
-    tant que (tmp_m ne divise pas tmp_n) {
-        tmp   = tmp_n
-        tmp_n = tmp_m
-        tmp_m = tmp modulo tmp_m
-    }
-    retourne tmp_m
-}
-```
-
-# Le code du PGCD de 2 nombres
-
-## Implémentez le pseudo-code et postez le code sur matrix (5min).
-
-. . .
-
-## Un corrigé possible
-
-```C
-#include <stdio.h>
-void main() {
-   int n = 90;
-   int m = 78;
-   printf("n = %d et m = %d\n", n, m);
-   int tmp_n = n;
-   int tmp_m = m;
-   while (tmp_n%tmp_m > 0) {
-      int tmp = tmp_n;
-      tmp_n = tmp_m;
-      tmp_m = tmp % tmp_m;
-   }
-   printf("Le pgcd de %d et %d est %d\n", n, m, tmp_m);
-}
-```
-
-# Quelques algorithmes simples
-
-* Remplissage d'un tableau et recherche de la valeur minimal
-* Anagrammes
-* Palindromes
-* Crible d'ératosthène
-
-. . .
-
-* Ces algorithme nécessitent d'utiliser des **tableaux**.
-
-# Collections: tableaux statiques
-
-\footnotesize
-
-* Objets de même type: leur nombre est **connu à la compilation**;
-* Stockés contigüement en mémoire (très efficace);
-
-    ```C
-    #define SIZE 10
-    int entiers[] = {2, 1, 4, 5, 7}; // taille 5, initialisé
-    int tab[3]; // taille 3, non initialisé
-    float many_floats[SIZE]; // taille 10, non initialisé
-    ```
-* Les indices sont numérotés de `0` à `taille-1`;
-
-    ```C
-    int premier = entier[0]; // premier = 2
-    int dernier = entier[4]; // dernier = 7
-    ```
-* Les tableaux sont **non-initialisés** par défaut;
-* Les bornes ne sont **jamais** vérifiées.
-
-    ```C
-    int indetermine_1 = tab[1];     // undefined behavior
-    int indetermine_2 = entiers[5]; // UB
-    ```
-
-# Remarques
-
-* Depuis  `C99` possibilité d'avoir des tableaux dont la taille est *inconnue à
-  la compilation*;
-
-    ```C
-    int size;
-    scanf("%d", &size);
-    char string[size];
-    ```
-
- . . .
-
-* Considéré comme une mauvaise pratique: que se passe-t-il si `size == 1e9`?
-* On préfère utiliser l'allocation **dynamique** de mémoire pour ce genre de
-  cas-là (spoiler du futur du cours).
-
-# Initialisation
-
-* Les variables ne sont **jamais** initialisées en `C` par défaut.
-* Question: Que contient le tableau suivant?
-
-    ```C
-    double tab[4];
-    ```
-
-. . .
-
-* Réponse: On en sait absolument rien!
-* Comment initialiser un tableau?
-
-. . .
-
-```C
-#define SIZE 10
-double tab[SIZE];
-for (int i = 0; i < SIZE; ++i) {
-    tab[i] = rand() / (double)RAND_MAX * 10.0 - 5.0; 
-    // tab[i] contient un double dans [-5;5]
-}
-```
-
-# Recherche du minimum dans un tableau (1/2)
-
-## Problématique
-
-Trouver la valeur minimale contenue dans un tableau et l'indice de l'élément le plus petit.
-
-## Écrire un pseudo-code résolvant ce problème (groupe de 3), 2min
-
-. . .
-
-```C
-index = 0
-min   = tab[0]
-pour i de 1 à SIZE - 1
-    si min > tab[i]
-        min = tab[i]
-        index = i
-```
-
-# Recherche du minimum dans un tableau (2/2)
-
-## Implémenter ce bout de code en C (groupe de 3), 4min
-
-. . .
-
-```C
-int index = 0;
-float min = tab[0];
-for (int i = 1; i < SIZE; ++i) {
-    if min > tab[i] {
-        min = tab[i];
-        index = i;
-    }
-}
-```
-
-# Tri par sélection (1/2)
-
-## Problématique
-
-Trier un tableau par ordre croissant.
-
-## Idée d'algorithme
-
-```C
-ind = 0
-tant que (ind < SIZE-1)
-    Trouver le minimum du tableau, tab_min[ind:SIZE].
-    Échanger tab_min avec tab[ind]
-    ind += 1
-```
-
-# Tri par sélection (2/2)
-
-## Implémentation par groupe de 3
-
-* Initialiser aléatoirement un tableau de `double` de taille 10;
-* Afficher le tableau;
-* Trier par sélection le tableau;
-* Afficher le résultat trié;
-* Vérifier algorithmiquement que le résultat est bien trié.
-
diff --git a/slides/cours_4.md b/slides/cours_4.md
deleted file mode 100644
index 7731096..0000000
--- a/slides/cours_4.md
+++ /dev/null
@@ -1,851 +0,0 @@
----
-title: "Introduction aux algorithmes"
-date: "2022-10-19"
----
-
-# Rappel
-
-## Quel est l'algorithme du tri par sélection?
-
-. . .
-
-1. Soit un tableau d'entiers, `tab[0:SIZE-1]` et `i=0`.
-2. Trouver l'indice, `j`, de `tab[i:SIZE-2]` où la valeur est minimale.
-3. Échanger `tab[i]` et `tab[j]`.
-4. `i+=1` et revenir à 2, tant que `j < SIZE-2`.
-
-# Un type de tableau particulier
-
-## Les chaînes de caractères
-
-```C
-string = tableau + char + magie noire
-```
-
-# Le type `char`{.C}
-
-- Le type `char`{.C} est utilisé pour représenter un caractère.
-- C'est un entier 8 bits signé.
-- En particulier:
-    - Écrire
-        
-        ```C
-        char c = 'A';
-        ```
-    - Est équivalent à:
-
-        ```C
-        char c = 65;
-        ```
-- Les fonctions d'affichage interprètent le nombre comme sa valeur ASCII.
-
-# Chaînes de caractères (strings)
-
-- Chaîne de caractère `==` tableau de caractères **terminé par la valeur** `'\0'`{.C} ou `0`{.C}.
-
-## Exemple
-
-```C
-char *str  = "HELLO !";
-char str[] = "HELLO !";
-```
-
-Est représenté par
-
-| `char`  | `H`  | `E`  | `L`  | `L`  | `O`  |      | `!`  | `\0`|
-|---------|------|------|------|------|------|------|------|-----|
-| `ASCII` | `72` | `69` | `76` | `76` | `79` | `32` | `33` | `0` |
-
-. . .
-
-## A quoi sert le `\0`?
-
-. . .
-
-Permet de connaître la fin de la chaîne de caractères (pas le cas des autres
-sortes de tableaux).
-
-# Syntaxe
-
-```C
-char name[5];
-name[0] = 'P';  // = 70;
-name[1] = 'a';  // = 97;
-name[2] = 'u';  // = 117;
-name[3] = 'l';  // = 108;
-name[4] = '\0'; // = 0;
-char name[] = {'P', 'a', 'u', 'l', '\0'};
-char name[5] = "Paul";
-char name[] = "Paul";
-char name[100] = "Paul is not 100 characters long.";
-```
-
-# Fonctions
-
-- Il existe une grande quantités de fonction pour la manipulation de chaînes de caractères dans `string.h`.
-- Fonctions principales:
-
-    ```C
-    // longueur de la chaîne (sans le \0)
-    size_t strlen(char *str);
-    // copie jusqu'à un \0
-    char *strcpy(char *dest, const char *src);
-     // copie len char
-    char *strncpy(char *dest, const char *src, size_t len);
-    // compare len chars
-    int strncmp(char *str1, char *str2, size_t len);
-    // compare jusqu'à un \0
-    int strcmp(char *str1, char *str2);
-    ```
-
-- Pour avoir la liste complète: `man string`.
-
-. . .
-
-## Quels problèmes peuvent se produire avec `strlen`, `strcpy`, `strcmp`?
-
-# Les anagrammes
-
-## Définition
-
-Deux mots sont des anagrammes l'un de l'autre quand ils contiennent les mêmes 
-lettres mais dans un ordre différent.
-
-## Exemple
-
-| `t`  | `u`  | `t`  | `u`  | `t`  | `\0` | ` `  | ` ` |
-|------|------|------|------|------|------|------|-----|
-| `t`  | `u`  | `t`  | `t`  | `u`  | `\0` | ` `  | ` ` |
-
-
-## Problème: Trouvez un algorithme pour déterminer si deux mots sont des anagrammes.
-
-# Les anagrammes
-
-## Il suffit de:
-
-1. Trier les deux mots.
-2. Vérifier s'ils contiennent les mêmes lettres.
-
-## Implémentation ensemble
-
-```C
-int main() { // pseudo C
-    tri(mot1);
-    tri(mot2);
-    if egalite(mot1, mot2) {
-        // anagrammes
-    } else {
-        // pas anagrammes
-    }
-}
-```
-
-<!-- TODO: Live implémentation hors des cours? -->
-
-# Les palindromes
-
-Mot qui se lit pareil de droite à gauche que de gauche à droite:
-
-. . .
-
-* rotor, kayak, ressasser, ...
-
-## Problème: proposer un algorithme pour détecter un palindrome
-
-. . .
-
-## Solution 1
-
-```C
-while (first_index < last_index {
-    if (mot[first_index] != mot [last_index]) {
-        return false;
-    }
-    first_index += 1;
-    last_index -= 1;
-}
-return true;
-```
-
-. . .
-
-## Solution 2
-
-```C
-mot_tmp = revert(mot);
-return mot == mot_tmp;
-```
-
-# Crible d'Ératosthène
-
-Algorithme de génération de nombres premiers.
-
-## Exercice
-
-* À l'aide d'un tableau de booléens,
-* Générer les nombres premiers plus petits qu'un nombre $N$
-
-## Pseudo-code
-
-* Par groupe de trois, réfléchir à un algorithme.
-
-## Programme en C
-
-* Implémenter l'algorithme et le poster sur le salon `Element`.
-
-# Crible d'Ératosthène: solution
-
-\footnotesize
-
-```C
-#include <stdio.h>
-#include <stdbool.h>
-#define SIZE 51
-int main() {
-   bool tab[SIZE];
-   for (int i=0;i<SIZE;i++) {
-      tab[i] = true;  
-   }
-   for (int i = 2; i < SIZE; i++) {
-      if (tab[i]) {
-         printf("%d ", i);
-         int j = i;
-         while (j < SIZE) {
-            j += i;
-            tab[j] = false;
-         } 
-      } 
-   }
-   printf("\n");
-}
-```
-
-
-# Réusinage de code (refactoring)
-
-## Le réusinage est?
-
-. . .
-
-* le processus de restructuration d'un programme:
-    * en modifiant son design,
-    * en modifiant sa structure,
-    * en modifiant ses algorithmes
-    * mais en **conservant ses fonctionalités**.
-
-. . .
-
-## Avantages?
-
-. . .
-
-* Amélioration de la lisibilité,
-* Amélioration de la maintenabilité,
-* Réduction de la complexité.
-
-. . .
-
-## "Make it work, make it nice, make it fast",  Kent Beck.
-
-. . .
-
-## Exercice:
-
-* Réusiner le code se trouvant sur
-  [Cyberlearn](https://cyberlearn.hes-so.ch/mod/resource/view.php?id=1627712).
-
-# Tableau à deux dimensions (1/4)
-
-## Mais qu'est-ce donc?
-
-. . .
-
-* Un tableau où chaque cellule est un tableau.
-
-## Quels cas d'utilisation?
-
-. . .
-
-* Tableau à double entrée;
-* Image;
-* Écran (pixels);
-* Matrice (mathématique);
- 
-# Tableau à deux dimensions (2/4)
-
-## Exemple: tableau à 3 lignes et 4 colonnes d'entiers
-
-+-----------+-----+-----+-----+-----+
-| `indices` | `0` | `1` | `2` | `3` |
-+-----------+-----+-----+-----+-----+
-| `0`       | `7` | `4` | `7` | `3` |
-+-----------+-----+-----+-----+-----+
-| `1`       | `2` | `2` | `9` | `2` |
-+-----------+-----+-----+-----+-----+
-| `2`       | `4` | `8` | `8` | `9` |
-+-----------+-----+-----+-----+-----+
-
-## Syntaxe
-
-```C
-int tab[3][4]; // déclaration d'un tableau 4x3
-tab[2][1]; // accès à la case 2, 1
-tab[2][1] = 14; // assignation de 14 à la position 2, 1
-```
-
-# Tableau à deux dimensions (3/4)
-
-## Exercice: déclarer et initialiser aléatoirement un tableau `50x100`
-
-. . .
-
-```C
-#define NX 50
-#define NY 100
-int tab[NX][NY];
-for (int i = 0; i < NX; ++i) {
-    for (int j = 0; j < NY; ++j) {
-        tab[i][j] = rand() % 256; // 256 niveaux de gris
-    }
-}
-```
- 
-## Exercice: afficher le tableau
-
-. . .
-
-```C
-for (int i = 0; i < NX; ++i) {
-    for (int j = 0; j < NY; ++j) {
-        printf("%d ", tab[i][j]);
-    }
-    printf("\n");
-}
-```
-
-# Tableau à deux dimensions (4/4)
-
-## Attention
-
-* Les éléments ne sont **jamais** initialisés.
-* Les bornes ne sont **jamais** vérifiées.
-
-    ```C
-    int tab[3][2] = { {1, 2}, {3, 4}, {5, 6} };
-    printf("%d\n", tab[2][1]);  // affiche?
-    printf("%d\n", tab[10][9]); // affiche?
-    printf("%d\n", tab[3][1]);  // affiche?
-    ```
-    
-# La couverture de la reine
-
-* Aux échecs la reine peut se déplacer horizontalement et verticalement
-* Pour un échiquier `5x6`, elle *couvre* les cases comme ci-dessous
-
-+-----+-----+-----+-----+-----+-----+-----+
-| ` ` | `0` | `1` | `2` | `3` | `4` | `5` |
-+-----+-----+-----+-----+-----+-----+-----+
-| `0` | `*` | ` ` | `*` | ` ` | `*` | ` ` |
-+-----+-----+-----+-----+-----+-----+-----+
-| `1` | ` ` | `*` | `*` | `*` | ` ` | ` ` |
-+-----+-----+-----+-----+-----+-----+-----+
-| `2` | `*` | `*` | `R` | `*` | `*` | `*` |
-+-----+-----+-----+-----+-----+-----+-----+
-| `3` | ` ` | `*` | `*` | `*` | ` ` | ` ` |
-+-----+-----+-----+-----+-----+-----+-----+
-| `4` | `*` | ` ` | `*` | ` ` | `*` | ` ` |
-+-----+-----+-----+-----+-----+-----+-----+
-
-## Exercice
-
-* En utilisant les conditions, les tableaux à deux dimensions, et des
-  `char` uniquement.
-* Implémenter un programme qui demande à l'utilisateur d'entrer les
-  coordonnées de la reine et affiche un tableau comme ci-dessus pour un
-  échiquier `8x8`.
-
-## Poster le résultat sur `Element`
-
-# Types énumérés (1/2)
-
-* Un **type énuméré**: ensemble de *variantes* (valeurs constantes).
-* En `C` les variantes sont des entiers numérotés à partir de 0.
-
-    ```C
-    enum days {
-        monday, tuesday, wednesday,
-        thursday, friday, saturday, sunday
-    };
-    ```
-* On peut aussi donner des valeurs "custom"
-
-    ```C
-    enum days {
-        monday = 2, tuesday = 8, wednesday = -2,
-        thursday = 1, friday = 3, saturday = 12, sunday = 9
-    };
-    ```
-* S'utilise comme un type standard et un entier
-
-    ```C
-    enum days d = monday;
-    (d + 2) == tuesday + tuesday; // true
-    ```
-
-# Types énumérés (2/2)
-
-* Très utile dans les `switch ... case`{.C}
-
-    ```C
-    enum days d = monday;
-    switch (d) {
-        case monday:
-            // trucs
-            break;
-        case tuesday:
-            printf("0 ou 1\n");
-            break;
-    }
-    ```
-* Le compilateur vous prévient qu'il en manque!
-
-# Utilisation des types énumérés
-
-## Réusiner votre couverture de la reine avec des `enum`
-
-# Représentation des nombres (1/2)
-
-* Le nombre `247`.
-
-## Nombres décimaux: Les nombres en base 10 
-
-+--------+--------+--------+
-| $10^2$ | $10^1$ | $10^0$ |
-+--------+--------+--------+
-| `2`    | `4`    | `7`    |
-+--------+--------+--------+
-
-$$
-247 = 2\cdot 10^2 + 4\cdot 10^1 + 7\cdot 10^0.
-$$
-
-# Représentation des nombres (2/2)
-
-* Le nombre `11110111`.
-
-## Nombres binaires: Les nombres en base 2
-
-+-------+-------+-------+-------+-------+-------+-------+-------+
-| $2^7$ | $2^6$ | $2^5$ | $2^4$ | $2^3$ | $2^2$ | $2^1$ | $2^0$ |
-+-------+-------+-------+-------+-------+-------+-------+-------+
-| `1`   | `1`   | `1`   | `1`   | `0`   | `1`   | `1`   | `1`   |
-+-------+-------+-------+-------+-------+-------+-------+-------+
- 
-$$
-1\cdot 2^7 + 1\cdot 2^6 +1\cdot 2^5 +1\cdot 2^4 +0\cdot 2^3 +1\cdot 2^2
-+1\cdot 2^1 +1\cdot 2^0
-$$
-
-. . .
-
-$$
-= 247.
-$$
-
-# Conversion de décimal à binaire (1/2)
-
-## Convertir 11 en binaire?
-
-. . .
-
-* On décompose en puissances de 2 en partant de la plus grande possible
-
-    ```
-    11 / 8 = 1, 11 % 8 = 3
-    3  / 4 = 0,  3 % 4 = 3
-    3  / 2 = 1,  3 % 2 = 1
-    1  / 1 = 1,  1 % 1 = 0
-    ```
-* On a donc
-
-    $$
-    1011 \Rightarrow 1\cdot 2^3 + 0\cdot 2^2 + 1\cdot 2^1 + 1\cdot
-    2^0=11.
-    $$
-
-# Conversion de décimal à binaire (2/2)
-
-## Convertir un nombre arbitraire en binaire: 247?
-
-* Par groupe établir un algorithme.
-
-. . .
-
-## Algorithme
-
-1. Initialisation
-    
-    ```C
-    num = 247
-    while (2^N < num) {
-        N += 1
-    }
-    ```
-
-. . .
-
-2. Boucle
-
-    ```C
-    while (N >= 0) {
-        bit = num / 2^N
-        num = num % 2^N
-        N += 1
-    }
-    ```
-
-# Les additions en binaire
-
-Que donne l'addition `1101` avec `0110`?
-
-* L'addition est la même que dans le système décimal
-
-    ```
-       1101         8+4+0+1 = 13
-    +  0110    +    0+4+2+0 =  6
-    -------    -----------------
-      10011      16+0+0+2+1 = 19
-    ```
-* Les entiers sur un ordinateur ont une précision **fixée** (ici 4 bits).
-* Que se passe-t-il donc ici?
-
-. . .
-
-## Dépassement de capacité: le nombre est "tronqué"
-
-* `10011 (19) -> 0011 (3)`.
-* On fait "le tour"."
-
-# Entier non-signés minimal/maximal
-
-* Quel est l'entier non-signé maximal représentable avec 4 bit?
-
-. . .
-
-$$
-(1111)_2 = 8+4+2+1 = 15
-$$
-
-* Quel est l'entier non-signé minimal représentable avec 4 bit?
-
-. . .
-
-$$
-(0000)_2 = 0+0+0+0 = 0
-$$
-
-* Quel est l'entier non-signé min/max représentable avec N bit?
-
-. . .
-
-$$
-0\mbox{ et  }2^N-1.
-$$
-
-* Donc `uint32_t?` maximal est?
-
-. . .
-
-$$
-4294967295
-$$
-
-
-# Les multiplications en binaire (1/2)
-
-Que donne la multiplication de `1101` avec `0110`?
-
-* L'addition est la même que dans le système décimal
-
-    ```
-         1101                13
-    *    0110    *            6
-    ---------    --------------
-         0000                78
-        11010
-       110100
-    + 0000000
-    ---------    --------------
-      1001110    64+0+0+8+4+2+0
-    ```
-
-# Les multiplications en binaire (2/2)
-
-## Que fait la multiplication par 2?
-
-. . .
-
-* Décalage de un bit vers la gauche!
-
-    ```
-         0110
-    *    0010
-    ---------
-         0000
-    +   01100
-    ---------
-        01100
-    ```
-
-. . .
-
-## Que fait la multiplication par $2^N$?
-
-. . .
-
-* Décalade de $N$ bits vers la gauche!
-
-# Entiers signés (1/2)
-
-Pas de nombres négatifs encore...
-
-## Comment faire?
-
-. . .
-
-## Solution naïve:
-
-* On ajoute un bit de signe (le bit de poids fort):
-
-    ```
-    00000010: +2
-    10000010: -2
-    ```
-
-## Problèmes?
-
-. . .
-
-* Il y a deux zéros (pas trop grave): `10000000` et `00000000`
-* Les additions différentes que pour les non-signés (très grave)
-    
-    ```
-      00000010              2    
-    + 10000100           + -4
-    ----------           ----
-      10000110 = -6  !=    -2
-    ```
-
-# Entiers signés (2/2)
-
-## Beaucoup mieux
-
-* Complément à un:
-    * on inverse tous les bits: `1001 => 0110`.
-
-## Encore un peu mieux
-
-* Complément à deux:
-    * on inverse tous les bits,
-    * on ajoute 1 (on ignore les dépassements).
-
-. . .
-
-* Comment écrit-on `-4` en 8 bits?
-
-. . .
-
-```
-     4 =  00000100
-            ________
-    -4 =>   00000100
-            
-            11111011
-          + 00000001 
-          ----------
-            11111100
-```
-
-# Le complément à 2 (1/2)
-
-## Questions:
-
-* Comment on écrit `+0` et `-0`?
-* Comment calcule-t-on `2 + (-4)`?
-* Quel est le complément à 2 de `1000 0000`?
-
-. . .
-
-## Réponses
-
-* Comment on écrit `+0` et `-0`?
-
-    ```
-    +0 = 00000000
-    -0 = 11111111 + 00000001 = 100000000 => 00000000 
-    ```
-* Comment calcule-t-on `2 + (-4)`?
-
-    ```
-      00000010            2
-    + 11111100        +  -4
-    ----------        -----
-      11111110           -2
-    ```
-* En effet
-
-    ```
-    11111110 => 00000001 + 00000001 = 00000010 = 2.
-    ```
-
-# Le complément à 2 (1/2)
-
-## Quels sont les entiers représentables en 8 bits?
-
-. . .
-
-```
-01111111 =>  127
-10000000 => -128 // par définition
-```
-
-## Quels sont les entiers représentables sur $N$ bits?
-
-. . .
-
-$$
--2^{N-1} ... 2^{N-1}-1.
-$$
-
-## Remarque: dépassement de capacité en `C`
-
-* Comportement indéfini!
-
-
-<!-- # TODO --
-
-<!-- ## Entiers, entiers non-signés -->
-
-<!-- ## Complément à 1, 2 -->
-
-<!-- ## Nombres à virgule flottante, simple/double précision -->
-
-# Types composés: `struct`{.C} (1/6)
-
-## Fractions
-
-* Numérateur: `int num`;
-* Dénominateur: `int denom`.
-
-## Addition
-
-```C
-int num1 = 1, denom1 = 2;
-int num2 = 1, denom2 = 3;
-int num3 = num1 * denom2 + num2 * denom1;
-int denom3 = denom1 * denom2;
-```
-
-## Pas super pratique....
-
-# Types composés: `struct`{.C} (2/6)
-
-## On peut faire mieux
-
-* Plusieurs variables qu'on aimerait regrouper dans un seul type: `struct`{.C}.
-
-```C
-struct fraction { // déclaration du type
-    int32_t num, denom;
-}
-
-struct fraction frac; // déclaration de frac
-```
-
-# Types composés: `struct`{.C} (3/6)
-
-## Simplifications
-
-- `typedef`{.C} permet de définir un nouveau type.
-
-    ```C
-    typedef unsinged int uint;
-    typedef struct fraction fraction_t;
-    typedef struct fraction {
-        int32_t num, denom;
-    } fraction_t;
-    ```
-- L'initialisation peut aussi se faire avec
-
-    ```C
-    fraction_t frac = {1, -2}; // num = 1, denom = -2
-    fraction_t frac = {.denom = 1, .num = -2};
-    fraction_t frac = {.denom = 1}; // argl! .num non initialisé 
-    fraction_t frac2 = frac; // copie
-    ```
-
-# Types composés: `struct`{.C} (4/6)
-
-## Pointeurs
-
-- Comme pour tout type, on peut avoir des pointeurs vers un `struct`{.C}.
-- Les champs sont accessible avec le sélecteur `->`{.C}
-
-    ```C
-    fraction_t *frac; // on crée un pointeur
-    frac->num = 1;    // seg fault...
-    frac->denom = -1; // mémoire pas allouée.
-    ```
-
-![La représentation mémoire de
-`fraction_t`.](figs/pointer_struct.svg){width=50%}
-
-# Types composés: `struct`{.C} (5/6)
-
-## Initialisation
-
-- Avec le passage par **référence** on peut modifier un struct *en place*.
-- Les champs sont accessible avec le sélecteur `->`{.C}
-
-    ```C
-    void fraction_init(fraction_t *frac, 
-                      int32_t re, int32_t im) 
-    {
-        // frac a déjà été allouée
-        frac->num   = frac;
-        frac->denom = denom;
-    }
-    int main() {
-        fraction_t frac; // on alloue une fraction
-        fraction_init(&frac, 2, -1); // on l'initialise
-    }
-    ```
-
-# Types composés: `struct`{.C} (6/6)
-
-## Initialisation version copie
-
-* On peut allouer une fraction, l'initialiser et le retourner.
-* La valeur retournée peut être copiée dans une nouvelle structure.
-
-    ```C
-    fraction_t fraction_create(int32_t re, int32_t im) {
-        fraction_t frac;
-        frac.num = re;
-        frac.denom = im;
-        return frac;
-    }
-    int main() {
-        // on crée une fraction et on l'initialise
-        // en copiant la fraction créé par fraction_create
-        // deux allocation et une copie
-        fraction_t frac = fraction_create(2, -1); 
-    }
-    ```
-
-<!-- # TODO jusqu'aux vacances -->
-
-<!-- * Refactorisation -->
-<!-- * Tris et complexité -->
-<!-- * Récursivité -->
diff --git a/slides/cours_5.md b/slides/cours_5.md
deleted file mode 100644
index da21610..0000000
--- a/slides/cours_5.md
+++ /dev/null
@@ -1,834 +0,0 @@
----
-title: "Représentation des nombres et récursivité"
-date: "2022-11-02"
----
-
-# Types énumérés (1/2)
-
-* Un **type énuméré**: ensemble de *variantes* (valeurs constantes).
-* En `C` les variantes sont des entiers numérotés à partir de 0.
-
-    ```C
-    enum days {
-        monday, tuesday, wednesday,
-        thursday, friday, saturday, sunday
-    };
-    ```
-* On peut aussi donner des valeurs "custom"
-
-    ```C
-    enum days {
-        monday = 2, tuesday = 8, wednesday = -2,
-        thursday = 1, friday = 3, saturday = 12, sunday = 9
-    };
-    ```
-* S'utilise comme un type standard et un entier
-
-    ```C
-    enum days d = monday;
-    (d + 2) == monday + monday; // true
-    ```
-
-# Types énumérés (2/2)
-
-* Très utile dans les `switch ... case`{.C}
-
-    ```C
-    enum days d = monday;
-    switch (d) {
-        case monday:
-            // trucs
-            break;
-        case tuesday:
-            printf("0 ou 1\n");
-            break;
-    }
-    ```
-* Le compilateur vous prévient qu'il en manque!
-
-# Utilisation des types énumérés
-
-## Réusiner votre couverture de la reine avec des `enum`
-
-A faire à la maison comme exercice!
-
-# Représentation des nombres (1/2)
-
-* Le nombre `247`.
-
-## Nombres décimaux: Les nombres en base 10 
-
-+--------+--------+--------+
-| $10^2$ | $10^1$ | $10^0$ |
-+--------+--------+--------+
-| `2`    | `4`    | `7`    |
-+--------+--------+--------+
-
-$$
-247 = 2\cdot 10^2 + 4\cdot 10^1 + 7\cdot 10^0.
-$$
-
-# Représentation des nombres (2/2)
-
-* Le nombre `11110111`.
-
-## Nombres binaires: Les nombres en base 2
-
-+-------+-------+-------+-------+-------+-------+-------+-------+
-| $2^7$ | $2^6$ | $2^5$ | $2^4$ | $2^3$ | $2^2$ | $2^1$ | $2^0$ |
-+-------+-------+-------+-------+-------+-------+-------+-------+
-| `1`   | `1`   | `1`   | `1`   | `0`   | `1`   | `1`   | `1`   |
-+-------+-------+-------+-------+-------+-------+-------+-------+
- 
-$$
-1\cdot 2^7 + 1\cdot 2^6 +1\cdot 2^5 +1\cdot 2^4 +0\cdot 2^3 +1\cdot 2^2
-+1\cdot 2^1 +1\cdot 2^0
-$$
-
-. . .
-
-$$
-= 247.
-$$
-
-# Conversion de décimal à binaire (1/2)
-
-## Convertir 11 en binaire?
-
-. . .
-
-* On décompose en puissances de 2 en partant de la plus grande possible
-
-    ```
-    11 / 8 = 1, 11 % 8 = 3
-    3  / 4 = 0,  3 % 4 = 3
-    3  / 2 = 1,  3 % 2 = 1
-    1  / 1 = 1,  1 % 1 = 0
-    ```
-* On a donc
-
-    $$
-    1011 \Rightarrow 1\cdot 2^3 + 0\cdot 2^2 + 1\cdot 2^1 + 1\cdot
-    2^0=11.
-    $$
-
-# Conversion de décimal à binaire (2/2)
-
-## Convertir un nombre arbitraire en binaire: 247?
-
-* Par groupe établir un algorithme.
-
-. . .
-
-## Algorithme
-
-1. Initialisation
-    
-    ```C
-    num = 247
-    tant que (2^N < num) {
-        N += 1
-    }
-    ```
-
-. . .
-
-2. Boucle
-
-    ```C
-    tant que (N >= 0) {
-        bit = num / 2^N
-        num = num % 2^N
-        N -= 1
-    }
-    ```
-
-# Les additions en binaire
-
-Que donne l'addition `1101` avec `0110`?
-
-* L'addition est la même que dans le système décimal
-
-    ```
-       1101         8+4+0+1 = 13
-    +  0110    +    0+4+2+0 =  6
-    -------    -----------------
-      10011      16+0+0+2+1 = 19
-    ```
-* Les entiers sur un ordinateur ont une précision **fixée** (ici 4 bits).
-* Que se passe-t-il donc ici?
-
-. . .
-
-## Dépassement de capacité: le nombre est "tronqué"
-
-* `10011 (19) -> 0011 (3)`.
-* On fait "le tour"."
-
-# Entier non-signés minimal/maximal
-
-* Quel est l'entier non-signé maximal représentable avec 4 bit?
-
-. . .
-
-$$
-(1111)_2 = 8+4+2+1 = 15
-$$
-
-* Quel est l'entier non-signé minimal représentable avec 4 bit?
-
-. . .
-
-$$
-(0000)_2 = 0+0+0+0 = 0
-$$
-
-* Quel est l'entier non-signé min/max représentable avec N bit?
-
-. . .
-
-$$
-0\mbox{ et  }2^N-1.
-$$
-
-* Donc `uint32_t?` maximal est?
-
-. . .
-
-$$
-2^{32}-1=4'294'967'295
-$$
-
-
-# Les multiplications en binaire (1/2)
-
-Que donne la multiplication de `1101` avec `0110`?
-
-* La mutliplication est la même que dans le système décimal
-
-    ```
-         1101                13
-    *    0110    *            6
-    ---------    --------------
-         0000                78
-        11010
-       110100
-    + 0000000
-    ---------    --------------
-      1001110    64+0+0+8+4+2+0
-    ```
-
-# Les multiplications en binaire (2/2)
-
-## Que fait la multiplication par 2?
-
-. . .
-
-* Décalage de un bit vers la gauche!
-
-    ```
-         0110
-    *    0010
-    ---------
-         0000
-    +   01100
-    ---------
-        01100
-    ```
-
-. . .
-
-## Que fait la multiplication par $2^N$?
-
-. . .
-
-* Décalade de $N$ bits vers la gauche!
-
-# Entiers signés (1/2)
-
-Pas de nombres négatifs encore...
-
-## Comment faire?
-
-. . .
-
-## Solution naïve:
-
-* On ajoute un bit de signe (le bit de poids fort):
-
-    ```
-    00000010: +2
-    10000010: -2
-    ```
-
-## Problèmes?
-
-. . .
-
-* Il y a deux zéros (pas trop grave): `10000000` et `00000000`
-* Les additions différentes que pour les non-signés (très grave)
-    
-    ```
-      00000010              2    
-    + 10000100           + -4
-    ----------           ----
-      10000110 = -6  !=    -2
-    ```
-
-# Entiers signés (2/2)
-
-## Beaucoup mieux
-
-* Complément à un:
-    * on inverse tous les bits: `1001 => 0110`.
-
-## Encore un peu mieux
-
-* Complément à deux:
-    * on inverse tous les bits,
-    * on ajoute 1 (on ignore les dépassements).
-
-. . .
-
-* Comment écrit-on `-4` en 8 bits?
-
-. . .
-
-```
-     4 =  00000100
-            ________
-    -4 =>   00000100
-            
-            11111011
-          + 00000001 
-          ----------
-            11111100
-```
-
-# Le complément à 2 (1/2)
-
-## Questions:
-
-* Comment on écrit `+0` et `-0`?
-* Comment calcule-t-on `2 + (-4)`?
-* Quel est le complément à 2 de `1000 0000`?
-
-. . .
-
-## Réponses
-
-* Comment on écrit `+0` et `-0`?
-
-    ```
-    +0 = 00000000
-    -0 = 11111111 + 00000001 = 100000000 => 00000000 
-    ```
-* Comment calcule-t-on `2 + (-4)`?
-
-    ```
-      00000010            2
-    + 11111100        +  -4
-    ----------        -----
-      11111110           -2
-    ```
-* En effet
-
-    ```
-    11111110 => 00000001 + 00000001 = 00000010 = 2.
-    ```
-
-# Le complément à 2 (2/2)
-
-## Quels sont les entiers représentables en 8 bits?
-
-. . .
-
-```
-01111111 =>  127
-10000000 => -128 // par définition
-```
-
-## Quels sont les entiers représentables sur $N$ bits?
-
-. . .
-
-$$
--2^{N-1} ... 2^{N-1}-1.
-$$
-
-## Remarque: dépassement de capacité en `C`
-
-* 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#/media/File:Float_example.svg)](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#/media/File:Float_example.svg)](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
deleted file mode 100644
index fcb044d..0000000
--- a/slides/cours_6.md
+++ /dev/null
@@ -1,488 +0,0 @@
----
-title: "Récursivité et complexité"
-date: "2022-11-09"
----
-
-# La récursivité (1/2)
-
-* Code récursif
-
-    ```C
-    int factorial(int n) {
-        if (n > 1) { // Condition de récursivité
-            return n * factorial(n - 1);
-        } else {     // Condition d'arrêt
-            return 1;
-        }
-    }
-```
-
-. . .
-
-* Code impératif
-
-    ```C
-    int factorial(int n) {
-        int f = 1;
-        for (int i = 1; i < n; ++i) {
-            f *= i;
-        }
-        return f;
-    }
-    ```
-
-# 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).
-$$
-
-
diff --git a/slides/cours_7.md b/slides/cours_7.md
deleted file mode 100644
index 1ee5638..0000000
--- a/slides/cours_7.md
+++ /dev/null
@@ -1,295 +0,0 @@
----
-title: "Tris"
-date: "2022-11-16"
----
-
-# Rappel: Complexité
-
-\footnotesize
-
-Soit `tab` un tableau de longueur `N` de `double`.
-
-1. Comment déclare-t-on un tel tableau?
-
-. . .
-
-```C
-double tab[N];
-```
-
-2. Quelle est la complexité du calcul de la moyenne de `tab`?
-
-. . .
-
-```C
-double mean = 0.0;
-for (int i = 0; i < N; ++i) { // N assignations
-    mean += tab[i];        // N additions
-}
-mean /= N; // O(N)
-```
-
-. . .
-
-3. Quelle est la complexité du calcul de l'écart type de `tab` ($\sigma=\sqrt{\sum_i (t_i - m)^2}/N$?
-
-. . .
-
-```C
-double mean = moyenne(N, tab); // O(N)
-double dev = 0.0;
-for (int i = 0; i < N; ++i) {
-    dev += pow(tab[i] - moyenne, 2); // N tours
-}
-dev = sqrt(dev); dev /= N; // O(2*N) = O(N)
-```
-
-# Tri par insertion (1/3)
-
-## But
-
-* trier un tableau par ordre croissant
-
-## Algorithme
-
-Prendre un élément du tableau et le mettre à sa place parmis les éléments déjà
-triés du tableau.
-
-![Tri par insertion d'un tableau d'entiers](figs/tri_insertion.svg)
-
-# Tri par insertion (2/3)
-
-## Exercice: Proposer un algorithme (en C)
-
-. . .
-
-```C
-void tri_insertion(int N, int tab[N]) {
-    for (int i = 1; i < N; i++) {
-        int tmp = tab[i];
-        int pos = i;
-        while (pos > 0 && tab[pos - 1] > tmp) {
-            tab[pos] = tab[pos - 1];
-            pos      = pos - 1;
-        }
-        tab[pos] = tmp;
-    }
-}
-```
-
-# Tri par insertion (3/3)
-
-## Question: Quelle est la complexité?
-
-. . .
-
-* Parcours de tous les éléments ($N-1$ passages dans la boucle)
-    * Placer: en moyenne $i$ comparaisons et affectations à l'étape $i$
-* Moyenne: $\mathcal{O}(N^2)$
-
-. . .
-
-* Pire des cas, liste triée à l'envers: $\mathcal{O}(N^2)$
-* Meilleurs des cas, liste déjà triée: $\mathcal{O}(N)$
-
-# L'algorithme à la main
-
-## Exercice *sur papier*
-
-* Trier par insertion le tableau `[5, -2, 1, 3, 10]`
-
-```C
-
-
-
-
-
-
-
-
-
-
-
-
-
-```
-
-# Tri rapide ou quicksort (1/8)
-
-## Idée: algorithme `diviser pour régner` (`divide-and-conquer`)
-
-* Diviser: découper un problème en sous problèmes;
-* Régner: résoudre les sous-problèmes (souvent récursivement);
-* Combiner: à partir des sous problèmes résolu, calculer la solution.
-
-## Le pivot
-
-* Trouver le **pivot**, un élément qui divise le tableau en 2, tels que:
-    1. Éléments à gauche sont **plus petits** que le pivot.
-    2. Élements à droite sont **plus grands** que le pivot.
-
-# Tri rapide ou quicksort (2/8)
-
-## Algorithme `quicksort(tableau)`
-
-1. Choisir le pivot et l'amener à sa place:
-    * Les éléments à gauche sont plus petits que le pivot.
-    * Les éléments à droite sont plus grand que le pivot.
-2. `quicksort(tableau_gauche)` en omettant le pivot.
-3. `quicksort(tableau_droite)` en omettant le pivot.
-4. S'il y a moins de deux éléments dans le tableau, le tableau est trié.
-
-. . .
-
-Compris?
-
-. . .
-
-Non c'est normal, faisons un exemple.
-
-# Tri rapide ou quicksort (3/8)
-
-\footnotesize
-
-Deux variables sont primordiales:
-
-```C
-entier ind_min, ind_max; // les indices min/max des tableaux à trier
-```
-
-![Un exemple de quicksort.](figs/quicksort.svg)
-
-# Tri rapide ou quicksort (4/8)
-
-\footnotesize
-
-Deux variables sont primordiales:
-
-```C
-entier ind_min, ind_max; // les indices min/max des tableaux à trier
-```
-
-## Pseudocode: quicksort
-
-```python
-rien quicksort(entier tableau[], entier ind_min, entier ind_max)
-    si (longueur(tab) > 1)
-        ind_pivot = partition(tableau, ind_min, ind_max)
-        si (longueur(tableau[ind_min:ind_pivot-1]) != 0)
-            quicksort(tableau, ind_min, pivot_ind - 1)
-        si (longueur(tableau[ind_pivot+1:ind_max-1]) != 0)
-            quicksort(tableau, ind_pivot + 1, ind_max)
-```
-
-# Tri rapide ou quicksort (5/8)
-
-\footnotesize
-
-## Pseudocode: partition
-
-```C
-entier partition(entier tableau[], entier ind_min, entier ind_max)
-    pivot = tableau[ind_max] // choix arbitraire
-    i = ind_min
-    j = ind_max-1
-    tant que i < j:
-        en remontant i trouver le premier élément > pivot
-        en descendant j trouver le premier élément < pivot
-        échanger(tableau[i], tableau[j])
-        // les plus grands à droite
-        // mettre les plus petits à gauche
-    
-    // on met le pivot "au milieu"
-    échanger(tableau[i], tableau[ind_max])    
-    retourne i // on retourne l'indice pivot
-```
-
-# Tri rapide ou quicksort (6/8)
-
-## Exercice: implémenter les fonctions `quicksort` et `partition`
-
-. . .
-
-```C
-void quicksort(int size, int array[size], int first, 
-               int last) 
-{
-    if (first < last) {
-        int midpoint = partition(size, array, first, last);
-        if (first < midpoint - 1) {
-            quicksort(size, array, first, midpoint - 1);
-        }
-        if (midpoint + 1 < last) {
-            quicksort(size, array, midpoint + 1, last);
-        }
-    }
-}
-```
-
-
-# Tri rapide ou quicksort (7/8)
-
-\footnotesize
-
-## Exercice: implémenter les fonctions `quicksort` et `partition`
-
-```C 
-int partition(int size, int array[size], int first, int last) {
-    int pivot = array[last];
-    int i = first - 1, j = last;
-    do {
-        do {
-            i += 1;
-        } while (array[i] < pivot && i < j);
-        do {
-            j -= 1;
-        } while (array[j] > pivot && i < j);
-        if (j > i) {
-            swap(&array[i], &array[j]);
-        }
-    } while (j > i);
-    swap(&array[i], &array[last]);
-    return i;
-}
-```
-
-# Tri rapide ou quicksort (8/8)
-
-## Quelle est la complexité du tri rapide?
-
-. . .
-
-* Pire des cas plus: $\mathcal{O}(N^2)$
-    * Quand le pivot sépare toujours le tableau de façon déséquilibrée ($N-1$
-      éléments d'un côté $1$ de l'autre).
-    * $N$ boucles et $N$ comparaisons $\Rightarrow N^2$.
-* Meilleur des cas (toujours le meilleur pivot): $\mathcal{O}(N\cdot \log_2(N))$.
-    * Chaque fois le tableau est séparé en $2$ parties égales.
-    * On a $\log_2(N)$ partitions, et $N$ boucles $\Rightarrow N\cdot
-      \log_2(N)$.
-* En moyenne: $\mathcal{O}(N\cdot \log_2(N))$.
-
-# L'algorithme à la main
-
-## Exercice *sur papier*
-
-* Trier par tri rapide le tableau `[5, -2, 1, 3, 10, 15, 7, 4]`
-
-```C
-
-
-
-
-
-
-
-
-
-
-
-
-
-```
-
-
-
diff --git a/slides/cours_8.md b/slides/cours_8.md
deleted file mode 100644
index 2cfa2a3..0000000
--- a/slides/cours_8.md
+++ /dev/null
@@ -1,281 +0,0 @@
----
-title: "Backtracking et piles"
-date: "2022-11-23"
----
-
-# Tri à bulle (1/4)
-
-## Algorithme
-
-* Parcours du tableau et comparaison des éléments consécutifs:
-    - Si deux éléments consécutifs ne sont pas dans l'ordre, ils sont échangés.
-* On recommence depuis le début du tableau jusqu'à avoir plus d'échanges à
-  faire.
-
-## Que peut-on dire sur le dernier élément du tableau après un parcours?
-
-. . .
-
-* Le plus grand élément est **à la fin** du tableau.
-    * Plus besoin de le traiter.
-* A chaque parcours on s'arrête un élément plus tôt.
-
-# Tri à bulle (2/4)
-
-## Exemple
-
-![Tri à bulles d'un tableau d'entiers](figs/tri_bulles.svg)
-
-
-# Tri à bulle (3/4)
-
-## Exercice: écrire l'algorithme (poster le résultat sur matrix)
-
-. . .
-
-```C
-rien tri_a_bulles(entier tableau[])
-    pour i de longueur(tableau)-1 à 1:
-        trié = vrai
-        pour j de 0 à i-1:
-            si (tableau[j] > tableau[j+1])
-                échanger(array[j], array[j+1])
-                trié = faux
-        
-        si trié
-            retourner
-```
-
-# Tri à bulle (4/4)
-
-## Quelle est la complexité du tri à bulles?
-
-. . .
-
-* Dans le meilleurs des cas:
-    * Le tableau est déjà trié: $\mathcal{O}(N)$ comparaisons.
-* Dans le pire des cas, $N\cdot (N-1)/2\sim\mathcal{O}(N^2)$:
-$$
-\sum_{i=1}^{N-1}i\mbox{ comparaison et }3\sum_{i=1}^{N-1}i \mbox{ affectations
-(swap)}\Rightarrow \mathcal{O}(N^2).
-$$
-* En moyenne, $\mathcal{O}(N^2)$ ($N^2/2$ comparaisons).
-
-# L'algorithme à la main
-
-## Exercice *sur papier*
-
-* Trier par tri à bulles le tableau `[5, -2, 1, 3, 10, 15, 7, 4]`
-
-```C
-
-
-
-
-
-
-
-
-
-
-
-
-
-```
-
-
-# Problème des 8-reines
-
-* Placer 8 reines sur un échiquier de $8 \times 8$.
-* Sans que les reines ne puissent se menacer mutuellement (92 solutions). 
-
-## Conséquence
-
-* Deux reines ne partagent pas la même rangée, colonne, ou diagonale.
-* Donc chaque solution a **une** reine **par colonne** ou **ligne**.
-
-## Généralisation
-
-* Placer $N$ reines sur un échiquier de $N \times
-  N$. 
-- Exemple de **backtracking** (retour en arrière) $\Rightarrow$ récursivité.
-
-![Problème des 8-reines. Source:
-[wikipedia](https://fr.wikipedia.org/wiki/Problème_des_huit_dames)](./figs/fig_recursivite_8_reines.png){width=35%}
-
-# Problème des 2-reines
-
-![Le problème des 2 reines n'a pas de solution.](figs/2reines.svg){width=50%}
-
-# Comment trouver les solutions?
-
-* On pose la première reine sur la première case disponible.
-* On rend inaccessibles toutes les cases menacées.
-* On pose la reine suivante sur la prochaine case non-menacée.
-* Jusqu'à ce qu'on puisse plus poser de reine.
-* On revient alors en arrière jusqu'au dernier coup où il y avait plus qu'une
-  possibilité de poser une reine.
-* On recommence depuis là.
-
-. . .
-
-* Le jeu prend fin quand on a énuméré *toutes* les possibilités de poser les
-  reines.
-
-# Problème des 3-reines
-
-![Le problème des 3 reines n'a pas de solution non plus.](figs/3reines.svg)
-
-# Problème des 4-reines
-
-![Le problème des 4 reines a une solution.](figs/4reines.svg)
-
-# Problème des 4-reines, symétrie
-
-![Le problème des 4 reines a une autre solution (symétrie
-horizontale).](figs/4reines_sym.svg)
-
-# Problème des 5 reines
-
-## Exercice: Trouver une solution au problème des 5 reines
-
-* Faire une capture d'écran / une photo de votre solution et la poster sur
-  matrix.
-
-```C
-
-
-
-
-
-
-
-
-
-
-
-
-
-```
-
-# Quelques observations sur le problème
-
-* Une reine par colonne au plus.
-* On place les reines sur des colonnes successives.
-* On a pas besoin de "regarder en arrière" (on place "devant" uniquement).
-* Trois étapes:
-    * On place une reine dans une case libre.
-    * On met à jour le tableau.
-    * Quand on a plus de cases libres on "revient dans le temps" ou c'est qu'on
-      a réussi.
-
-# Le code du problème des 8 reines (1/N)
-
-## Quelle structure de données?
-
-. . .
-
-Une matrice de booléens fera l'affaire:
-
-```C
-bool board[n][n];
-```
-
-## Quelles fonctionnalités?
-
-. . .
-
-```C
-// Pour chaque ligne placer la reine sur toutes les colonnes
-//    et compter les solutions
-void nbr_solutions(board, column, counter);
-// Copier un tableau dans un autre
-void copy(board_in, board_out);
-// Placer la reine à li, co et rendre inaccessible devant
-void placer_devant(board, li, co);
-```
-
-# Le code du problème des 8 reines (2/N)
-
-## Le calcul du nombre de solutions
-
-```C
-// Calcule le nombre de solutions au problème des <n> reines
-nbr_solutions(board, column, count)
-   // pour chaque ligne 
-       // si la case libre
-          // si column < n - 1
-              // copier board dans un "new" board, 
-              //   y poser une reine
-              //   et mettre à jour ce "new" board
-              // nbr_solutions(new_board, column+1, count)
-          // sinon
-              // on a posé la n-ème et on a gagné
-              // count += 1
-```
-
-# Le code du problème des 8 reines (3/N)
-
-## Le calcul du nombre de solutions
-
-```C
-// Placer une reine et mettre à jour
-placer_devant(board, ligne, colonne)
-    // board est occupé à ligne/colonne
-        // toutes les cases des colonnes
-        //    suivantes sont mises à jour
-```
-
-# Le code du problème des 8 reines (4/N)
-
-## Compris? Alors écrivez le code et postez le!
-
-. . .
-
-## Le nombre de solutions
-
-\footnotesize
-
-```C
-// Calcule le nombre de solutions au problème des <n> reines
-void nb_sol(int n, bool board[n][n], int co, int *ptr_cpt) {
-    for (int li = 0; li < n; li++) {
-        if (board[li][co]) {
-            if (co < n-1) {
-                bool new_board[n][n]; // alloué à chaque nouvelle tentative
-                copy(n, board, new_board);         
-                prises_devant(n, new_board, li, co);
-                nb_sol(n, new_board, co+1, ptr_cpt);
-            } else {
-                *ptr_cpt = (*ptr_cpt)+1;
-            }
-        }
-    }
-}
-```
-
-
-# Le code du problème des 8 reines (5/N)
-
-\footnotesize
-
-## Placer devant
-
-```C
-// Retourne une copie du tableau <board> complété avec les positions
-// prises sur la droite droite par une reine placée en <board(li,co)>
-void prises_devant(int n, bool board[n][n], int li, int co) {
-    board[li][co] = false; // position de la reine
-    for (int j = 1; j < n-co; j++) {
-        // horizontale et diagonales à droite de la reine
-        if (j <= li) {
-            board[li-j][co+j] = false;
-        }
-        board[li][co+j] = false;
-        if (li+j < n) {
-            board[li+j][co+j] = false;
-        }
-    }
-}
-```
-
diff --git a/slides/cours_9.md b/slides/cours_9.md
deleted file mode 100644
index d3b4a02..0000000
--- a/slides/cours_9.md
+++ /dev/null
@@ -1,304 +0,0 @@
----
-title: "Piles"
-date: "2022-12-07"
----
-
-# Les piles (1/5)
-
-## Qu'est-ce donc?
-
-* Structure de données abstraite...
-
-. . .
-
-* de type `LIFO` (*Last in first out*).
-
-![Une pile où on ajoute A, puis B avant de les retirer. Source:
-[Wikipedia](https://upload.wikimedia.org/wikipedia/commons/e/e1/Stack_%28data_structure%29_LIFO.svg)](figs/Stack.svg){width=70%}
-
-## Des exemples de la vraie vie
-
-. . .
-
-* Pile d'assiettes, de livres, ...
-* Adresses visitées par un navigateur web.
-* Les calculatrices du passé (en polonaise inverse).
-* Les boutons *undo* de vos éditeurs de texte (aka *u* dans vim).
-
-# Les piles (2/5)
-
-## Fonctionnalités
-
-. . .
-
-1. Empiler (push): ajouter un élément sur la pile.
-2. Dépiler (pop): retirer l'élément du sommet de la pile et le retrouner.
-3. Liste vide? (is_empty?).
-
-. . .
-
-4. Jeter un oeil (peek): retourner l'élément du sommet de la pile (sans le dépiler).
-5. Nombre d'éléments (length).
-
-## Comment faire les 4,5 à partir de 1 à 3?
-
-. . .
-
-4. Dépiler l'élément, le copier, puis l'empiler à nouveau.
-5. Dépiler jusqu'à ce que la pile soit vide, puis empiler à nouveau.
-
-. . .
-
-## Existe en deux goûts
-
-* Pile avec ou sans limite de capacité (à concurrence de la taille de la
-mémoire).
-
-# Les piles (3/5)
-
-## Implémentation
-
-* Jusqu'ici on n'a pas du tout parlé d'implémentation (d'où le nom de structure
-  abstraite).
-* Pas de choix unique d'implémentation.
-
-## Quelle structure de données allons nous utiliser?
-
-. . .
-
-Et oui vous avez deviné: un tableau!
-
-## La structure: de quoi avons-nous besoin (pile de taille fixe)?
-
-. . .
-
-```C
-#define MAX_CAPACITY 500
-typedef struct _stack {
-    int data[MAX_CAPACITY]; // les données
-    int top;                // indice du sommet
-} stack;
-```
-
-# Les piles (4/5)
-
-## Initialisation
-
-. . .
-
-```C
-void stack_init(stack *s) {
-    s->top = -1;
-}
-```
-
-## Est vide?
-
-. . .
-
-```C
-bool stack_is_empty(stack s) {
-    return s.top == -1;
-} 
-```
-
-## Empiler (ajouter un élément au sommet)
-
-. . .
-
-```C
-void stack_push(stack *s, int val) {
-    s->top += 1;
-    s->data[s->top] = val;
-}
-```
-
-# Les piles (5/5)
-
-## Dépiler (enlever l'élément du sommet)
-
-. . .
-
-```C
-int stack_pop(stack *s) {
-    s->top -= 1;
-    return s->data[s->top+1];
-}
-```
-
-## Jeter un oeil (regarder le sommet)
-
-. . .
-
-```C
-int stack_peek(stack *s) {
-    return s->data[s->top];
-}
-```
-
-## Quelle est la complexité de ces opérations?
-
-. . .
-
-## Voyez-vous des problèmes potentiels avec cette implémentation?
-
-. . .
-
-* Empiler avec une pile pleine.
-* Dépiler avec une pile vide.
-* Jeter un oeil au sommet d'une pile vide.
-
-# Gestion d'erreur, level 0
-
-* Il y a plusieurs façon de traiter les erreur:
-    * Ne rien faire (laisser la responsabilité à l'utilisateur).
-    * Faire paniquer le programme (il plante plus ou moins violemment).
-    * Utiliser des codes d'erreurs.
-
-## La panique
-
-* En C, on a les `assert()` pour faire paniquer un programme.
-
-
-# Assertions (1/3)
-
-```C
-#include <assert.h>
-void assert(int expression);
-```
-
-## Qu'est-ce donc?
-
-- Macro permettant de tester une condition lors de l'exécution d'un programme:
-  - Si `expression == 0`{.C} (condition fausse), `assert()`{.C} affiche un message d'erreur sur `stderr`{.C} et termine l'exécution du programme.
-  - Sinon l'exécution se poursuit normalement.
-  - Peuvent être désactivés à la compilation avec `-DNDEBUG` (équivalent à `#define
-    NDEBUG`)
-
-## À quoi ça sert?
-
-- Permet de réaliser des tests unitaires.
-- Permet de tester des conditions catastrophiques d'un programme.
-- **Ne permet pas** de gérer les erreurs.
-
-# Assertions (2/3)
-
-<!-- \footnotesize -->
-
-## Exemple
-
-```C
-#include <assert.h>
-void stack_push(stack *s, int val) {
-    assert(s->top < MAX_CAPACITY-1);
-    s->top += 1;
-    s->data[s->top] = val;
-}
-int stack_pop(stack *s) {
-    assert(s->top >= 0);
-    s->top -= 1;
-    return s->data[s->top+1];
-}
-int stack_peek(stack *s) {
-    assert(s->top >= 0);
-    return s->data[s->top];
-}
-```
-
-# Assertions (3/3)
-
-## Cas typiques d'utilisation
-
-- Vérification de la validité des pointeurs (typiquement `!= NULL`{.C}).
-- Vérification du domaine des indices (dépassement de tableau).
-
-## Bug vs. erreur de *runtime*
-
-- Les assertions sont là pour détecter les bugs (erreurs d'implémentation).
-- Les assertions ne sont pas là pour gérer les problèmes externes au programme (allocation mémoire qui échoue, mauvais paramètre d'entrée passé par l'utilisateur, ...).
-
-. . .
-
-- Mais peuvent être pratiques quand même pour ça...
-- Typiquement désactivées dans le code de production.
-
-# La pile dynamique
-
-## Comment modifier le code précédent pour avoir une taille dynamique?
-
-. . .
-
-```C
-// alloue une zone mémoire de size octets
-void *malloc(size_t size); 
-// change la taille allouée à size octets (contiguïté garantie)
-void *realloc(void *ptr, size_t size);
-```
-
-## Et maintenant?
-
-. . .
-
-```C
-stack_create(); // crée une pile avec une taille par défaut
-// vérifie si la pile est pleine et réalloue si besoin
-stack_push();
-// vérifie si la pile est vide/trop grande 
-// et réalloue si besoin
-stack_pop(); 
-```
-
-## Exercice: ouvrir un repo/issues pour l'implémentation
-
-* Oui-oui cela est une introduction au développement collaboratif (et
-  hippie).
-
-# Le tri à deux piles (1/3)
-
-## Cas pratique
-
-![Un exemple de tri à deux piles](figs/tri_piles.svg){width=70%}
-
-# Le tri à deux piles (2/3)
-
-## Exercice: formaliser l'algorithme
-
-. . .
-
-## Algorithme de tri nécessitant 2 piles (G, D)
-
-Soit `tab` le tableau à trier:
-
-```C
-pour i de 0 à N-1
-    tant que (tab[i] > que le sommet de G)
-        dépiler G dans D
-    tant que (tab[i] < que le sommet de D)
-        dépiler de D dans G
-    empiler tab[i] sur G
-dépiler tout D dans G
-tab est trié dans G
-```
-
-# Le tri à deux piles (3/3)
-
-## Exercice: trier le tableau `[2, 10, 5, 20, 15]`
-
-```C
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-```
-- 
GitLab