diff --git a/content/docs/L2_MathInfo/TP3.zip b/content/docs/L2_MathInfo/TP3.zip
new file mode 100644
index 0000000000000000000000000000000000000000..d22bb2131700a8619e0243b63eb701db6816b49a
Binary files /dev/null and b/content/docs/L2_MathInfo/TP3.zip differ
diff --git a/content/docs/L2_MathInfo/TP3/TP3.cpp b/content/docs/L2_MathInfo/TP3/TP3.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..fdf5eba9591330229fd9e376cc2c36d10ec6d5de
--- /dev/null
+++ b/content/docs/L2_MathInfo/TP3/TP3.cpp
@@ -0,0 +1,627 @@
+#include <vector>
+#include <iostream>
+using namespace std;
+
+/** Infrastructure minimale de test **/
+#define ASSERT(test) if (!(test)) cout << "Test failed in file " << __FILE__ << " line " << __LINE__ << ": " #test << endl;
+
+
+/**********************************************************/
+/**** Exercice 1 : Programation récursive / dynamique  ****/
+/**********************************************************/
+
+/** Retourne le nombre de fibonacci défini selon la suite :
+ * f(n) = 0 pour n < 0
+ * f(0) = 1
+ * f(n) = f(n-1) + f(n-2) pour n  > 0
+ * et calculé de façon récursive
+ * @param n un entier
+ * @return la valeur de la fonction
+ **/
+int fibonacciRec(int n) {
+    cerr << "Erreur : fonction non implantée" << endl; throw 0; // Supprimer cette ligne
+}
+
+/** Test de la fonction fibonacciRec
+ */
+void testFibonacciRec() {
+    cout << "Début des tests : fibonacci rec" << endl;
+    ASSERT(fibonacciRec(-5)==0);
+    ASSERT(fibonacciRec(0)==1);
+    ASSERT(fibonacciRec(1)==1);
+    ASSERT(fibonacciRec(2)==2);
+    ASSERT(fibonacciRec(3)==3);
+    ASSERT(fibonacciRec(4)==5);
+    ASSERT(fibonacciRec(5)==8);
+    ASSERT(fibonacciRec(6)==13);
+    ASSERT(fibonacciRec(7)==21);
+    cout << "Fin des tests : fibonacci rec" << endl;
+}
+
+/** Retourne le nombre de fibonacci défini selon la suite :
+ * f(n) = 0 pour n < 0
+ * f(0) = 1
+ * f(n) = f(n-1) + f(n-2) pour n  > 0
+ * et calculé de façon dynamique
+ * @param n un entier
+ * @return la valeur de la fonction
+ **/
+int fibonacciDyn(int n) {
+    cerr << "Erreur : fonction non implantée" << endl; throw 0; // Supprimer cette ligne
+}
+
+/** Test de la fonction fibonacciDyn
+ */
+void testFibonacciDyn() {
+    cout << "Début des tests : fibonacci dyn" << endl;
+    ASSERT(fibonacciDyn(-5)==0);
+    ASSERT(fibonacciDyn(0)==1);
+    ASSERT(fibonacciDyn(1)==1);
+    ASSERT(fibonacciDyn(2)==2);
+    ASSERT(fibonacciDyn(3)==3);
+    ASSERT(fibonacciDyn(4)==5);
+    ASSERT(fibonacciDyn(5)==8);
+    ASSERT(fibonacciDyn(6)==13);
+    ASSERT(fibonacciDyn(7)==21);
+    ASSERT(fibonacciDyn(22) == 28657);
+    ASSERT(fibonacciDyn(40) == 165580141);
+    cout << "Fin des tests : fibonacci dyn" << endl;
+}
+
+/** Retourne le nombre de suites possibe de taille n formée de
+ * briques de taille 1
+ * briques de taille 2 rouges ou bleues
+ * et calculé de façon récursive
+ * @param n un entier
+ * @return le nombre de suites possible
+ **/
+int rougeBleuRec(int n) {
+    cerr << "Erreur : fonction non implantée" << endl; throw 0; // Supprimer cette ligne
+}
+
+/** Test de la fonction rougeBleuRec
+ */
+void testRougeBleuRec() {
+    cout << "Début des tests : rouge bleu rec" << endl;
+    ASSERT(rougeBleuRec(-5)==0);
+    ASSERT(rougeBleuRec(0)==1);
+    ASSERT(rougeBleuRec(1)==1);
+    ASSERT(rougeBleuRec(2)==3);
+    ASSERT(rougeBleuRec(3)==5);
+    ASSERT(rougeBleuRec(4)==11);
+    ASSERT(rougeBleuRec(5)==21);
+    ASSERT(rougeBleuRec(6)==43);
+    ASSERT(rougeBleuRec(7)==85);
+    cout << "Fin des tests : rouge bleu rec" << endl;
+}
+
+/** Retourne le nombre de suites possibe de taille n formée de
+ * briques de taille 1
+ * briques de taille 2 rouges ou bleues
+ * et calculé de façon dynamique
+ * @param n un entier
+ * @return le nombre de suites possible
+ **/
+int rougeBleuDyn(int n) {
+    cerr << "Erreur : fonction non implantée" << endl; throw 0; // Supprimer cette ligne
+}
+
+/** Test de la fonction rougeBleuRec
+ */
+void testRougeBleuDyn() {
+    cout << "Début des tests : rouge bleu dyn" << endl;
+    ASSERT(rougeBleuDyn(-5)==0);
+    ASSERT(rougeBleuDyn(0)==1);
+    ASSERT(rougeBleuDyn(1)==1);
+    ASSERT(rougeBleuDyn(2)==3);
+    ASSERT(rougeBleuDyn(3)==5);
+    ASSERT(rougeBleuDyn(4)==11);
+    ASSERT(rougeBleuDyn(5)==21);
+    ASSERT(rougeBleuDyn(6)==43);
+    ASSERT(rougeBleuDyn(7)==85);
+    ASSERT(rougeBleuDyn(22)==2796203);
+    ASSERT(rougeBleuDyn(35)==1431655765);
+    cout << "Fin des tests : rouge bleu dyn" << endl;
+}
+
+
+
+/** Retourne le nombre de sequences possibles pour un score donné
+ * une séquence est une suite contenant des :
+ *   - essais transformés (7 points),
+ *   - essais non transformés (5 points),
+ *   - tirs (3 points),
+ *   - pénalités (3 points)
+ * calculé de façon récursive
+ * @param n, le score final
+ * @return le nombre de sequences
+ **/
+int nbSeqRugbyRec(int n) {
+    cerr << "Erreur : fonction non implantée" << endl; throw 0; // Supprimer cette ligne
+}
+
+/** Test de la fonction nbSeqRugbyRec
+ */
+void testNbSeqRugbyRec() {
+    cout << "Début des tests : Séquence rugby rec" << endl;
+    ASSERT(nbSeqRugbyRec(-5)==0);
+    ASSERT(nbSeqRugbyRec(0)==1);
+    ASSERT(nbSeqRugbyRec(1)==0);
+    ASSERT(nbSeqRugbyRec(2)==0);
+    ASSERT(nbSeqRugbyRec(3)==2);
+    ASSERT(nbSeqRugbyRec(4)==0);
+    ASSERT(nbSeqRugbyRec(5)==1);
+    ASSERT(nbSeqRugbyRec(6)==4);
+    ASSERT(nbSeqRugbyRec(7)==1);
+    ASSERT(nbSeqRugbyRec(8)==4);
+    ASSERT(nbSeqRugbyRec(9)==8);
+    ASSERT(nbSeqRugbyRec(10)==5);
+    cout << "Fin des tests : Séquence rugby rec" << endl;
+}
+
+/** Retourne le nombre de sequences possibles pour un score donné
+ * une séquence est une suite contenant des :
+ *   - essais transformés (7 points),
+ *   - essais non transformés (5 points),
+ *   - tirs (3 points),
+ *   - pénalités (3 points)
+ * calculé de façon dynamique
+ * @param n, le score final
+ * @return le nombre de sequences
+ **/
+int nbSeqRugbyDyn(int n) {
+    cerr << "Erreur : fonction non implantée" << endl; throw 0; // Supprimer cette ligne
+}
+
+/** Test de la fonction nbSeqRugbyRec
+ */
+void testNbSeqRugbyDyn() {
+    cout << "Début des tests : Séquence rugby dyn" << endl;
+    ASSERT(nbSeqRugbyDyn(-5)==0);
+    ASSERT(nbSeqRugbyDyn(0)==1);
+    ASSERT(nbSeqRugbyDyn(1)==0);
+    ASSERT(nbSeqRugbyDyn(2)==0);
+    ASSERT(nbSeqRugbyDyn(3)==2);
+    ASSERT(nbSeqRugbyDyn(4)==0);
+    ASSERT(nbSeqRugbyDyn(5)==1);
+    ASSERT(nbSeqRugbyDyn(6)==4);
+    ASSERT(nbSeqRugbyDyn(7)==1);
+    ASSERT(nbSeqRugbyDyn(8)==4);
+    ASSERT(nbSeqRugbyDyn(9)==8);
+    ASSERT(nbSeqRugbyDyn(10)==5);
+    ASSERT(nbSeqRugbyDyn(50)==6156717);
+    cout << "Fin des tests : Séquence rugby dyn" << endl;
+}
+
+/*********************************************/
+/**** Exercice 2 : Génération exhaustive  ****/
+/*********************************************/
+
+/** Affiche tous les couples (i,j)
+ * pour 0 <= i < n, 0 <= j < n
+ * @param n, un entier
+ **/
+void afficheCouples(int n) {
+    for(int i = 0; i < n; i++) {
+        for(int j = 0; j < n; j++) {
+            cout << "(" << i << "," << j << ") ";
+        }
+    }
+    cout << endl;
+}
+
+/** Test de la fonction afficheCouples
+ */
+void testAffichesCouples() {
+    afficheCouples(0);
+    afficheCouples(3);
+    afficheCouples(5);
+}
+
+/** Affiche tous les triplets (i,j,k)
+ * pour 0 <= i < n, 0 <= j < n, 0 <= k < n
+ * @param n, un entier
+ **/
+void afficheTriplets(int n) {
+    cerr << "Erreur : fonction non implantée" << endl; throw 0; // Supprimer cette ligne
+}
+
+/** Test de la fonction afficheTriplets
+ */
+void testAffichesTriplets() {
+    afficheTriplets(0);
+    afficheTriplets(3);
+    afficheTriplets(5);
+}
+
+typedef vector<vector<int>> Collection;
+
+/** Affiche un vecteur d'entier
+ * @param v, un k-uplet d'entier
+ **/
+void afficheVector(const vector<int> &v) {
+    cout << "(";
+    for(unsigned int i =0; i < v.size(); i++) {
+        cout << v[i];
+        if(i!= v.size() -1) {
+            cout << ", ";
+        }
+    }
+    cout << ")" << endl;
+}
+
+/** Affiche une collection de vecteur d'entiers
+ * @param C une collection de vecteurs
+ **/
+void afficheCollection(const Collection &C) {
+    cout << "{";
+    for(unsigned int i =0; i < C.size(); i++) {
+        afficheVector(C[i]);
+    }
+    cout << "}" << endl;
+}
+
+/** Retourne la collection contenant l'unique 0-uplet
+ **/
+Collection genere0Uplets() {
+    Collection C = Collection();
+    C.push_back(vector<int>()); // On ajoute le vecteur vide à la collection
+    return C;
+}
+
+/** Retourne la collection contenant l'ensembe des 1-uplets (i) avec
+ * 0 <= i < n
+ * @param n, un entier : la valeur maximale de i
+ **/
+Collection genere1Uplets(int n) {
+    Collection C1 = Collection(); // collection des 1-uplets
+    Collection C0 = genere0Uplets(); // collection des 0-uplets
+    for(unsigned int ind =0; ind < C0.size(); ind++) {
+        for(int i =0; i < n; i++) {
+            vector<int> v = C0[ind]; // Je copie le vecteur d'entier de taille 0
+            v.push_back(i); // Je rajoute i au vecteur de taille 0 (j'obtiens donc un vecteur de taille 1)
+            C1.push_back(v); // Je rajoute v à ma collection
+        }
+    }
+    return C1;
+}
+
+/** Retourne la collection contenant l'ensembe des 2-uplets (i,j) avec
+ * 0 <= i < n, 0 <= j < n
+ * @param n, un entier : la valeur maximale de i et j
+ **/
+Collection genere2Uplets(int n) {
+    Collection C2 = Collection(); // collection des 2-uplets
+    Collection C1 = genere1Uplets(n); // collection des 1-uplets
+    for(unsigned int ind =0; ind < C1.size(); ind++) {
+        for(int i =0; i < n; i++) {
+            vector<int> v = C1[ind]; // Je copie le vecteur d'entier de taille 1
+            v.push_back(i); // Je rajoute i au vecteur de taille 1 (j'obtiens donc un vecteur de taille 2)
+            C2.push_back(v); // Je rajoute v à ma collection
+        }
+    }
+    return C2;
+}
+
+/** Retourne la collection contenant l'ensembe des 3-uplets (i,j,k) avec
+ * 0 <= i < n, 0 <= j < n, 0 <= k < n
+ * @param n, un entier : la valeur maximale de i, j et k
+ **/
+Collection genere3Uplets(int n) {
+    cerr << "Erreur : fonction non implantée" << endl; throw 0; // Supprimer cette ligne
+}
+
+/** Test de la fonction genere3Uplets
+ **/
+void testGenere3Uplets() {
+    cout << "Début des tests : genere3Uplets" << endl;
+    ASSERT(genere3Uplets(-5).size() == 0);
+    ASSERT(genere3Uplets(0).size() == 0);
+    ASSERT(genere3Uplets(1).size() == 1);
+    ASSERT(genere3Uplets(2).size() == 8);
+    ASSERT(genere3Uplets(3).size() == 27);
+    Collection C = genere3Uplets(4);
+    ASSERT(C.size() == 64);
+    ASSERT(C[0].size() == 3);
+    ASSERT(C[63].size() == 3);
+    ASSERT(C[42].size() == 3);
+    cout << "Fin des tests : genere3Uplets" << endl;
+}
+
+/** Retourne la collection contenant l'ensembe des k-uplets (i1, ..., ik)
+ * 0 <= i1 < n, 0 <= i2 < n,... 0 <= ik < n
+ * @param n, un entier : la valeur maximale de i1, i2, ...,ik
+ * @param k, le nombre d'éléments dans les k-uplets
+ * @return une collection de k-uplets
+ * Remarque : si k<0, no retourne la collection vide, si k=0 on retourne la collection contenant le vecteur vide
+ **/
+Collection generekUplets(int n, int k) {
+    cerr << "Erreur : fonction non implantée" << endl; throw 0; // Supprimer cette ligne
+}
+
+/** Test de la fonction generekUplets
+ **/
+void testGenerekUplets() {
+    cout << "Début des tests : generekUplets" << endl;
+    ASSERT(generekUplets(1,-1).size() == 0);
+    ASSERT(generekUplets(-1,1).size() == 0);
+    ASSERT(generekUplets(0,0).size() == 1);
+    ASSERT(generekUplets(0,1).size() == 1);
+    ASSERT(generekUplets(1,0).size() == 0);
+    ASSERT(generekUplets(0,3).size() == 0);
+    ASSERT(generekUplets(1,3).size() == 1);
+    ASSERT(generekUplets(2,3).size() == 8);
+    ASSERT(generekUplets(3,3).size() == 27);
+    ASSERT(generekUplets(1,4).size() == 1);
+    ASSERT(generekUplets(2,4).size() == 16);
+    ASSERT(generekUplets(3,4).size() == 81);
+    Collection C = generekUplets(4,3);
+    ASSERT(C.size() == 64);
+    ASSERT(C[0].size() == 3);
+    ASSERT(C[63].size() == 3);
+    ASSERT(C[42].size() == 3);
+    C = generekUplets(4,4);
+    ASSERT(C.size() == 256);
+    ASSERT(C[0].size() == 4);
+    ASSERT(C[63].size() == 4);
+    ASSERT(C[42].size() == 4);
+    ASSERT(C[255].size() == 4);
+    cout << "Fin des tests : generekUplets" << endl;
+}
+
+/***************************************/
+/**** Exercice 3 : Retour au Rugby  ****/
+/***************************************/
+
+/** Retourne le score associé à un vecteur qui représente un jeu
+ * de rugby (nb d'essais transformé, nb d'essais non transformés, nb de tirs, nb de pénalités)
+ * @param v,un vecteur d'entier
+ * @return le score associé
+ **/
+int scoreRugby(const vector<int> &v) {
+    cerr << "Erreur : fonction non implantée" << endl; throw 0; // Supprimer cette ligne
+}
+
+/** Test de la fonction scoreRugby
+ **/
+void testScoreRugby() {
+    cout << "Début des tests : scoreRugby" << endl;
+    ASSERT(scoreRugby({}) == 0);
+    ASSERT(scoreRugby({0}) == 0);
+    ASSERT(scoreRugby({1}) == 7);
+    ASSERT(scoreRugby({2}) == 14);
+    ASSERT(scoreRugby({0,0}) == 0);
+    ASSERT(scoreRugby({0,1}) == 5);
+    ASSERT(scoreRugby({1,1}) == 12);
+    ASSERT(scoreRugby({1,2}) == 17);
+    ASSERT(scoreRugby({0,0,0}) == 0);
+    ASSERT(scoreRugby({0,0,1}) == 3);
+    ASSERT(scoreRugby({0,0,2}) == 6);
+    ASSERT(scoreRugby({1,1,2}) == 18);
+    ASSERT(scoreRugby({0,0,0,0}) == 0);
+    ASSERT(scoreRugby({0,0,0,1}) == 3);
+    ASSERT(scoreRugby({0,0,0,2}) == 6);
+    ASSERT(scoreRugby({3,1,2,3}) == 41);
+    cout << "Fin des tests : scoreRugby" << endl;
+}
+
+/** Retourne l'ensemble des configuations possible pour un score donné
+ * sans tenir compte de l'ordre
+ * @param le score
+ * @return une collection de vecteurs représentant des matchs
+ **/
+Collection matchsRugby(int score) {
+    cerr << "Erreur : fonction non implantée" << endl; throw 0; // Supprimer cette ligne
+}
+
+/** Test de la fonction matchsRugby
+ **/
+void testMatchsRugby() {
+    cout << "Début des tests : matchs Rugby" << endl;
+    ASSERT(matchsRugby(-5).size() == 0);
+    ASSERT(matchsRugby(0).size() == 1);
+    ASSERT(matchsRugby(1).size() == 0);
+    ASSERT(matchsRugby(2).size() == 0);
+    ASSERT(matchsRugby(3).size() == 2);
+    ASSERT(matchsRugby(4).size() == 0);
+    ASSERT(matchsRugby(5).size() == 1);
+    ASSERT(matchsRugby(6).size() == 3);
+    ASSERT(matchsRugby(7).size() == 1);
+    ASSERT(matchsRugby(8).size() == 2);
+    ASSERT(matchsRugby(9).size() == 4);
+    ASSERT(matchsRugby(10).size() == 3);
+    ASSERT(matchsRugby(50).size() == 106);
+    cout << "Fin des tests : matchs Rugby" << endl;
+}
+
+/** Retourne les vecteurs de taille k qui correspondent à un score inférireur ou égal à n
+ * @param n, le score
+ * @param k, la taille du vecteur (on suppose k inférieur ou égal à 4)
+ * @return une collection de vecteurs représentant des matchs
+ **/
+Collection matchsRugbyInf(int n, int k) {
+    cerr << "Erreur : fonction non implantée" << endl; throw 0; // Supprimer cette ligne
+}
+
+/** Test de la fonction matchsRugbyInf
+ **/
+void testMatchsRugbyInf() {
+    cout << "Début des tests : matchs Rugby inf" << endl;
+    ASSERT(matchsRugbyInf(-5,1).size() == 0);
+    ASSERT(matchsRugbyInf(0,1).size() == 1);
+    ASSERT(matchsRugbyInf(0,2).size() == 1);
+    ASSERT(matchsRugbyInf(0,3).size() == 1);
+    ASSERT(matchsRugbyInf(0,4).size() == 1);
+    ASSERT(matchsRugbyInf(1,1).size() == 1);
+    ASSERT(matchsRugbyInf(1,2).size() == 1);
+    ASSERT(matchsRugbyInf(1,3).size() == 1);
+    ASSERT(matchsRugbyInf(1,4).size() == 1);
+    ASSERT(matchsRugbyInf(3,1).size() == 1);
+    ASSERT(matchsRugbyInf(3,2).size() == 1);
+    ASSERT(matchsRugbyInf(3,3).size() == 2);
+    ASSERT(matchsRugbyInf(3,4).size() == 3);
+    ASSERT(matchsRugbyInf(4,2).size() == 1);
+    ASSERT(matchsRugbyInf(4,4).size() == 3);
+    ASSERT(matchsRugbyInf(5,1).size() == 1);
+    ASSERT(matchsRugbyInf(5,2).size() == 2);
+    ASSERT(matchsRugbyInf(5,3).size() == 3);
+    ASSERT(matchsRugbyInf(5,4).size() == 4);
+    ASSERT(matchsRugbyInf(6,1).size() == 1);
+    ASSERT(matchsRugbyInf(6,2).size() == 2);
+    ASSERT(matchsRugbyInf(6,3).size() == 4);
+    ASSERT(matchsRugbyInf(6,4).size() == 7);
+    ASSERT(matchsRugbyInf(7,1).size() == 2);
+    ASSERT(matchsRugbyInf(7,2).size() == 3);
+    ASSERT(matchsRugbyInf(7,3).size() == 5);
+    ASSERT(matchsRugbyInf(7,4).size() == 8);
+    ASSERT(matchsRugbyInf(10,4).size() == 17);
+    cout << "Fin des tests : matchs Rugby inf" << endl;
+}
+
+/** Retourne l'ensemble des configuations possible pour un score donné
+ * sans tenir compte de l'ordre
+ * en utilisant la fonction matchsRugbyInf
+ * @param le score
+ * @return une collection de vecteurs représentant des matchs
+ **/
+Collection matchsRugby2(int score) {
+    cerr << "Erreur : fonction non implantée" << endl; throw 0; // Supprimer cette ligne
+}
+
+/** Test de la fonction matchsRugby2
+ **/
+void testMatchsRugby2() {
+    cout << "Début des tests : matchs Rugby 2" << endl;
+    ASSERT(matchsRugby2(-5).size() == 0);
+    ASSERT(matchsRugby2(0).size() == 1);
+    ASSERT(matchsRugby2(1).size() == 0);
+    ASSERT(matchsRugby2(2).size() == 0);
+    ASSERT(matchsRugby2(3).size() == 2);
+    ASSERT(matchsRugby2(4).size() == 0);
+    ASSERT(matchsRugby2(5).size() == 1);
+    ASSERT(matchsRugby2(6).size() == 3);
+    ASSERT(matchsRugby2(7).size() == 1);
+    ASSERT(matchsRugby2(8).size() == 2);
+    ASSERT(matchsRugby2(9).size() == 4);
+    ASSERT(matchsRugby2(10).size() == 3);
+    ASSERT(matchsRugby2(50).size() == 106);
+    ASSERT(matchsRugby2(200).size() == 4820);
+    cout << "Fin des tests : matchs Rugby 2" << endl;
+}
+
+/******************************************/
+/**** Exercice 4 : Retour aux briques  ****/
+/******************************************/
+
+/** Retourne l'ensemble des "murs" de taille n formés de briques de taille 1 et 2
+ * c'est à dire, les vecteurs de valeurs 1 et 2 dont la somme est n
+ * @param n, un entier
+ * @return une Collection de vecteur
+ **/
+Collection mursFibonacci(int n) {
+    cerr << "Erreur : fonction non implantée" << endl; throw 0; // Supprimer cette ligne
+}
+
+/** Test de la fonction mursFibonacci
+ */
+void testMursFibonacci() {
+    cout << "Début des tests : murs fibonacci" << endl;
+    ASSERT(mursFibonacci(-5)==Collection());
+    ASSERT(mursFibonacci(0).size()==1);
+    ASSERT(mursFibonacci(1).size()==1);
+    ASSERT(mursFibonacci(2).size()==2);
+    ASSERT(mursFibonacci(3).size()==3);
+    ASSERT(mursFibonacci(4).size()==5);
+    ASSERT(mursFibonacci(5).size()==8);
+    ASSERT(mursFibonacci(6).size()==13);
+    ASSERT(mursFibonacci(7).size()==21);
+    Collection C = mursFibonacci(2);
+    vector<int> v1 = {1,1};
+    vector<int> v2 = {2};
+    ASSERT(v1 ==  C[0] or v1 == C[1]);
+    ASSERT(v2 ==  C[0] or v2 == C[1]);
+    C = mursFibonacci(7);
+    v1 = C[2];
+    int m1 = 0;
+    for(unsigned int i =0; i < v1.size(); i++) m1+=v1[i];
+    ASSERT(m1 == 7);
+    v2 = C[20];
+    int m2 = 0;
+    for(unsigned int i =0; i < v2.size(); i++) m2+=v2[i];
+    ASSERT(m2 == 7);
+    cout << "Fin des tests : murs fibonacci" << endl;
+}
+
+/** Retourne le nombre de murs de taille n composés de brique de longueur quelconque
+ * @param n, un entier
+ * @return le nombre de murs décrits
+ **/
+int nbMursToutesBriques(int n) {
+    cerr << "Erreur : fonction non implantée" << endl; throw 0; // Supprimer cette ligne
+}
+
+/** Test de la fonction nbMursToutesBriques
+ **/
+void testNbMursToutesBriques() {
+    cout << "Début des tests : murs toutes briques" << endl;
+    ASSERT(nbMursToutesBriques(-5) == 0);
+    ASSERT(nbMursToutesBriques(0) == 1);
+    ASSERT(nbMursToutesBriques(1) == 1);
+    ASSERT(nbMursToutesBriques(2) == 2);
+    ASSERT(nbMursToutesBriques(3) == 4);
+    ASSERT(nbMursToutesBriques(4) == 8);
+    ASSERT(nbMursToutesBriques(5) == 16);
+    ASSERT(nbMursToutesBriques(26) == 33554432);
+    cout << "Fin des tests : murs toutes briques" << endl;
+}
+
+/** Retourne le nombre de murs de taille n formés d'une succession de briques alternant
+ * nombres pairs et impairs
+ * @param n, un entier
+ * @return le nombre de murs décrits
+ **/
+int nbMursPairsImpairs(int n) {
+    cerr << "Erreur : fonction non implantée" << endl; throw 0; // Supprimer cette ligne
+}
+
+/** Test de la fonction nbMursPairsImpairs
+ **/
+void testNbMursPairsImpairs() {
+    cout << "Début des tests : murs pairs impairs" << endl;
+    ASSERT(nbMursPairsImpairs(-3) == 0);
+    ASSERT(nbMursPairsImpairs(0) == 1);
+    ASSERT(nbMursPairsImpairs(1) == 1);
+    ASSERT(nbMursPairsImpairs(2) == 1);
+    ASSERT(nbMursPairsImpairs(3) == 3);
+    ASSERT(nbMursPairsImpairs(4) == 2);
+    ASSERT(nbMursPairsImpairs(5) == 6);
+    ASSERT(nbMursPairsImpairs(10) == 37);
+    ASSERT(nbMursPairsImpairs(20) == 1874);
+    ASSERT(nbMursPairsImpairs(30) == 101393);
+    cout << "Fin des tests : murs pairs impairs" << endl;
+}
+
+int main() {
+    // testFibonacciRec();
+    // testFibonacciDyn();
+    // testRougeBleuRec();
+    // testRougeBleuDyn();
+    // testNbSeqRugbyRec();
+    // testNbSeqRugbyDyn();
+    // testAffichesCouples();
+    // testAffichesTriplets();
+    // afficheCollection(genere1Uplets(3));
+    // afficheCollection(genere2Uplets(3));
+    // afficheCollection(genere3Uplets(3));
+    // testGenere3Uplets();
+    // testGenerekUplets();
+    // testScoreRugby();
+    // afficheCollection(matchsRugby(10));
+    // testMatchsRugby();
+    // testMatchsRugbyInf();
+    // testMatchsRugby2();
+    // afficheCollection(mursFibonacci(5));
+    // testMursFibonacci();
+    // testNbMursToutesBriques();
+    // testNbMursPairsImpairs();
+}
diff --git a/content/docs/L2_MathInfo/TP3/TP3.pdf b/content/docs/L2_MathInfo/TP3/TP3.pdf
new file mode 100644
index 0000000000000000000000000000000000000000..cec0ae51edccdc6c84941ade56e400606a70c542
Binary files /dev/null and b/content/docs/L2_MathInfo/TP3/TP3.pdf differ
diff --git a/content/teaching/2016-09-01.md b/content/teaching/2016-09-01.md
index 5973c91c69c7fe988e014a9ffa9c8a0585f25334..e2f3ddf836ca6d542fc88c7cb958f1fc1e4a13a4 100644
--- a/content/teaching/2016-09-01.md
+++ b/content/teaching/2016-09-01.md
@@ -8,6 +8,7 @@ course_doc_link: L2_MathInfo/
 
  * [TP1.pdf](/~pons/docs/L2_MathInfo/TP1/TP1.pdf) -- [TP1.zip](/~pons/docs/L2_MathInfo/TP1.zip)
  * [TP2.pdf](/~pons/docs/L2_MathInfo/TP2/TP2.pdf) -- [TP2.zip](/~pons/docs/L2_MathInfo/TP2.zip)
+ * [TP3.pdf](/~pons/docs/L2_MathInfo/TP3/TP3.pdf) -- [TP3.zip](/~pons/docs/L2_MathInfo/TP3.zip)
 
 **Une note de TP sera donnée par le chargé de TP, voir les modalités avec votre
 chargé de TP**.