diff --git a/src/main/java/fr/univamu/progav/td2/ASimpleLoop.java b/src/main/java/fr/univamu/progav/td2/ASimpleLoop.java
new file mode 100644
index 0000000000000000000000000000000000000000..45593bfe0484086068bc53f2d543683829c90b36
--- /dev/null
+++ b/src/main/java/fr/univamu/progav/td2/ASimpleLoop.java
@@ -0,0 +1,13 @@
+package fr.univamu.progav.td2;
+
+public class ASimpleLoop {
+
+  public static double nonTerminatingSum(int n) {
+    double sum = 0;
+    for (double i = 0; i != n; i = i + 0.1) {
+      sum = sum + i ;
+    }
+    return sum;
+  }
+
+}
diff --git a/src/main/java/fr/univamu/progav/td2/GuessingGame.java b/src/main/java/fr/univamu/progav/td2/GuessingGame.java
new file mode 100644
index 0000000000000000000000000000000000000000..0d75eb86cd450def04cdc3a2a8e953584050adc9
--- /dev/null
+++ b/src/main/java/fr/univamu/progav/td2/GuessingGame.java
@@ -0,0 +1,41 @@
+package fr.univamu.progav.td2;
+
+public class GuessingGame {
+
+  public static int solve(int mystery) {
+    return new GuessingGame(mystery).nbAttempts();
+  }
+
+  public static final int LOWER_BOUND = 1;
+  public static final int UPPER_BOUND = 1000;
+
+  private final int mystery;
+  private int attempts = 0;
+
+  public GuessingGame(int mystery) {
+    this.mystery = mystery;
+    guess(LOWER_BOUND, UPPER_BOUND);
+  }
+
+  private int nbAttempts() {
+    return attempts;
+  }
+
+  private void guess(int lowerBound, int upperBound) {
+    this.attempts++;
+    if (lowerBound == upperBound) {
+      return;
+    }
+    int middle = (upperBound + lowerBound) / 2;
+    if (middle == mystery) {
+      return;
+    }
+    if (middle < mystery) {
+      guess(middle,upperBound);
+    } else {
+      guess(lowerBound,middle-1);
+    }
+
+  }
+
+}
diff --git a/src/main/java/fr/univamu/progav/td2/People.java b/src/main/java/fr/univamu/progav/td2/People.java
new file mode 100644
index 0000000000000000000000000000000000000000..1873654d712f2e454edae98dbd5f84aed45a08a4
--- /dev/null
+++ b/src/main/java/fr/univamu/progav/td2/People.java
@@ -0,0 +1,44 @@
+package fr.univamu.progav.td2;
+
+import java.util.List;
+
+public class People {
+
+  private final String name;
+  private final int age;
+
+  public People(String name, int age) {
+    this.name = name;
+    this.age = age;
+  }
+
+  public String getName() {
+    return name;
+  }
+
+  public int getAge() {
+    return age;
+  }
+
+  /** Decides whether the list contains a 25-year-old "Charlie"
+   * @param peopleList
+   * @return true if a 25-year-old charlie is in the list
+   */
+  public static int whereIsCharlie(List<People> peopleList) {
+    People charlie = new People("Charlie", 25);
+    int count = 0;
+    for (People p : peopleList) {
+      if (p == charlie) {
+        return  count;
+      }
+      count++;
+    }
+    return -1; // Charlie is not here.
+  }
+
+
+  @Override
+  public String toString() {
+    return this.name;
+  }
+}
diff --git a/src/main/java/fr/univamu/progav/td2/Ratio.java b/src/main/java/fr/univamu/progav/td2/Ratio.java
new file mode 100644
index 0000000000000000000000000000000000000000..cde58322c4da073b86a09e434a2e6874d55e5b7b
--- /dev/null
+++ b/src/main/java/fr/univamu/progav/td2/Ratio.java
@@ -0,0 +1,54 @@
+package fr.univamu.progav.td2;
+
+public class Ratio {
+
+  private final int num;
+  private final int denom;
+
+  private Ratio(int num, int denom) {
+    this.num = num;
+    this.denom = denom;
+  }
+
+  /** Builds a ratio, given its numerator and denominator
+   * @param num the numerator of the ratio
+   * @param denom the denominator of the ratio
+   * @return a reduced ratio equals to num/denom, represented in reduced form.
+   */
+  public static Ratio of(int num, int denom) {
+    int d = gcd(denom, num);
+    return new Ratio(num / d, denom /d );
+  }
+
+  // UnsafeOf is used in test, to build a ratio without reducing it,
+  // and must be used with already reduced numerator and denominator.
+  protected static Ratio unsafeOf(int num, int denom) {
+    return new Ratio(num, denom);
+  }
+
+  // Euclid's algorithm
+  public static int gcd(int a, int b) {
+    return a == 0 || b == 0? a + b:
+           gcd(b, a % b);
+  }
+
+
+  public Ratio plus(Ratio r) {
+    return of(this.num * r.denom + this.denom * r.num, this.denom * r.denom);
+  }
+
+
+  @Override
+  public boolean equals(Object obj) {
+    if (!(obj instanceof Ratio r)) {
+      return false;
+    }
+    return r.num == this.num && r.denom == this.denom;
+  }
+
+  @Override
+  public String toString() {
+    double value = this.num / (double) this.denom;
+    return String.valueOf(value);
+  }
+}
diff --git a/src/main/java/fr/univamu/progav/td2/TD2.md b/src/main/java/fr/univamu/progav/td2/TD2.md
new file mode 100644
index 0000000000000000000000000000000000000000..2e59ad9204820d0990425302b44c86a6181b5ddc
--- /dev/null
+++ b/src/main/java/fr/univamu/progav/td2/TD2.md
@@ -0,0 +1,109 @@
+Introduction
+============
+
+Dans les exercices suivants, chaque petit programme comporte une 
+erreur, qui 
+apparait lors du test. L'objectif est d'apprendre à utiliser le débugger 
+pour Java d'IntelliJ pour trouver la cause de l'erreur, et la corriger.
+
+La tâche Gradle permet de lancer les tests, mais on préfèrera cette fois 
+lancer uniquement le test de l'exercice en cours. Pour cela, ouvrir le 
+fichier contenant le test, trouver la méthode de test, et dans la marge 
+`clic gauche` sur l'icône de lancement ![run](../../../../../resources/run.png),
+et choisir l'option *debug* ![debug](../../../../../resources/debug.png).
+
+Pour arrêter le débugger à une instruction du programme, il faut placer des 
+*breakpoints* ![breakpoint](../../../../../resources/breakpoint.png). Il suffit 
+pour cela d'un `clic gauche` dans la marge du programme, sur le numéro de 
+ligne. Un `clic droit` permet de le paramétrer si nécessaire, et un deuxième 
+`clic gauche` le fait disparaître.
+
+Lorsque le programme s'exécute, il s'interrompt automatiquement aux 
+breakpoints, et affiche l'état de la pile.
+
+![Panneau de débuggage](../../../../../resources/debug-panel.png)
+
+Dans la partie gauche se trouve la liste des *frames*, c'est-à-dire des 
+niveaux ou couches de la pile, la plus récente en haut. Attention, lancer un 
+test demande un grand nombre d'appels de méthode avant d'arriver à la 
+méthode de test, donc la plupart des *frames* ne sont pas pertinents, seuls 
+les frames les plus hauts, pour lesquels on reconnaît les méthodes du projet,
+nous intéressent.
+
+La partie droite affiche le contenu du frame courant, en commençant par la 
+valeur de `this` (si la méthode n'est pas statique), puis toutes les 
+variables et leurs valeurs. Les tableaux et les objets peuvent être 
+inspectés en dépliant les arborescences.
+
+La barre du haut contient les actions réalisables, dont voici les plus 
+importantes.
+
+![Relancer](../../../../../resources/rerun.png) relance le test depuis le 
+début, toujours en mode *debug*.
+
+![Arrêter](../../../../../resources/stop.png) arrête l'évaluation du 
+programme immédiatement, et ferme le débuggeur.
+
+![Reprendre](../../../../../resources/resume.png) reprend l'évaluation, 
+jusqu'au prochain *breakpoint* ou la fin normale de l'exécution du programme.
+
+![Passer](../../../../../resources/step-over.png) passe à l'instruction 
+suivante, en ignorant tout appel de méthodes dans l'instruction en cours.
+
+![Entrer](../../../../../resources/step-into.png) passe à la première 
+instruction d'une méthode appelée dans l'instruction en cours. En cas de 
+choix entre plusieurs méthodes (ou constructeurs), il faut cliquer sur celle 
+qui nous intéresse. Il est conseillé de ne pas entrer dans les méthodes ne 
+faisant pas partie du projet.
+
+![Sortir](../../../../../resources/step-out.png) reprend l'exécution jusqu'à 
+terminer la méthode actuellement en cours, et s'interrompt à l'instruction 
+ayant appelé la méthode.
+
+Ces actions permettent d'exécuter le programme pas-à-pas, plus ou moins 
+finement, en inspectant les valeurs des variables. 
+
+Exercice 1
+==========
+
+Dans la classe `People`, la méthode `whereIsCharlie` devrait retourner la 
+position de Charlie, 25 ans, dans la liste. Utiliser le test et le débuggeur 
+pour trouver l'erreur.
+
+Exercice 2
+==========
+
+Dans la classe `ASimpleLoop`, la méthode `nonTerminatingSum` fait un calcul, 
+qui ne termine pas. Utiliser le test et le débuggeur, pour comprendre 
+pourquoi elle ne termine pas. Corriger ensuite la méthode pour que le calcul 
+s'arrête,
+
+Exercice 3
+==========
+
+Dans la classe `Ratio`, représentant les nombres rationnels, l'addition ne 
+semble pas produire le bon résultat. Pourtant, nous avons pris soin de bien 
+réduire les fractions en calculant le plus grand commun diviseur avec 
+l'algorithme d'Euclide, et de forcer cette réduction dans la méthode 
+statique `of` que nous utilisons pour construire les fractions. Pour être 
+sûr de bien tester, nous avons aussi ajouter une méthode `unsafeOf`, qui 
+ignore l'étape de réduction : ainsi les valeurs attendues dans les tests 
+sont certainement bien définies (nous les avons réduites nous-mêmes). Enfin, 
+la méthode de test d'égalité profite de la forme réduite : il suffit de 
+tester l'égalité des numérateurs et des dénominateurs. Utiliser la méthode 
+de test et le débuggeur pour trouver l'erreur et la corriger. 
+
+
+Exercice 4
+==========
+
+La classe `GuessingGame` reprend la stratégie optimale pour le jeu 
+consistant à trouver un entier d'un intervalle (par exemple entre 1 et 1000),
+en tentant des valeurs, et en obtenant pour chaque mauvaise réponse une 
+indication "plus petit" ou "plus grand". Bien sûr, il s'agit de faire une 
+recherche dichotomique. Ici, une erreur a été faite, et la dichotomie ne 
+termine pas toujours. Il va d'abord falloir trouver une valeur mystère pour 
+laquelle l'algorithme boucle infiniment (provoquant un dépassement de pile). 
+Ensuite, en utilisant le débuggeur et en partant avec cette valeur, il sera 
+possible de repérer la raison pour laquelle l'algorithme boucle ainsi. 
+Utiliser donc une fois de plus le débugger pour trouver et corriger l'erreur.
\ No newline at end of file
diff --git a/src/main/resources/breakpoint.png b/src/main/resources/breakpoint.png
new file mode 100644
index 0000000000000000000000000000000000000000..835ccd8307666d7a7abc325bdbd435ddac2fc48d
Binary files /dev/null and b/src/main/resources/breakpoint.png differ
diff --git a/src/main/resources/debug-panel.png b/src/main/resources/debug-panel.png
new file mode 100644
index 0000000000000000000000000000000000000000..59d6c03d8b471d96f531c1c87e9d73d3e35cb634
Binary files /dev/null and b/src/main/resources/debug-panel.png differ
diff --git a/src/main/resources/debug.png b/src/main/resources/debug.png
new file mode 100644
index 0000000000000000000000000000000000000000..0e410347746d30c95c66beab6edc26803d774ad9
Binary files /dev/null and b/src/main/resources/debug.png differ
diff --git a/src/main/resources/mute-breakpoint.png b/src/main/resources/mute-breakpoint.png
new file mode 100644
index 0000000000000000000000000000000000000000..f7a3efb2366dff36520c44792abf20d6b4d1d5f9
Binary files /dev/null and b/src/main/resources/mute-breakpoint.png differ
diff --git a/src/main/resources/rerun-auto.png b/src/main/resources/rerun-auto.png
new file mode 100644
index 0000000000000000000000000000000000000000..8262d20240f06795c099f4ecc8d80ca9d7354562
Binary files /dev/null and b/src/main/resources/rerun-auto.png differ
diff --git a/src/main/resources/rerun-failed.png b/src/main/resources/rerun-failed.png
new file mode 100644
index 0000000000000000000000000000000000000000..9dd194a24d4f368872f04ccc54ece354a5ee58d6
Binary files /dev/null and b/src/main/resources/rerun-failed.png differ
diff --git a/src/main/resources/rerun.png b/src/main/resources/rerun.png
new file mode 100644
index 0000000000000000000000000000000000000000..1acc05554535be535d91515c4ee4b952e849b017
Binary files /dev/null and b/src/main/resources/rerun.png differ
diff --git a/src/main/resources/resume.png b/src/main/resources/resume.png
new file mode 100644
index 0000000000000000000000000000000000000000..ed843ff60e8d1aa8f4aa6a79d3d48d8ef2c7b1e3
Binary files /dev/null and b/src/main/resources/resume.png differ
diff --git a/src/main/resources/run.png b/src/main/resources/run.png
new file mode 100644
index 0000000000000000000000000000000000000000..a466a16d2078b9f5c686cd283685d0d2cff40f6c
Binary files /dev/null and b/src/main/resources/run.png differ
diff --git a/src/main/resources/step-into.png b/src/main/resources/step-into.png
new file mode 100644
index 0000000000000000000000000000000000000000..362b040202578116a15c0a3af8d7c441f81ed4fe
Binary files /dev/null and b/src/main/resources/step-into.png differ
diff --git a/src/main/resources/step-out.png b/src/main/resources/step-out.png
new file mode 100644
index 0000000000000000000000000000000000000000..cd340d1d08c01a6d416a13d87cb0bee23377dc90
Binary files /dev/null and b/src/main/resources/step-out.png differ
diff --git a/src/main/resources/step-over.png b/src/main/resources/step-over.png
new file mode 100644
index 0000000000000000000000000000000000000000..a179c06db4bcfd1a01c4d497c6818b81269abfc0
Binary files /dev/null and b/src/main/resources/step-over.png differ
diff --git a/src/main/resources/stop.png b/src/main/resources/stop.png
new file mode 100644
index 0000000000000000000000000000000000000000..a4e7520311c536fe68b5f1451137f314222ace09
Binary files /dev/null and b/src/main/resources/stop.png differ
diff --git a/src/main/resources/view-breakpoint.png b/src/main/resources/view-breakpoint.png
new file mode 100644
index 0000000000000000000000000000000000000000..fd8542e5d4c65bec5f3d21c33cb2b37055e831ad
Binary files /dev/null and b/src/main/resources/view-breakpoint.png differ
diff --git a/src/test/java/fr/univamu/progav/td2/ASimpleLoopTest.java b/src/test/java/fr/univamu/progav/td2/ASimpleLoopTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..a534b433fe5ac1529a588375f0aae6d7755ebbad
--- /dev/null
+++ b/src/test/java/fr/univamu/progav/td2/ASimpleLoopTest.java
@@ -0,0 +1,15 @@
+package fr.univamu.progav.td2;
+
+import org.junit.jupiter.api.Test;
+
+import static fr.univamu.progav.td2.ASimpleLoop.nonTerminatingSum;
+import static org.junit.jupiter.api.Assertions.*;
+
+class ASimpleLoopTest {
+
+  @Test
+  void nonTerminatingSumTest() {
+    double result = nonTerminatingSum(10);
+    assertEquals(505,result);
+  }
+}
\ No newline at end of file
diff --git a/src/test/java/fr/univamu/progav/td2/GuessingGameTest.java b/src/test/java/fr/univamu/progav/td2/GuessingGameTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..4fc05a27d18b1d97ce02ff371ca9423b765698d7
--- /dev/null
+++ b/src/test/java/fr/univamu/progav/td2/GuessingGameTest.java
@@ -0,0 +1,32 @@
+package fr.univamu.progav.td2;
+
+import org.junit.jupiter.api.Test;
+
+import static fr.univamu.progav.td2.GuessingGame.LOWER_BOUND;
+import static fr.univamu.progav.td2.GuessingGame.UPPER_BOUND;
+import static org.junit.jupiter.api.Assertions.*;
+
+class GuessingGameTest {
+
+  @Test
+  void solve() {
+    int max_allowed = // a bound on the minimum number of guesses by the best strategy.
+      (int) Math.ceil(log2(GuessingGame.UPPER_BOUND - GuessingGame.LOWER_BOUND + 2,1e-1));
+    for (int i = GuessingGame.LOWER_BOUND; i <= GuessingGame.UPPER_BOUND; i++) {
+      int r = GuessingGame.solve(i);
+      assertTrue(r <= max_allowed,
+        "Guessing " + i + " in " + r + "/" + max_allowed + " attempts");
+    }
+  }
+
+  // compute log(x) in base 2, with given precision, for instance log2(x,1e-6)
+  // is at most 0.000001 away from the exact value.
+  private static double log2(double x, double precision) {
+    return
+      (x >= 2)? 1 + log2(x/2, precision):
+      (x == 1)? 0:
+      (x < 1)? - log2(1/x, precision):
+      (precision > 1) ? 0:
+      0.5 * log2(x * x, precision*2);
+  }
+}
\ No newline at end of file
diff --git a/src/test/java/fr/univamu/progav/td2/PeopleTest.java b/src/test/java/fr/univamu/progav/td2/PeopleTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..79b0ce8b14b629d51f691100d701b90ea25c4ae4
--- /dev/null
+++ b/src/test/java/fr/univamu/progav/td2/PeopleTest.java
@@ -0,0 +1,36 @@
+package fr.univamu.progav.td2;
+
+import org.junit.jupiter.api.Test;
+
+import java.util.List;
+
+import static fr.univamu.progav.td2.People.whereIsCharlie;
+import static org.junit.jupiter.api.Assertions.*;
+
+class PeopleTest {
+
+  private final List<People> peopleList =
+    List.of(
+      new People("Alfa", 12),
+      new People("Bravo", 18),
+      new People("Charlie", 25),
+      new People("Delta", 36),
+      new People("Echo", 8),
+      new People("Foxtrot", 11),
+      new People("Golf", 21),
+      new People("Hotel", 53),
+      new People("India", 42),
+      new People("Juliett", 28)
+    );
+
+
+  @Test
+  void whereIsCharlieTest() {
+    int charliePosition = whereIsCharlie(peopleList);
+    assertEquals(2, charliePosition);
+    List<People> noCharlie =
+      peopleList.stream().filter(p -> !p.getName().equals("Charlie")).toList();
+    int noCharliePosition = whereIsCharlie(noCharlie);
+    assertEquals(-1, noCharliePosition);
+  }
+}
\ No newline at end of file
diff --git a/src/test/java/fr/univamu/progav/td2/RatioTest.java b/src/test/java/fr/univamu/progav/td2/RatioTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..c4ac7a3c08c8266fb53aa73f84116777ba5e3042
--- /dev/null
+++ b/src/test/java/fr/univamu/progav/td2/RatioTest.java
@@ -0,0 +1,21 @@
+package fr.univamu.progav.td2;
+
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+class RatioTest {
+
+
+  @Test
+  void plusTest() {
+    assertEquals(Ratio.unsafeOf(2,1),Ratio.of(1,1).plus(Ratio.of(1,1)));
+    assertEquals(Ratio.unsafeOf(5,6),Ratio.of(1,3).plus(Ratio.of(1,2)));
+    assertEquals(Ratio.unsafeOf(1,6),Ratio.of(-1,3).plus(Ratio.of(1,2)));
+    assertEquals(Ratio.unsafeOf(-1,6),Ratio.of(1,3).plus(Ratio.of(-1,2)));
+    assertEquals(Ratio.unsafeOf(-5,6),Ratio.of(-1,3).plus(Ratio.of(-1,2)));
+    assertEquals(Ratio.unsafeOf(-5,6),Ratio.of(1,-3).plus(Ratio.of(1,-2)));
+    assertEquals(Ratio.unsafeOf(5,6),Ratio.of(-1,-3).plus(Ratio.of(1,2)));
+  }
+
+}
\ No newline at end of file