diff --git a/slides/cours_19.md b/slides/cours_19.md
index 04045f3be08b638bae3af855b15b04f6b162512e..fc3595dafe946a33447d43df33886ed44a321259 100644
--- a/slides/cours_19.md
+++ b/slides/cours_19.md
@@ -38,7 +38,7 @@ patat:
 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 à un point
+## Un à un et le/la premier/ère qui poste la bonne réponse sur matrix a un point
 
 # Suppression dans un arbre AVL
 
@@ -385,293 +385,3 @@ Image 64 pixels, arbre 25 neouds.
 :::
 
 
-# Structure de données
-
-::: columns
-
-:::: {.column width=50%}
-
-## Pseudocode?
-
-. . .
-
-```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?
-
-```pyrhon
-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évident pas trop on supprime le quadrant (avec perte)
-
-# Fonctions utiles (1/N)
-
-## 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(*n));
-    if (depth > 0) {
-        for (int i = 0; i < 4; ++i) {
-            n->child[i] = qt_create(depth-1);
-        }
-    }
-    return n;
-}
-```
-
-# Fonctions utiles (2/N)
-
-## 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 (3/N)
-
-* 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?
-* 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 (4/N)
-
-::: 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)
-
-* 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
-    retourn arbre
-```
-
-::::
-
-:::
-
-# Remplir l'arbre
-
-## A partir d'une matrice (pseudo-code, 5min, matrix)?
-
-. . .
-
-```C
-arbre matrice_à_arbre(matrice, arbre)
-    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)?
-
-```C
-node *matrice_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;
-```
-
-
-# Interface
-
-## Quelles sont les fonctions à implémenter?
-
-
-
-
-# Implémentation
diff --git a/slides/cours_20.md b/slides/cours_20.md
new file mode 100644
index 0000000000000000000000000000000000000000..7ecd130e5cb093d3a9164cfa69fa594ed4e25296
--- /dev/null
+++ b/slides/cours_20.md
@@ -0,0 +1,653 @@
+---
+title: "Arbres quaternaires et compression"
+date: "2022-03-30"
+patat:
+  eval:
+    tai:
+      command: fish
+      fragment: false
+      replace: true
+    ccc:
+      command: fish
+      fragment: false
+      replace: true
+  images:
+    backend: auto
+---
+
+# Le cours précédent
+
+## Questions (réponse sur matrix)
+
+. . .
+
+* Combien de points du suture?
+
+![](figs/alkis_avant.jpeg)
+
+# Le cours précédent
+
+## Questions
+
+* Aucun c'est de la colle
+
+![](figs/alkis_apres.jpeg)
+
+# Le cours précédent
+
+## Questions
+
+* Qu'est-ce qu'un arbre quaternaire?
+
+. . .
+
+* Un arbre où chaque noeud a soit **4 enfants** soit **aucun**.
+* A quoi peut servir un arbre quaternaire?
+
+. . .
+
+* Compression
+
+# Les arbres quaternaires
+
+## Définition
+
+Arbre dont chaque nœud a 4 enfants ou aucun. 
+
+![Un exemple de quadtree.](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 neouds.
+
+::::
+
+:::
+
+
+# Structure de données
+
+::: columns
+
+:::: {.column width=50%}
+
+## Pseudocode?
+
+. . .
+
+```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?
+
+```pyrhon
+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évident pas trop on supprime le quadrant (avec perte)
+
+# Fonctions utiles (1/N)
+
+## 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(*n));
+    if (depth > 0) {
+        for (int i = 0; i < 4; ++i) {
+            n->child[i] = qt_create(depth-1);
+        }
+    }
+    return n;
+}
+```
+
+# Le nombre de noeuds?
+
+## Comment implémenter la fonction (pseudo-code, 5min, matrix)?
+
+. . .
+
+```C
+entier nombre_noeuds(arbre)
+    si est_feuille(arbre)
+        retourne 1
+    sinon
+        somme = 1
+        pour i de 0 à 3
+            somme += nombre_noeuds(arbre.enfant[i])
+        retourne somme
+```
+
+# Le nombre de noeuds?
+
+## Comment implémenter la fonction en C (3min, matrix)?
+
+. . .
+
+```C
+inf 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)
+
+. . .
+
+```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 {
+        depths[i] = 1 + depth(qt->child[i]);
+        return max_depth(depths);
+    }
+}
+```
+
+# Fonctions utiles (2/N)
+
+## 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 (3/N)
+
+* 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?
+* 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 (4/N)
+
+::: 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
+    retourn arbre
+```
+
+. . .
+
+* Écrire le code `C` correspondant (5min, matrix)
+
+::::
+
+:::
+
+# 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)?
+
+```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;
+```
+
+# La profondeur?
+
+## Comment implémenter la fonction profondeur?
+
+* Quelle signature?
+
+. . .
+
+```C
+entier profondeur(arbre)
+```
+
+* Quel pseudo-code (3min, matrix)?
+
+. . .
+
+```C
+entier profondeur(arbre)
+    profondeurs = [0, 0, 0, 0];
+    si est_feuille(arbre)
+        retourne 0
+    sinon
+        pour i 0 à 3
+            profondeurs[i] = 1 + profondeur(arbre.enfant[i])
+        retourn max(p)
+```
+
+# La profondeur en C?
+
+## Implémentation (5min, matrix)
+
+. . .
+
+```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 {
+        depths[i] = 1 + depth(qt->child[i]);
+        return max_depth(depths);
+    }
+}
+```
+
+# Remplir la matrice
+
+## A partir de l'arbre (pseudo-code, 3min, matrix)?
+
+. . .
+
+```C
+matrice arbre_à_matrice(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 arbre
+```
+
+. . .
+
+## A partir de l'arbre (C, 3min, matrix)?
+
+```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;
+        }
+    }
+```
+
+# 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)?
+
+. . .
+
+```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)
+
+. . .
+
+```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
+```
+
+* 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
+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
+```
+