diff --git a/Projets/SUIVI_TEMPLATE.md b/Projets/SUIVI_TEMPLATE.md
new file mode 100644
index 0000000..d98fca2
--- /dev/null
+++ b/Projets/SUIVI_TEMPLATE.md
@@ -0,0 +1,72 @@
+# Suivi de projet — [Nom du projet]
+
+**Élève(s) :**
+**Classe :**
+**Projet :**
+**Date de début :**
+
+---
+
+## Journal de bord
+
+*Compléter après chaque séance.*
+
+### Séance 1 — [Date]
+
+**Objectif de la séance :**
+
+**Ce que j'ai fait :**
+
+**Difficultés rencontrées :**
+
+**Décisions prises et pourquoi :**
+
+**Ce qu'il reste à faire :**
+
+---
+
+### Séance 2 — [Date]
+
+**Objectif de la séance :**
+
+**Ce que j'ai fait :**
+
+**Difficultés rencontrées :**
+
+**Décisions prises et pourquoi :**
+
+**Ce qu'il reste à faire :**
+
+---
+
+*(Dupliquer le bloc ci-dessus pour chaque séance)*
+
+---
+
+## Bilan du projet
+
+### Ce qui fonctionne
+
+### Ce qui ne fonctionne pas encore (et pourquoi)
+
+### Choix techniques importants
+
+*Quelles décisions as-tu prises ? Pourquoi ce choix plutôt qu'un autre ?*
+
+### Ce que j'ai appris
+
+---
+
+## Préparation au Grand Oral
+
+*Le Grand Oral dure 20 minutes. Tu dois pouvoir présenter ton projet et répondre à des questions. Prépare-toi en répondant à ces questions :*
+
+**1. En quoi consiste ton projet ? Explique-le en 2 minutes à quelqu'un qui ne connaît pas l'informatique.**
+
+**2. Quelles notions du cours as-tu utilisées ? Donne un exemple concret dans ton code.**
+
+**3. Quelle a été la difficulté principale ? Comment l'as-tu résolue ?**
+
+**4. Qu'aurais-tu fait différemment si tu recommençais ?**
+
+**5. Quelle extension aimerais-tu implémenter si tu avais plus de temps ?**
diff --git a/Projets/fichier_suivi.md b/Projets/fichier_suivi.md
new file mode 100644
index 0000000..2c35932
--- /dev/null
+++ b/Projets/fichier_suivi.md
@@ -0,0 +1,596 @@
+## Les algorithmes génétiques
+
+* Présentation
+
+ - Les *algorithmes génétiques* font partie des algorithmes
+ évolutionnistes.
+ - S'inspirent des mécanismes de sélection naturelle pour approcher
+ une solution d'un problème *d'optimisation*.
+ - S'appliquent bien dans le cas où l'espace des solutions est grand.
+
+
+* Darwin
+
+ - /De l'origine des espèces/
+ - les individus les mieux adaptés à leur environnement survivent et
+ se reproduisent davantage en transmettant les variations utiles à
+ la survie.
+ - L'espèce évolue en s'adaptant à son environnement.
+ - C'est le principe de *sélection naturelle*
+
+
+* Sélection naturelle
+
+ Trois principes :
+ - Variation : les individus diffèrent les uns des autres et d'une
+ génération à l'autre ;
+ - Adaptation : les individus les mieux adaptés survivent et se
+ reproduisent davantage ;
+ - Hérédité : les caractéristiques sont héréditaires et se
+ transmettent de génération en génération.
+
+
+* Principes
+
+** Problèmes et solution
+
+ On dispose d'un problème d'optimisation :
+
+ $$\max_{s\in R}\lbrace f(s) \rbrace$$
+
+ - $R$ est l'espace des solutions *réalisables*
+ - $f$ est la fonction *objectif*, où encore :
+ - fonction d'évaluation ,
+ - fonction d'adaptation ,
+ - fonction de fitness.
+
+
+
+** Le principe des algorithmes génétiques
+
+ - travailler avec un sous-ensemble $P$ de $R$ appelé *population* ;
+ - On fait évoluer $P$ en lui appliquent des opérateurs génétiques
+ pour produire une nouvelle génération ;
+ - On favorise les individus les mieux adaptés (valeur de $f$ plus
+ élevée) lors de la production de la génération suivante ;
+ - Après $n$ générations, on choisit un individu dans la population.
+
+
+** génome
+
+ - Les individus sont représentés par leur génôme : suite finie de
+ $k$ symboles ;
+ - Ces symboles représentent les caractéristiques d'un individu,
+ c'est-à-dire un gène ;
+
+ Chercher la solution optimale consiste à chercher une séquence de
+ symboles optimale.
+
+ Idée à respecter : plus l'adaptation est élevée, plus l'individu
+ est proche de la solution.
+
+** Opérateurs génétiques
+
+ Il existe trois opérateurs génétiques :
+
+*** la *sélection*
+ choix des individus d'une population qui vont survivre à la
+ génération suivante :
+ - Les individus les mieux adaptés ont plus de
+ chance de survivre ;
+ - Méthode du /tournoi/ .
+
+
+*** le *croisement*
+
+ Combine les gènes de deux individus pour en produire deux
+ nouveaux :
+ - croisement **1 point** : découpe des deux génome au même
+ endroit, puis échange ,
+ - croisement **2 points** : découpe chacun des génomes en trois
+ portions , on échange les gènes des parties médianes.
+
+
+*** La *mutation*
+
+ - Mutation /aléatoire/ des caractéristiques d'un individu ;
+ - Réalisée avec une probabilité faible ;
+ - Permet de faire apparaitre dans une population de nouvelles
+ caractéristiques
+
+
+
+* L'algorithme génétique
+
+ Notre algorithme travaillera avec une population constante d'une
+ génération à l'autre.
+
+** Entrées
+ - la fonction de /fitness/ du problème ;
+ - le nombre d'individus $n$ pair ;
+ - le nombre de génération $g$ ;
+ - la probabilité de mutation $p$.
+
+
+** L'algorithme
+
+ 1. population $\leftarrow$ $n$ individus créés aléatoirement.
+ 2. calculer pour chaque individu de population son degré
+ d'adaptation.
+ 3. répéter $g$ fois
+ 4. $\quad$ next_gen_1 $\leftarrow$ sélectionner par tournoi
+ $\frac{n}{2}$ individus de la population
+ 5. $\quad$ next_gen_2 $\leftarrow$ créer $\frac{n}{2}$ individus
+ par croisement entre individus de population
+ 6. $\quad$ next_gen $\leftarrow$ next_gen_1 + next_gen_2
+ 7. $\quad$ faire muter chacun des individus de next_gen
+ 8. $\quad$ calculer pour chaque individu de next_gen son degré
+ d'adaptation
+ 9. $\quad$ meilleurs $\leftarrow$ les 5 individus les mieux adaptés de population
+ 10. $\quad$ retirer de next_gen les 5 individus les moins adaptés
+ 11. $\quad$ population $\leftarrow$ neilleurs + next_gen
+ 12. solution $\leftarrow$ individu le mieux adapté de population
+
+** Sélection par tournoi
+
+ - La sélection par tournoi dans une population de taille $n$
+ consiste à choisir aléatoirement deux individus de la population
+ pour ne garder que l'individu le mieux adapté des deux.
+ - On répète ce processus de sorte que chaque individu est choisi
+ exactement une fois. On obtient donc $\frac{n}{2}$ individus à la
+ fin de cette phase.
+
+** Croisements
+
+ - Croisement à un point
+ - On choisit aléatoirement deux individus de la population pour
+ construire deux nouveaux individus
+ - On applique ensuite un tournoi entre les deux individus produits
+ pour ne garder que le meilleur
+ - On répète ce processus de sorte que chaque individu est choisi
+ exactement une fois. On obtient donc $\frac{n}{2}$ individus à la
+ fin de cette phase.
+
+** Mutations
+
+ - Pour chacun des individus considérés, il y a une probabilité $p$
+ que chacune de ses caractéristiques mute. C'est-à-dire que la
+ valeur de cette caractéristique est modifiée
+ aléatoirement. L'individu est donc remplacé par sa /version
+ mutée/.
+
+ - À la fin de la population la taille de la population est la même.
+
+
+* Programmation
+
+ Plusieurs classes :
+ - l'algorithme génétique,
+ - le problème traité et
+ - les individus.
+
+
+
+** l'algorithme génétique
+
+ - classe `AlgoGen`.
+
+
+ #+begin_src python :tangle src/algo_gen.py :exports none
+ import random
+
+ BEST_KEPT = 5
+
+ class AlgoGen(object):
+
+ def __init__(self, problem, population_size, crossover_rate, mutation_probability):
+ '''
+ build an genetic algorithm to solve problem using a population of size population_size and a probability of muation of mutation_probability
+
+ :param problem: the problem to solve
+ :type problem: a Problem object
+ :param population_size: the size of the population (must be even)
+ :type population_size: int
+ :param mutation_probability: the mutation probability
+ :type mutation_probability: float
+ :UC: population_size must be even and mutation_probability must be 0<= and <1
+ '''
+ self.__problem = problem
+ self.__population_size = population_size
+ self.__population = []
+ self.__nb_crossover = crossover_rate
+ self.__mutation_probability = mutation_probability
+
+ def get_population(self):
+ return self.__population
+
+ def genesis(self):
+ """
+ create the population
+ """
+ pass
+
+ def evaluate_population(self, population):
+ """
+ evalue la population passée en paramètre
+ :param population: (list) la population
+ """
+ pass
+
+
+ def next_generation_tournament(self, population):
+ '''
+ organise un tournoi entre les individu d'une population .
+ chaque individu choisi une et une seule fois, dans un tournoi ,
+ vainqueur conservé taille résultat = 1/2 taille population
+
+ :param population: (list) la population
+ :return: (list) les vainqueurs du tournoi
+ '''
+ pass
+
+
+
+ def crossover(self, population):
+ '''Croise les individus d'une population.
+
+ Chaque individu est sélectionné une et une seule fois, on
+ garde le meilleur descendant à chaque fois.
+
+ taille résultat = 1/2 taille population
+
+ :param population: (list) a population
+ :return: (list) new individuals
+ '''
+
+ pass
+
+ def mutate(self, individuals):
+ """
+ mute les individus
+ :param individuals: (list) une liste des individus
+ """
+ pass
+
+ def one_round(self):
+ '''
+ applique successivement les opéréateurs
+ - selection
+ - croisement
+ - mutation
+ '''
+ pass
+
+
+ def solve(self, nb_rounds):
+ """
+ tente d'approcher une solution en faisant muter la population
+ :param nb_rounds: (int) nombre de génération
+ """
+ self.genesis()
+ self.evaluate_population(self.__population)
+ self.display_stat('INITIAL')
+ for step in range(nb_rounds):
+ self.one_round()
+ #self.display_population(step=step+1, number = 20)
+ self.display_stat(step)
+ #self.display_population(number = 20) # display 20 best individuals
+ return self.__problem.best_individual(self.__population)
+
+
+ def display_stat(self, step):
+ best = self.__problem.best_individual(self.__population)
+ all_scores = [ individual.get_score() for individual in self.__population ]
+ average = sum (all_scores) / self.__population_size
+ print ( ' STEP = {} -- best = {} - avg = {} '.format(step, best, average) )
+
+
+ def display_population(self, step = ' ', number = 0):
+ if number <= 0:
+ individuals = self.__population
+ else:
+ individuals = self.__population[:min(number, len(self.__population))]
+ print( ' **** STEP : {} ********* '.format(step) )
+ for individual in individuals :
+ print ( individual )
+ print( )
+
+
+ # tool function
+ def biased_wheel(alea,scores):
+ '''
+ return smallest i such that alea < sum(scores[k], 0 <= k < i)
+ CU : 0 <= alea < sum(scores)
+ '''
+ current_sum = 0
+ result_index = -1
+ while alea > current_sum :
+ result_index = result_index + 1
+ current_sum = current_sum + scores[result_index]
+ return result_index
+ #+end_src
+
+** les problèmes
+
+ Comme indiqué, les classes pour représenter les problèmes devront
+ partager certaines méthodes. Nous suggérons les méthodes suivantes
+ comme méthodes communes aux problèmes. Evidemment, il peut exister
+ d'autres méthodes spécifiques à chacun des problèmes. Notamment la
+ manière de calculer l'adaptation d'un individu variera.
+
+ #+begin_src python :tangle src/problem_interface.py :exports none
+ class Problem_Interface(object):
+ '''
+ a prototype class for "problems" in genetic algorithm
+
+ an Individual class must be associated to a problem to represent the individuals
+ '''
+
+ def create_individual(self):
+ '''
+ create a randomly generated indidivual for this problem
+
+ :return: a randomly generated individual gfor this problem
+ :rtype: an Individual object
+ '''
+ pass
+
+ def evaluate_fitness(self, individual):
+ '''
+ compute the fitness of individual for this problem
+
+ :param individual: the individual to consider
+ :type individual: an Individual object
+ :return: the fitness of individual for this problem
+ :rtype: an Individual object
+ '''
+ pass
+
+ def sort_population(self, population):
+ '''
+ sort population from best fitted to worst fitted individuals.
+ Depending on the problem, it can correspond to ascending or descending order with respect to the fitness function.
+
+ side effect : population is modified by this method
+
+ :param population: the list of individuals to sort
+ :type population: list(Individual)
+ '''
+ pass
+
+ def best_individual(self, population):
+ '''
+ return the best fitted individual from population.
+ Depending on the problem, it can correspond to the individual with the highest or the lowest fitness value.
+
+
+ :param population: the list of individuals to sort
+ :type population: list(Individual)
+ :return: the best fitted individual of population
+ :rtype: an Individual object
+ '''
+ pass
+
+ def tournament(self, first, second):
+ '''
+ perform a rounament between two individuals, the winner is the most fitted one, it is returned
+
+
+ :param first: an individual
+ :type first: an Indivdual object
+ :param second: an individual
+ :type second: an Individual object
+ :return: the winner of the tournament
+ :rtype: Individual object
+ '''
+ pass
+ #+end_src
+
+** les individus
+
+ Les classes pour les individus devront partager certaines
+ méthodes. Nous suggérons les méthodes suivantes comme méthodes
+ communes aux individus. Evidemment, il peut exister d'autres méthodes
+ spécifiques à chacun des individus, et notamment, les valeurs des
+ génomes vont différer.
+
+ #+begin_src python :tangle src/individual_interface.py :exports none
+ import random
+
+
+ class Individual_Interface(object):
+ '''
+ an Individual in genteic algorithm problem
+
+ the value (or genome) of an indal is a sequence (e.g string or list) of a fixed size
+
+ an individual has a fitness score
+ '''
+
+
+
+ def __init__(self, size):
+ '''
+ create an Individual object, its genome value is randomly built. Initially score is not set.
+
+ :param size: size of the genome
+ :type size: int
+ '''
+ self.__score = None
+ self.__size = size
+ self.__value = self.init_value()
+
+ def copy(self):
+ '''
+ build a copy of self, the genome is a copy of self's genome
+
+ :return: a new Individual which is a "clone" of self
+ :rtype: an Individual object
+ '''
+ return None
+
+ def get_size(self):
+ '''
+ :return: the size of self's genome
+ :rtype: int
+ '''
+
+ return self.__size
+
+ def get_score(self):
+ '''
+ :return: the fitness score of self
+ :rtype: number
+ '''
+ return self.__score
+
+ def set_score(self, new_score):
+ '''
+ change the fitness score of self
+
+ :param new_score: the new fitness score
+ :type new_score: number
+ '''
+ self.__score = new_score
+
+ def __str__(self):
+ return "{} ({})".format(self.__value, self.__score)
+
+ def __repr__(self):
+ return self.__str__()
+
+ def get_value(self):
+ '''
+ :return: the genome of self
+ :rtype: sequence
+ '''
+ return self.__value
+
+ def set_value(self, new_value):
+ '''
+ change the genome value of self
+
+ :param new_score: the new genome value
+ :type new_score: sequence
+ '''
+ self.__value = new_value
+
+ def init_value(self):
+ '''
+ randomly initialize the genome value of self
+ '''
+ return None
+
+ def evaluate(self,problem):
+ '''
+ set the fitness score with the fitness computed by problem for self
+
+ :param problem: the problem
+ :type problem: a Problem object
+ '''
+ self.set_score(problem.evaluate_fitness(self))
+
+ def cross_with(self, other):
+ '''
+ perform a 1 point crossover between self and other, two new built individuals are returned
+
+ :param other: the individual to croww with
+ :type other: an Idnividual object
+ :return: the two new Individuals built by 1 point crossover operation
+ :rtype: 2-uple of individuals
+ '''
+ pass
+
+
+
+ def mutate(self, probability):
+ '''
+ apply mutation operation to self : each element of the geome sequence is randomly changed with given probabiliy
+
+ side effect : self's genome is modified
+
+ :param probability: the probability of mutation for every gene
+ :type probability: float
+ :UC: probability in [0,1[
+ '''
+ pass
+
+ def mutate_gene(self, gene):
+ pass
+ #+end_src
+
+
+* Problème 1 : Calcul de la valeur maximale d'une fonction
+
+ Problème : trouver dans un intervalle $[x_\mbox{min};x_\mbox{max}]$
+ une valeur de $x$ pour laquelle $f(x)$ est maximale.
+
+
+
+* Problème 2 : Recherche d'un message "secret"
+
+** Description
+ Cette fois, il ne s'agit pas à proprement parler d'un problème à
+ résoudre, puisqu'on en connaît la solution au départ... Ce second
+ exemple a pour objectif d'illustrer que les algorithmes génétiques
+ peuvent trouver une solution dans un très grand espace de recherche.
+
+** Problème
+ Le problème est celui de faire trouver une chaîne de caractères à un
+ algorithme génétique. On suppose cette chaîne construite à partir du
+ caractère espace et des 26 lettres de l'alphabet (minuscules et non
+ accentuées). Si elle est le longueur 30, il existe alors *27^30*
+ chaînes possibles.
+
+ Nous allons donc vérifier qu'en explorant qu'une petite partie de
+ toutes ces possibilités, un
+ algorithme génétique est capable de trouver l'une d'entre elles.
+
+
+ Par exemple, nous allons considérer la chaine
+ *secret* = ~'ceci est un secret a retrouver'~.
+
+
+* Problème 3 : Recherche d'un chemin dans un labyrinthe
+
+** Labyrinthe
+
+ #+begin_example
+ 7;7
+ +-+-+-+-+-+-+-+
+ | | |
+ + + +-+ + +-+ +
+ | | | | |
+ + + +-+ + + + +
+ | | | | |
+ + +-+ +-+-+ + +
+ | | | |
+ + + +-+-+ +-+-+
+ | | | |
+ + +-+-+ + +-+ +
+ | | | | |
+ + + + +-+-+ +-+
+ | | |
+ +-+-+-+-+-+-+-+
+
+ #+end_example
+
+** Problème
+ Le problème consiste à trouver dans un tel labyrinthe de taille *N*
+ (ici *N=7x7=49*) donné, un chemin entre la case d'entrée située en
+ haut à gauche et celle de sortie située en bas à droite.
+
+ Pour simplifier on considère que les largeur et hauteur du
+ labyrinthe sont identiques.
+
+
+** Matériel
+
+ - une classe ~Maze~ permettant de gérer les labyrinthes (fichier ~maze.py~);
+ - des exemples de labyrinthe (fichier ~maze.zip~)
+
+
+* Problème 4 : le TSP
+
+ Utiliser un algorithme génétique pour approcher une solution du
+ Problème du voyageur de commerce.
diff --git a/Projets/jeu_de_la_vie/JALONS.md b/Projets/jeu_de_la_vie/JALONS.md
new file mode 100644
index 0000000..bbcb2a0
--- /dev/null
+++ b/Projets/jeu_de_la_vie/JALONS.md
@@ -0,0 +1,80 @@
+# Jalons — Le Jeu de la Vie
+
+> Progression suggérée sur ~10 séances (septembre → février)
+
+---
+
+## Phase 1 — Analyse et modélisation (Séances 1-2)
+
+**Objectif :** Comprendre le problème et choisir les structures de données.
+
+- Lire les règles de Conway et les reformuler avec ses propres mots
+- Dessiner à la main quelques générations d'une configuration simple (ex. 3 cellules en ligne)
+- Choisir une représentation de la grille : liste 2D, dictionnaire `{(i,j): état}` ?
+- Écrire la fonction `creer_grille(n, m)` → grille vide de n lignes et m colonnes
+- Écrire la fonction `afficher_grille(grille)` → affichage terminal
+
+**Questions à se poser :**
+- Comment représenter une cellule morte / vivante en Python ?
+- Que se passe-t-il aux bords de la grille ?
+
+---
+
+## Phase 2 — Règles du jeu (Séances 3-4)
+
+**Objectif :** Implémenter le cœur de la simulation.
+
+- Écrire `compter_voisins(grille, i, j)` → nombre de voisins vivants de la cellule (i, j)
+- Écrire `etat_suivant(etat, nb_voisins)` → applique les 4 règles, renvoie le nouvel état
+- Écrire `generation_suivante(grille)` → calcule la grille à l'étape suivante
+- Tester manuellement sur un petit exemple (3×3)
+
+**Point d'attention :** la prochaine génération doit être calculée **simultanément** pour toutes les cellules — on ne modifie pas la grille en cours de calcul.
+
+---
+
+## Phase 3 — Simulation et configurations (Séances 5-6)
+
+**Objectif :** Lancer une simulation complète et observer des comportements.
+
+- Écrire `simuler(grille, nb_generations)` → boucle principale
+- Tester sur les configurations classiques :
+ - **Bloc** (stable)
+ - **Clignotant** (oscillateur période 2)
+ - **Planeur** (se déplace)
+- Observer : certaines configurations sont-elles stables ? Oscillantes ? Chaotiques ?
+
+---
+
+## Phase 4 — Affichage graphique (Séances 7-8)
+
+**Objectif :** Rendre la simulation visuelle et interactive.
+
+- Choisir une bibliothèque graphique : Pyxel, matplotlib (animation), tkinter
+- Afficher la grille avec des cellules colorées
+- Animer la simulation pas à pas avec un délai configurable
+- (Extension) Permettre à l'utilisateur de cliquer pour activer/désactiver des cellules
+
+---
+
+## Phase 5 — Finitions et documentation (Séances 9-10)
+
+**Objectif :** Préparer le rendu et le Grand Oral.
+
+- Nettoyer le code, ajouter des docstrings
+- Rédiger un README personnel décrivant le projet et les choix techniques
+- Compléter le `SUIVI.md`
+- Préparer 2-3 questions pour le Grand Oral (voir `SUIVI.md`)
+
+---
+
+## Idées d'extension avancée
+
+- **Grille torique** : `i % n` et `j % m` pour que les bords se rejoignent
+- **Statistiques** : tracer le nombre de cellules vivantes par génération (matplotlib)
+- **Chargement de patterns** : lire des fichiers `.rle` (format standard des patterns Conway)
+- **Détection de stabilité** : arrêter la simulation quand la grille ne change plus
+
+---
+
+Auteur : Florian Mathieu — Licence CC BY NC
diff --git a/Projets/jeu_de_la_vie/README.md b/Projets/jeu_de_la_vie/README.md
new file mode 100644
index 0000000..a505bbf
--- /dev/null
+++ b/Projets/jeu_de_la_vie/README.md
@@ -0,0 +1,54 @@
+# Projet — Le Jeu de la Vie
+
+> En 1970, le mathématicien John Horton Conway invente un automate cellulaire capable de générer une vie artificielle à partir de quatre règles simples. Cinquante ans plus tard, des chercheurs utilisent encore ce modèle pour simuler des phénomènes biologiques, sociaux et physiques.
+
+## Contexte
+
+Le **Jeu de la Vie** est un automate cellulaire qui se déroule sur une grille infinie (ou torique) de cellules. Chaque cellule est soit **vivante**, soit **morte**. À chaque génération, l'état de chaque cellule évolue selon quatre règles appliquées simultanément :
+
+1. Une cellule vivante avec **moins de 2 voisins vivants** meurt (sous-population).
+2. Une cellule vivante avec **2 ou 3 voisins vivants** survit.
+3. Une cellule vivante avec **plus de 3 voisins vivants** meurt (surpopulation).
+4. Une cellule morte avec **exactement 3 voisins vivants** devient vivante (reproduction).
+
+Ces règles font émerger des comportements complexes : structures stables, oscillateurs, planeurs...
+
+## Compétences mobilisées
+
+| Notion | Chapitre du cours |
+|--------|-------------------|
+| Listes 2D (grille) | Programmation |
+| Fonctions pures | Paradigmes |
+| Classes et objets | POO |
+| Récursivité / itération | Récursivité |
+| Visualisation (matplotlib / Pyxel) | — |
+
+## Cahier des charges
+
+### Fonctionnalités minimales
+
+- [ ] Représenter la grille sous forme de liste 2D (ou dictionnaire)
+- [ ] Calculer le nombre de voisins vivants d'une cellule
+- [ ] Appliquer les 4 règles pour calculer la génération suivante
+- [ ] Afficher la grille dans le terminal (caractères `█` / `.`)
+- [ ] Lancer la simulation sur N générations
+
+### Extensions possibles
+
+- [ ] Affichage graphique animé (Pyxel, matplotlib, tkinter)
+- [ ] Grille torique (les bords se rejoignent)
+- [ ] Charger des configurations célèbres (planeur, canon à planeurs, pulsar...)
+- [ ] Compter et tracer l'évolution du nombre de cellules vivantes
+- [ ] Permettre à l'utilisateur de dessiner une configuration initiale
+- [ ] Détecter automatiquement les structures stables et les oscillateurs
+
+## Ressources
+
+- `5_projet_le_jeu_de_la_vie.pdf` — consignes détaillées (dans le dossier parent)
+- [Conway's Game of Life — Wikipedia](https://fr.wikipedia.org/wiki/Jeu_de_la_vie)
+- [LifeWiki — patterns célèbres](https://conwaylife.com/wiki/)
+- [Pyxel — moteur graphique Python](https://github.com/kitao/pyxel)
+
+---
+
+Auteur : Florian Mathieu — Licence CC BY NC
diff --git a/Projets/jeu_de_la_vie/SUIVI.md b/Projets/jeu_de_la_vie/SUIVI.md
new file mode 100644
index 0000000..d98fca2
--- /dev/null
+++ b/Projets/jeu_de_la_vie/SUIVI.md
@@ -0,0 +1,72 @@
+# Suivi de projet — [Nom du projet]
+
+**Élève(s) :**
+**Classe :**
+**Projet :**
+**Date de début :**
+
+---
+
+## Journal de bord
+
+*Compléter après chaque séance.*
+
+### Séance 1 — [Date]
+
+**Objectif de la séance :**
+
+**Ce que j'ai fait :**
+
+**Difficultés rencontrées :**
+
+**Décisions prises et pourquoi :**
+
+**Ce qu'il reste à faire :**
+
+---
+
+### Séance 2 — [Date]
+
+**Objectif de la séance :**
+
+**Ce que j'ai fait :**
+
+**Difficultés rencontrées :**
+
+**Décisions prises et pourquoi :**
+
+**Ce qu'il reste à faire :**
+
+---
+
+*(Dupliquer le bloc ci-dessus pour chaque séance)*
+
+---
+
+## Bilan du projet
+
+### Ce qui fonctionne
+
+### Ce qui ne fonctionne pas encore (et pourquoi)
+
+### Choix techniques importants
+
+*Quelles décisions as-tu prises ? Pourquoi ce choix plutôt qu'un autre ?*
+
+### Ce que j'ai appris
+
+---
+
+## Préparation au Grand Oral
+
+*Le Grand Oral dure 20 minutes. Tu dois pouvoir présenter ton projet et répondre à des questions. Prépare-toi en répondant à ces questions :*
+
+**1. En quoi consiste ton projet ? Explique-le en 2 minutes à quelqu'un qui ne connaît pas l'informatique.**
+
+**2. Quelles notions du cours as-tu utilisées ? Donne un exemple concret dans ton code.**
+
+**3. Quelle a été la difficulté principale ? Comment l'as-tu résolue ?**
+
+**4. Qu'aurais-tu fait différemment si tu recommençais ?**
+
+**5. Quelle extension aimerais-tu implémenter si tu avais plus de temps ?**
diff --git a/Projets/labyrinthe/JALONS.md b/Projets/labyrinthe/JALONS.md
new file mode 100644
index 0000000..33a553c
--- /dev/null
+++ b/Projets/labyrinthe/JALONS.md
@@ -0,0 +1,88 @@
+# Jalons — Labyrinthe
+
+> Progression suggérée sur ~10 séances (septembre → février)
+
+---
+
+## Phase 1 — Modélisation (Séances 1-2)
+
+**Objectif :** Représenter un labyrinthe en Python.
+
+- Étudier la classe `Maze` dans `../src/maze.py` : comment est codé le labyrinthe ? Quelles méthodes sont disponibles ?
+- Choisir une représentation : dictionnaire `{cellule: [voisins accessibles]}` ou grille 2D avec murs
+- Écrire `creer_grille(n, m)` → grille n×m avec tous les murs fermés
+- Écrire `afficher(grille)` → affichage terminal avec `+`, `-`, `|`, ` `
+
+**Exemple de représentation :**
+```
++--+--+--+
+| | |
++ +--+ +
+| | |
++--+--+--+
+```
+
+---
+
+## Phase 2 — Génération (Séances 3-4)
+
+**Objectif :** Générer un labyrinthe parfait aléatoirement.
+
+**Algorithme DFS récursif (backtracking) :**
+1. Partir d'une cellule aléatoire, la marquer comme visitée
+2. Choisir aléatoirement un voisin non visité
+3. Supprimer le mur entre les deux cellules
+4. Appeler récursivement depuis le voisin
+5. Si aucun voisin non visité : revenir en arrière (backtrack)
+
+- Implémenter `generer_dfs(grille, cellule)` de manière récursive
+- Tester sur un labyrinthe 5×5, puis 20×20
+- Observer : le labyrinthe est-il toujours parfait (sans cycle) ?
+
+---
+
+## Phase 3 — Résolution (Séances 5-6)
+
+**Objectif :** Trouver le chemin de l'entrée à la sortie.
+
+- Implémenter `resoudre_bfs(grille, entree, sortie)` → plus court chemin (largeur d'abord)
+- Implémenter `resoudre_dfs(grille, entree, sortie)` → premier chemin trouvé (profondeur d'abord)
+- Comparer les deux : même longueur de chemin ? Même rapidité ?
+- Afficher le chemin dans le labyrinthe (ex. cellules marquées `*`)
+
+**Point clé :** dans un labyrinthe parfait, BFS et DFS trouvent tous les deux le chemin (unique), mais BFS garantit qu'il est le plus court.
+
+---
+
+## Phase 4 — Affichage graphique (Séances 7-8)
+
+**Objectif :** Visualiser la génération et la résolution.
+
+- Choisir une bibliothèque graphique (Pyxel, tkinter, pygame)
+- Afficher le labyrinthe avec des rectangles
+- Animer la génération cellule par cellule
+- Afficher le chemin solution en couleur
+
+---
+
+## Phase 5 — Finitions et documentation (Séances 9-10)
+
+**Objectif :** Préparer le rendu et le Grand Oral.
+
+- Nettoyer le code, ajouter des docstrings
+- Mesurer les performances : temps de génération selon la taille (10×10, 50×50, 100×100)
+- Compléter le `SUIVI.md`
+- Préparer 2-3 questions pour le Grand Oral
+
+---
+
+## Idées d'extension avancée
+
+- **A\*** : heuristique distance de Manhattan pour guider la recherche vers la sortie
+- **Kruskal** : algorithme de génération alternatif (union-find)
+- **Résolution par algo génétique** : utiliser le framework du projet `mastermind/`
+- **Labyrinthe 3D** : extension vers une grille à 3 dimensions
+
+---
+
+Auteur : Florian Mathieu — Licence CC BY NC
diff --git a/Projets/labyrinthe/README.md b/Projets/labyrinthe/README.md
new file mode 100644
index 0000000..9c6aa0b
--- /dev/null
+++ b/Projets/labyrinthe/README.md
@@ -0,0 +1,51 @@
+# Projet — Labyrinthe
+
+> Générer un labyrinthe parfait (sans boucles, avec un unique chemin entre deux cases) et le résoudre automatiquement — un problème classique qui mobilise graphes, récursivité et algorithmique de recherche.
+
+## Contexte
+
+Un **labyrinthe parfait** est un graphe dans lequel il existe exactement un chemin entre n'importe quelle paire de cellules. Le générer revient à construire un arbre couvrant d'une grille ; le résoudre revient à parcourir ce graphe de l'entrée à la sortie.
+
+Ce projet relie directement le chapitre **Graphes** et le chapitre **Récursivité** du programme de Terminale NSI.
+
+Une base de code est disponible dans `../src/maze.py` : la classe `Maze` lit un labyrinthe depuis un fichier texte et permet de tester un chemin.
+
+## Compétences mobilisées
+
+| Notion | Chapitre du cours |
+|--------|-------------------|
+| Graphes, arbres couvrants | Graphes |
+| Parcours DFS / BFS | Graphes, Récursivité |
+| Récursivité et pile d'appels | Récursivité |
+| Classes et encapsulation | POO |
+| Représentation par dictionnaire | Programmation |
+
+## Cahier des charges
+
+### Fonctionnalités minimales
+
+- [ ] Représenter un labyrinthe sous forme de graphe (dictionnaire de voisins)
+- [ ] Générer un labyrinthe parfait aléatoire (algorithme DFS récursif ou union-find/Kruskal)
+- [ ] Afficher le labyrinthe dans le terminal (avec `+`, `-`, `|`, ` `)
+- [ ] Résoudre le labyrinthe (trouver un chemin de l'entrée à la sortie) avec BFS ou DFS
+- [ ] Afficher le chemin solution
+
+### Extensions possibles
+
+- [ ] Affichage graphique (Pyxel, tkinter)
+- [ ] Visualisation animée de la génération et de la résolution
+- [ ] Comparer BFS (plus court chemin) et DFS (premier chemin trouvé)
+- [ ] Implémenter l'algorithme A* (heuristique distance de Manhattan)
+- [ ] Résolution par algorithme génétique (en lien avec le projet `mastermind/`)
+- [ ] Mesurer les performances selon la taille du labyrinthe
+
+## Ressources
+
+- `../src/maze.py` — classe `Maze` de base (lecture depuis fichier texte)
+- `../src/maze.zip` — archive complète avec exemples de labyrinthes
+- [Maze generation algorithms — Wikipedia](https://en.wikipedia.org/wiki/Maze_generation_algorithm)
+- [Algorithme A* — Wikipedia](https://fr.wikipedia.org/wiki/Algorithme_A*)
+
+---
+
+Auteur : Florian Mathieu — Licence CC BY NC
diff --git a/Projets/labyrinthe/SUIVI.md b/Projets/labyrinthe/SUIVI.md
new file mode 100644
index 0000000..d98fca2
--- /dev/null
+++ b/Projets/labyrinthe/SUIVI.md
@@ -0,0 +1,72 @@
+# Suivi de projet — [Nom du projet]
+
+**Élève(s) :**
+**Classe :**
+**Projet :**
+**Date de début :**
+
+---
+
+## Journal de bord
+
+*Compléter après chaque séance.*
+
+### Séance 1 — [Date]
+
+**Objectif de la séance :**
+
+**Ce que j'ai fait :**
+
+**Difficultés rencontrées :**
+
+**Décisions prises et pourquoi :**
+
+**Ce qu'il reste à faire :**
+
+---
+
+### Séance 2 — [Date]
+
+**Objectif de la séance :**
+
+**Ce que j'ai fait :**
+
+**Difficultés rencontrées :**
+
+**Décisions prises et pourquoi :**
+
+**Ce qu'il reste à faire :**
+
+---
+
+*(Dupliquer le bloc ci-dessus pour chaque séance)*
+
+---
+
+## Bilan du projet
+
+### Ce qui fonctionne
+
+### Ce qui ne fonctionne pas encore (et pourquoi)
+
+### Choix techniques importants
+
+*Quelles décisions as-tu prises ? Pourquoi ce choix plutôt qu'un autre ?*
+
+### Ce que j'ai appris
+
+---
+
+## Préparation au Grand Oral
+
+*Le Grand Oral dure 20 minutes. Tu dois pouvoir présenter ton projet et répondre à des questions. Prépare-toi en répondant à ces questions :*
+
+**1. En quoi consiste ton projet ? Explique-le en 2 minutes à quelqu'un qui ne connaît pas l'informatique.**
+
+**2. Quelles notions du cours as-tu utilisées ? Donne un exemple concret dans ton code.**
+
+**3. Quelle a été la difficulté principale ? Comment l'as-tu résolue ?**
+
+**4. Qu'aurais-tu fait différemment si tu recommençais ?**
+
+**5. Quelle extension aimerais-tu implémenter si tu avais plus de temps ?**
diff --git a/Projets/mastermind/JALONS.md b/Projets/mastermind/JALONS.md
new file mode 100644
index 0000000..13e7539
--- /dev/null
+++ b/Projets/mastermind/JALONS.md
@@ -0,0 +1,80 @@
+# Jalons — Mastermind & Algorithmes Génétiques
+
+> Progression suggérée sur ~10 séances (septembre → février)
+
+---
+
+## Phase 1 — Comprendre les algorithmes génétiques (Séances 1-2)
+
+**Objectif :** Saisir l'analogie entre évolution biologique et optimisation.
+
+- Lire la fiche `../src/src_mastermind_fiche.md` du début jusqu'à la section "Les individus"
+- Répondre aux questions : qu'est-ce qu'un individu ? une population ? le fitness ? la sélection ?
+- Schématiser à la main le cycle d'un algorithme génétique :
+ ```
+ Génèse → Évaluation → Sélection → Croisement → Mutation → [retour Évaluation]
+ ```
+- Expliquer en une phrase comment cet algorithme peut résoudre le Mastermind
+
+---
+
+## Phase 2 — L'individu : la classe Combinaison (Séances 3-4)
+
+**Objectif :** Implémenter la brique de base.
+
+- Implémenter `init_value(self)` → génère une combinaison aléatoire de couleurs
+- Implémenter `cross_with(self, other)` → croisement en 1 point (renvoie 2 enfants)
+- Implémenter `mutate_gene(self, gene)` → remplace un gène par une autre couleur aléatoire
+- Tester chaque méthode indépendamment avant de passer à la suite
+
+**Point clé :** le croisement en 1 point prend un indice aléatoire et échange les parties.
+
+---
+
+## Phase 3 — Le problème : la classe Mastermind (Séances 5-6)
+
+**Objectif :** Définir comment évaluer une combinaison.
+
+- Implémenter `create_individual(self)` → crée un individu aléatoire du bon type
+- Implémenter `evaluate_fitness(self, individual)` → compte les gènes bien placés
+- Implémenter `best_individual(self, population)` → renvoie le meilleur de la population
+- Implémenter `tournament(self, first, second)` → compare deux individus, garde le meilleur
+- Tester avec une combinaison cible connue et vérifier que le score est correct
+
+---
+
+## Phase 4 — L'algorithme : la classe AlgoGen (Séances 7-8)
+
+**Objectif :** Assembler toutes les briques.
+
+- Implémenter `genesis(self)` → crée la population initiale
+- Implémenter `evaluate_population(self, population)` → évalue tous les individus
+- Implémenter `next_generation_tournament(self, population)` → sélection par tournoi
+- Implémenter `crossover(self, population)` → croisements entre les meilleurs
+- Implémenter `mutate(self, individuals)` → applique les mutations
+- Implémenter `solve(self, nb_generations)` → boucle principale
+
+---
+
+## Phase 5 — Tests, ajustement et documentation (Séances 9-10)
+
+**Objectif :** Valider et optimiser.
+
+- Tester avec la combinaison exemple : `Mastermind(["bleu", "blanc", "blanc", "rouge"])`
+- Faire varier les paramètres : taille de population, probabilité de mutation, taux de croisement
+- Observer : combien de générations faut-il en moyenne pour trouver la solution ?
+- Tracer la courbe de convergence (fitness max par génération)
+- Compléter le `SUIVI.md` et préparer les questions pour le Grand Oral
+
+---
+
+## Idées d'extension avancée
+
+- **Nouveau problème** : adapter le framework à un autre problème (labyrinthe, sac à dos, TSP...)
+- **Roulette vs tournoi** : implémenter une sélection par roulette et comparer les performances
+- **Mastermind jouable** : ajouter une interface où un humain joue contre l'IA
+- **Parallélisation** : tester plusieurs populations en parallèle et garder la meilleure
+
+---
+
+Auteur : Florian Mathieu — Licence CC BY NC
diff --git a/Projets/mastermind/README.md b/Projets/mastermind/README.md
new file mode 100644
index 0000000..7365da4
--- /dev/null
+++ b/Projets/mastermind/README.md
@@ -0,0 +1,53 @@
+# Projet — Mastermind & Algorithmes Génétiques
+
+> Darwin rencontre la programmation : faire évoluer une population de combinaisons pour qu'elle converge vers la solution cachée du Mastermind — sans jamais la connaître à l'avance.
+
+## Contexte
+
+Le **Mastermind** est un jeu de déduction : un joueur choisit une combinaison secrète de 4 couleurs parmi 8, l'autre doit la deviner en un minimum d'essais.
+
+Plutôt que de coder une IA par force brute, ce projet applique un **algorithme génétique** : on fait évoluer une population de combinaisons candidates en s'inspirant de la sélection naturelle (tournoi, croisement, mutation) jusqu'à trouver la solution.
+
+Une base de code complète est disponible dans `../src/` :
+- `algo_gen.py` — framework de l'algorithme génétique
+- `combinaison.py` — représentation d'un individu (une combinaison)
+- `src_mastermind_fiche.md` — fiche TP détaillée avec toutes les consignes
+
+## Compétences mobilisées
+
+| Notion | Chapitre du cours |
+|--------|-------------------|
+| Classes, héritage, encapsulation | POO |
+| Paradigme fonctionnel (fonctions pures) | Paradigmes |
+| Algorithmes d'optimisation | Algorithmique |
+| Listes, compréhensions de listes | Programmation |
+| Probabilités appliquées | — |
+
+## Cahier des charges
+
+### Fonctionnalités minimales
+
+- [ ] Implémenter la classe `Combinaison` (individu) : création aléatoire, croisement, mutation
+- [ ] Implémenter la classe `Mastermind` (problème) : évaluation du fitness, tournoi
+- [ ] Implémenter la classe `AlgoGen` : génèse, sélection, croisement, mutation, solve
+- [ ] Résoudre une combinaison cible en un nombre raisonnable de générations
+- [ ] Afficher l'évolution du meilleur individu à chaque génération
+
+### Extensions possibles
+
+- [ ] Adapter le framework à un autre problème (labyrinthe, sac à dos...)
+- [ ] Comparer plusieurs stratégies de sélection (tournoi vs roulette)
+- [ ] Tracer la courbe de convergence (fitness max par génération)
+- [ ] Implémenter un Mastermind jouable par un humain vs l'IA
+
+## Ressources
+
+- `../src/src_mastermind_fiche.md` — fiche TP complète avec toutes les consignes
+- `../src/algo_gen.py` — squelette du framework générique
+- `../src/combinaison.py` — classe individu à compléter
+- [Algorithme génétique — Wikipedia](https://fr.wikipedia.org/wiki/Algorithme_génétique)
+- [Mastermind — Wikipedia](https://fr.wikipedia.org/wiki/Mastermind)
+
+---
+
+Auteur : Florian Mathieu — Licence CC BY NC
diff --git a/Projets/mastermind/SUIVI.md b/Projets/mastermind/SUIVI.md
new file mode 100644
index 0000000..d98fca2
--- /dev/null
+++ b/Projets/mastermind/SUIVI.md
@@ -0,0 +1,72 @@
+# Suivi de projet — [Nom du projet]
+
+**Élève(s) :**
+**Classe :**
+**Projet :**
+**Date de début :**
+
+---
+
+## Journal de bord
+
+*Compléter après chaque séance.*
+
+### Séance 1 — [Date]
+
+**Objectif de la séance :**
+
+**Ce que j'ai fait :**
+
+**Difficultés rencontrées :**
+
+**Décisions prises et pourquoi :**
+
+**Ce qu'il reste à faire :**
+
+---
+
+### Séance 2 — [Date]
+
+**Objectif de la séance :**
+
+**Ce que j'ai fait :**
+
+**Difficultés rencontrées :**
+
+**Décisions prises et pourquoi :**
+
+**Ce qu'il reste à faire :**
+
+---
+
+*(Dupliquer le bloc ci-dessus pour chaque séance)*
+
+---
+
+## Bilan du projet
+
+### Ce qui fonctionne
+
+### Ce qui ne fonctionne pas encore (et pourquoi)
+
+### Choix techniques importants
+
+*Quelles décisions as-tu prises ? Pourquoi ce choix plutôt qu'un autre ?*
+
+### Ce que j'ai appris
+
+---
+
+## Préparation au Grand Oral
+
+*Le Grand Oral dure 20 minutes. Tu dois pouvoir présenter ton projet et répondre à des questions. Prépare-toi en répondant à ces questions :*
+
+**1. En quoi consiste ton projet ? Explique-le en 2 minutes à quelqu'un qui ne connaît pas l'informatique.**
+
+**2. Quelles notions du cours as-tu utilisées ? Donne un exemple concret dans ton code.**
+
+**3. Quelle a été la difficulté principale ? Comment l'as-tu résolue ?**
+
+**4. Qu'aurais-tu fait différemment si tu recommençais ?**
+
+**5. Quelle extension aimerais-tu implémenter si tu avais plus de temps ?**
diff --git a/Projets/pyxel_text.py b/Projets/pyxel_text.py
new file mode 100644
index 0000000..7be06aa
--- /dev/null
+++ b/Projets/pyxel_text.py
@@ -0,0 +1,329 @@
+"""
+Module de gestion de texte pour Pyxel
+Permet d'afficher du texte et de capturer la saisie utilisateur
+"""
+
+import pyxel
+
+# Mapping des touches Pyxel vers les caractères
+KEY_MAP = {
+ pyxel.KEY_A: ('a', 'A'), pyxel.KEY_B: ('b', 'B'), pyxel.KEY_C: ('c', 'C'),
+ pyxel.KEY_D: ('d', 'D'), pyxel.KEY_E: ('e', 'E'), pyxel.KEY_F: ('f', 'F'),
+ pyxel.KEY_G: ('g', 'G'), pyxel.KEY_H: ('h', 'H'), pyxel.KEY_I: ('i', 'I'),
+ pyxel.KEY_J: ('j', 'J'), pyxel.KEY_K: ('k', 'K'), pyxel.KEY_L: ('l', 'L'),
+ pyxel.KEY_M: ('m', 'M'), pyxel.KEY_N: ('n', 'N'), pyxel.KEY_O: ('o', 'O'),
+ pyxel.KEY_P: ('p', 'P'), pyxel.KEY_Q: ('q', 'Q'), pyxel.KEY_R: ('r', 'R'),
+ pyxel.KEY_S: ('s', 'S'), pyxel.KEY_T: ('t', 'T'), pyxel.KEY_U: ('u', 'U'),
+ pyxel.KEY_V: ('v', 'V'), pyxel.KEY_W: ('w', 'W'), pyxel.KEY_X: ('x', 'X'),
+ pyxel.KEY_Y: ('y', 'Y'), pyxel.KEY_Z: ('z', 'Z'),
+ pyxel.KEY_0: ('0', ')'), pyxel.KEY_1: ('1', '!'), pyxel.KEY_2: ('2', '@'),
+ pyxel.KEY_3: ('3', '#'), pyxel.KEY_4: ('4', '$'), pyxel.KEY_5: ('5', '%'),
+ pyxel.KEY_6: ('6', '^'), pyxel.KEY_7: ('7', '&'), pyxel.KEY_8: ('8', '*'),
+ pyxel.KEY_9: ('9', '('),
+ pyxel.KEY_SPACE: (' ', ' '),
+ pyxel.KEY_MINUS: ('-', '_'),
+ pyxel.KEY_PERIOD: ('.', '>'),
+ pyxel.KEY_COMMA: (',', '<'),
+ pyxel.KEY_SLASH: ('/', '?'),
+ pyxel.KEY_SEMICOLON: (';', ':'),
+ pyxel.KEY_APOSTROPHE: ("'", '"'),
+}
+
+
+class TextInput:
+ """
+ Champ de saisie de texte pour Pyxel
+
+ Exemple d'utilisation:
+ input_field = TextInput(x=10, y=50, max_length=20)
+
+ def update():
+ input_field.update()
+ if input_field.submitted:
+ print(f"Texte saisi: {input_field.text}")
+ input_field.reset()
+
+ def draw():
+ input_field.draw()
+ """
+
+ def __init__(self, x=0, y=0, max_length=32, width=None, color=7, bg_color=0, cursor_color=8):
+ """
+ Initialise un champ de saisie
+
+ Args:
+ x, y: Position du champ
+ max_length: Nombre maximum de caractères
+ width: Largeur du champ en pixels (auto si None)
+ color: Couleur du texte (0-15)
+ bg_color: Couleur de fond (0-15, None pour transparent)
+ cursor_color: Couleur du curseur (0-15)
+ """
+ self.x = x
+ self.y = y
+ self.max_length = max_length
+ self.width = width if width else (max_length * 4 + 4)
+ self.color = color
+ self.bg_color = bg_color
+ self.cursor_color = cursor_color
+
+ self.text = ""
+ self.cursor_pos = 0
+ self.active = True
+ self.submitted = False
+ self._cursor_visible = True
+ self._cursor_timer = 0
+
+ def update(self):
+ """Met à jour le champ de saisie (à appeler dans update())"""
+ if not self.active:
+ return
+
+ self.submitted = False
+
+ # Clignotement du curseur
+ self._cursor_timer += 1
+ if self._cursor_timer >= 15:
+ self._cursor_timer = 0
+ self._cursor_visible = not self._cursor_visible
+
+ # Validation avec Entrée
+ if pyxel.btnp(pyxel.KEY_RETURN):
+ self.submitted = True
+ return
+
+ # Suppression avec Backspace
+ if pyxel.btnp(pyxel.KEY_BACKSPACE, hold=10, repeat=3):
+ if self.cursor_pos > 0:
+ self.text = self.text[:self.cursor_pos-1] + self.text[self.cursor_pos:]
+ self.cursor_pos -= 1
+
+ # Suppression avec Delete
+ if pyxel.btnp(pyxel.KEY_DELETE, hold=10, repeat=3):
+ if self.cursor_pos < len(self.text):
+ self.text = self.text[:self.cursor_pos] + self.text[self.cursor_pos+1:]
+
+ # Navigation avec flèches
+ if pyxel.btnp(pyxel.KEY_LEFT, hold=10, repeat=3):
+ self.cursor_pos = max(0, self.cursor_pos - 1)
+ if pyxel.btnp(pyxel.KEY_RIGHT, hold=10, repeat=3):
+ self.cursor_pos = min(len(self.text), self.cursor_pos + 1)
+ if pyxel.btnp(pyxel.KEY_HOME):
+ self.cursor_pos = 0
+ if pyxel.btnp(pyxel.KEY_END):
+ self.cursor_pos = len(self.text)
+
+ # Saisie de caractères
+ if len(self.text) < self.max_length:
+ shift = pyxel.btn(pyxel.KEY_LSHIFT) or pyxel.btn(pyxel.KEY_RSHIFT)
+ for key, chars in KEY_MAP.items():
+ if pyxel.btnp(key, hold=15, repeat=3):
+ char = chars[1] if shift else chars[0]
+ self.text = self.text[:self.cursor_pos] + char + self.text[self.cursor_pos:]
+ self.cursor_pos += 1
+ break
+
+ def draw(self):
+ """Dessine le champ de saisie (à appeler dans draw())"""
+ # Fond
+ if self.bg_color is not None:
+ pyxel.rect(self.x, self.y, self.width, 9, self.bg_color)
+
+ # Bordure si actif
+ if self.active:
+ pyxel.rectb(self.x - 1, self.y - 1, self.width + 2, 11, self.color)
+
+ # Texte
+ pyxel.text(self.x + 2, self.y + 1, self.text, self.color)
+
+ # Curseur
+ if self.active and self._cursor_visible:
+ cursor_x = self.x + 2 + self.cursor_pos * 4
+ pyxel.rect(cursor_x, self.y + 1, 1, 7, self.cursor_color)
+
+ def reset(self):
+ """Réinitialise le champ"""
+ self.text = ""
+ self.cursor_pos = 0
+ self.submitted = False
+
+ def set_text(self, text):
+ """Définit le texte du champ"""
+ self.text = text[:self.max_length]
+ self.cursor_pos = len(self.text)
+
+
+class TextBox:
+ """
+ Zone de texte multiligne avec retour à la ligne automatique
+
+ Exemple d'utilisation:
+ textbox = TextBox(x=10, y=10, width=100, color=7)
+ textbox.set_text("Ceci est un long texte qui sera automatiquement découpé en plusieurs lignes.")
+
+ def draw():
+ textbox.draw()
+ """
+
+ def __init__(self, x=0, y=0, width=100, color=7, line_spacing=8):
+ """
+ Initialise une zone de texte
+
+ Args:
+ x, y: Position de la zone
+ width: Largeur en pixels
+ color: Couleur du texte (0-15)
+ line_spacing: Espacement entre les lignes
+ """
+ self.x = x
+ self.y = y
+ self.width = width
+ self.color = color
+ self.line_spacing = line_spacing
+ self.lines = []
+
+ def set_text(self, text):
+ """Définit le texte avec retour à la ligne automatique"""
+ self.lines = []
+ chars_per_line = self.width // 4
+
+ paragraphs = text.split('\n')
+ for paragraph in paragraphs:
+ words = paragraph.split(' ')
+ current_line = ""
+
+ for word in words:
+ test_line = current_line + (" " if current_line else "") + word
+ if len(test_line) <= chars_per_line:
+ current_line = test_line
+ else:
+ if current_line:
+ self.lines.append(current_line)
+ # Mot trop long, on le coupe
+ while len(word) > chars_per_line:
+ self.lines.append(word[:chars_per_line])
+ word = word[chars_per_line:]
+ current_line = word
+
+ if current_line:
+ self.lines.append(current_line)
+
+ def draw(self):
+ """Dessine la zone de texte"""
+ for i, line in enumerate(self.lines):
+ pyxel.text(self.x, self.y + i * self.line_spacing, line, self.color)
+
+ def get_height(self):
+ """Retourne la hauteur totale du texte"""
+ return len(self.lines) * self.line_spacing
+
+
+class TypeWriter:
+ """
+ Effet machine à écrire pour afficher du texte progressivement
+
+ Exemple d'utilisation:
+ typewriter = TypeWriter(x=10, y=10, speed=3)
+ typewriter.set_text("Bienvenue dans le jeu...")
+
+ def update():
+ typewriter.update()
+
+ def draw():
+ typewriter.draw()
+ """
+
+ def __init__(self, x=0, y=0, width=100, color=7, speed=2, line_spacing=8):
+ """
+ Args:
+ x, y: Position
+ width: Largeur en pixels
+ color: Couleur du texte
+ speed: Frames entre chaque caractère (plus bas = plus rapide)
+ line_spacing: Espacement entre les lignes
+ """
+ self.textbox = TextBox(x, y, width, color, line_spacing)
+ self.speed = speed
+ self.full_text = ""
+ self.displayed_chars = 0
+ self.timer = 0
+ self.finished = False
+
+ def set_text(self, text):
+ """Définit le texte à afficher progressivement"""
+ self.full_text = text
+ self.displayed_chars = 0
+ self.timer = 0
+ self.finished = False
+
+ def update(self):
+ """Met à jour l'animation"""
+ if self.finished:
+ return
+
+ self.timer += 1
+ if self.timer >= self.speed:
+ self.timer = 0
+ self.displayed_chars += 1
+ if self.displayed_chars >= len(self.full_text):
+ self.displayed_chars = len(self.full_text)
+ self.finished = True
+
+ self.textbox.set_text(self.full_text[:self.displayed_chars])
+
+ def draw(self):
+ """Dessine le texte"""
+ self.textbox.draw()
+
+ def skip(self):
+ """Affiche tout le texte immédiatement"""
+ self.displayed_chars = len(self.full_text)
+ self.finished = True
+ self.textbox.set_text(self.full_text)
+
+ def is_finished(self):
+ """Retourne True si tout le texte est affiché"""
+ return self.finished
+
+
+# --- Exemple d'utilisation ---
+if __name__ == "__main__":
+
+ class Demo:
+ def __init__(self):
+ pyxel.init(200, 150, title="Demo TextInput")
+
+ self.input_field = TextInput(x=10, y=60, max_length=25, color=7)
+ self.typewriter = TypeWriter(x=10, y=10, width=180, speed=2)
+ self.typewriter.set_text("Bienvenue ! Entrez votre nom ci-dessous et appuyez sur Entree.")
+
+ self.messages = []
+
+ pyxel.run(self.update, self.draw)
+
+ def update(self):
+ self.typewriter.update()
+ self.input_field.update()
+
+ # Skip le typewriter avec espace
+ if pyxel.btnp(pyxel.KEY_SPACE) and not self.input_field.active:
+ self.typewriter.skip()
+
+ # Validation de la saisie
+ if self.input_field.submitted and self.input_field.text:
+ self.messages.append(f"Bonjour, {self.input_field.text} !")
+ self.input_field.reset()
+
+ def draw(self):
+ pyxel.cls(0)
+
+ self.typewriter.draw()
+
+ pyxel.text(10, 50, "Votre nom:", 6)
+ self.input_field.draw()
+
+ # Afficher les messages
+ for i, msg in enumerate(self.messages[-3:]):
+ pyxel.text(10, 90 + i * 10, msg, 11)
+
+ Demo()
diff --git a/Projets/src/.ipynb_checkpoints/Untitled-checkpoint.ipynb b/Projets/src/.ipynb_checkpoints/Untitled-checkpoint.ipynb
new file mode 100644
index 0000000..7fec515
--- /dev/null
+++ b/Projets/src/.ipynb_checkpoints/Untitled-checkpoint.ipynb
@@ -0,0 +1,6 @@
+{
+ "cells": [],
+ "metadata": {},
+ "nbformat": 4,
+ "nbformat_minor": 4
+}
diff --git a/Projets/src/Activité.md b/Projets/src/Activité.md
new file mode 100644
index 0000000..017f5c0
--- /dev/null
+++ b/Projets/src/Activité.md
@@ -0,0 +1,559 @@
+# TP d'introduction aux algorithmes génétiques
+
+Durée : 2h00
+
+Objectifs à atteindre :
+
+- Comprendre le fonctionnement d'un algorithme génétique
+- Parvenir à tester son algorithme
+- Niveau des connaissances : Première
+- Pré requis :
+ - Avoir suivi les cours sur les algorithmes
+ - Être bien réveillé et suivre la fiche d'activité !
+
+ - Systèmes mis en œuvre : PC connecté au réseau
+ - Logiciels utilisés : Thonny.
+
+
+## Type de document
+
+Il s'agit d'un TP de découverte des algorithmes dits "génétiques"
+
+## Table des matières
+
+1. Introduction
+2. Le coffre-fort
+3. Consignes
+4. Au boulot !
+
+### Introduction
+
+Dans le dense monde des algorithmes, le génétique est un type particulier. Il ne s'appuie sur aucune forme particulière, et propose de résoudre un problème de manière *évolutionniste* (comprendre à la manière de Darwin ) et cherche à trouver une solution à l'aide de tests de comparaison.
+
+Ce type d'algorithme necessite un jeu de données, lequel servira de source d'échantillons afin d'effectuer les tests et de stocker les résultats.
+
+Un peu comme lorsque nous avons vu les algorithmes gloutons, il s'agira d'effectuer le meilleur cas optimal mais ici ça ne sera pas localement mais globalement, à l'aide du principe de **selection naturelle** :
+
+ À l'aide d'une classe particulière, nous allons pouvoir procéder à des mesures entre plusieurs *individus* (on parle d'individus peu importe le type de données comparé, n'oubliez pas qu'on se base sur les travaux de Darwin) et ne garder que les meilleurs éléments selon un score établi.
+
+Nous créerons donc de nouveaux jeux de données avec ces meilleurs éléments qui devraient nous rapprocher du résultat recherché.
+
+En somme, un algorithme génétique compare des éléments pour affiner une recherche et se rapprocher d'un résultat optimal.
+
+
+--------------------
+
+### Le coffre-fort
+
+En informatique, on connait le principe de bruteforce ou d'attaque par dictionnaire, qui se rapproche du principe d'algorithme générique.
+
+Mais on peut appliquer aussi cet algorithme en *réel*, par exemple pour trouver une chaîne de caractère la plus proche possible d'un mot donné, - un peu comme si vous jouiez à Motus - à des jeux type mastermind, sobokan, ou à un parcours de labyrinthe, trouver un code pin...etc.
+
+Après tout, tous ces exemples ont une solution et il est possible de tester différentes combinaisons afin de s'en approcher voir même de trouver cette solution.
+
+Songez à un cas pratique qui vous demanderait une combinaison, un code...Et vous pourriez faire quelques essais pour trouver...Une combinaison de coffre fort !
+
+
+
+Après tout, nous disposons d'un jeu de données : les chiffres [0 - 9], il manque juste une donnée : la longueur du code à trouver.
+
+Notre but sera donc de proposer un code python permettant de tester un nombre à **n** chiffres, en regardant combien d'essais sont necessaires pour trouver la bonne formule qui ouvrira ce coffre.
+
+Pour simplifier la chose, nous fixerons **n** nous mêmes afin de réduire le nombre de possibilités : en admettant un code de longueur n avec tous les chiffres possibles, nous aurions 10^n possibilités...
+
+Par exemple, un code de longueur n = 4 qui utiliserait tous les chiffres (0 à 9) aurait 10^4 (10 000) combinaisons possibles ! Imaginez le temps que celà prendra, même avec une bonne machine, si n valait 20, 30, 100 !
+
+Il est donc temps de s'y mettre car cela risque de durer un moment.
+
+---------------
+
+### Consignes
+
+Avant de commencer à programmer, rappelons les besoins :
+
+1. Décider de quel type seront les individus que nous allons comparer
+ 2. Un jeu de données
+ 3. Une classe permettant de traiter ces données
+
+1. Comme indiqué plus haut, nous allons rechercher une suite numérique : il semble logique que le type d'individus que nous allons comparer se trouve être des chiffres. Nous devrons donc indiquer une liste de chiffres possiblement utilisables pour la combinaison.
+
+2. Quel type de structure utiliser ?
+
+Une liste comprenant les nombres sera plus facile à employer, d'autant qu'il s'agit de stocker des nombres.
+
+3. Les fichiers individual_interface.py et problem_interface.py vous sont fournis : les classes que vous devez écrire en héritent.
+
+Il s'agira donc de créer un fichier de classe héritant d'individual_interface et un autre héritant de problem_interface.
+
+Il faudra définir les méthodes de ces classes et adapter le code fournit pour notre problème.
+
+N'oubliez pas d'importer les bibliothèques necessaires ainsi que les fichiers python dont vous avez besoin.
+
+---------------------------------
+
+### Au boulot !
+
+Nous allons travailler sur deux fichiers différents : dans le but d'être clair et de ne pas se perdre, mieux vaut en faire un (1) à la fois.
+
+Commençons par le fichier combinaison.py, qui hérite d'individual_interface : ce fichier nous permettra d'écrire le comportement de notre algorithme.
+
+
+Avant de créer la classe, déclarons la liste des chiffres susceptibles d'être utilisés :
+
+
+ ```python
+
+CHIFFRE = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9"]
+
+ ```
+
+Maintenant, il va s'agir de remplir ces espaces vides
+
+1. Copier notre individu
+
+ ```python
+
+class Combinaison(Individual_Interface):
+
+
+ def copy(self):
+ '''
+ créé une copie d'un individu (appelé génome)
+
+ :return: un individu nouveau, qui est son propre clone
+ :rtype: un type d'individu
+ '''
+ copy = ....(self.get_size())
+ copy.set_value(self.get_value())
+ return ....
+
+ ```
+
+Ici, il est question de copier l'individu sur lequel nous allons travailler : rappelez vous, notre jeu de données sera modifié et remplacé par un nouveau, après les tests. Donc nous avons besoin de cloner nos données.
+
+
+2. Initialiser un nouvel individu
+
+
+
+
+Pour remplir notre jeu de données avec de nouveaux individus, il nous faut bien une initialisation.
+
+```python
+
+def init_value(self):
+ '''
+ randomly initialize the genome value of self
+ '''
+
+ return [choice(....) for .... in .... (self.get_size())]
+
+
+
+```
+
+**Rappel** : choice est une méthode permettant de retourner un nombre aléatoire dans une séquence spécifique. Il faut donc importer une bibliothèque et choisir la séquence indiqué plus tôt.
+
+
+
+3. Croiser deux individus afin de générer un tuple de deux nouveaux individus.
+
+
+
+Les deux individus passés en paramètres de la fonction seront appelés *self* et *other*.
+
+Pour les besoins de cette fonction, il sera necessaire de créer un "pivot" qui sera un nombre aléatoire compris entre 0 et le nombre d'élements dans la séquence CHIFFRE (donc sa longueur...)
+
+
+Ce pivot permettra de créer des individus aléatoire grâce au croisement.
+
+On appellera test_1 et test_2 nos deux nouveaux individus obtenus depuis self et other ainsi qu'à l'aide de pivot.
+
+Finalement, nous aurons besoin de définir la valeur de nos deux nouveaux amis
+
+ test_1.set_value(param1[:...] + param2[...:])
+ test_2.set_value(param2[:...] + param1[...:])
+
+
+```python
+
+def cross_with(self, other):
+ '''
+ Croiser self et other, grâce à un point pivot, puis retourner deux nouveaux individus créés.
+
+ :param other: le second individu
+ :type other: un individu
+ :return: Les deux individus crées par le croisement, test_1 et test_2
+ :rtype: tuple de test_1 et test_2
+ '''
+ value = self.
+ other_value = other.
+
+ #générer le nombre pivot ici
+
+ #initialiser test_1 et test_2 (comme vous avez créé les individus de base)
+
+ #modifier la valeur de test_1
+ #modifier la valeur de test_2
+
+ return (...)
+
+
+```
+
+
+
+4. Enfin, puisqu'on parle de *génétique*, de *croisement* : lorsque l'on va tester notre combinaison de coffre fort, et bien si le test n'est pas concluant du premier coup, il faudra changer les chiffres utilisés et pour cela, on parlera de **mutation**
+
+Chaque individu est susceptible d'être transformé par un autre individu, qui fera partie de la séquence génétique que nous avons déclaré au tout début...
+
+```python
+
+def mutate(self, probability):
+ '''
+ Appliquer la mutation à l'individu self passé en paramètre : chaque élément de la séquence (combinaison ici) est changé aléatoirement selon une probabilité donnée
+
+ Effet de bord : l'individu va être modifié
+
+ :param probability: la probabilité de mutation de chaque génome
+ :type probability: float
+ :UC: probability entre [0,1[
+ '''
+ for .... in (len(self.get_value())):
+ #variable = uniform (nombre_min, nombre_max)
+ #si variable < param probabilité :
+ self.mutate_gene(gene)
+
+
+
+```
+
+
+On vous donnera la fonction mutate_gene que l'on utilise ci dessus afin de muter un individu
+
+```python
+
+
+def mutate_gene(self, gene):
+ temp = self.get_value()
+ self.set_value(temp[:gene] + [choice(COLOR)] + temp [gene+1:])
+
+
+
+
+
+```
+
+Ici, notre fichier combinaison.py est terminé. Il nous reste à travailler sur le fichier de la combinaison : celui qui va créer le problème auquel notre algorithme devra répondre.
+
+
+
+----------------------------
+
+Maintenant, attaquons nous à problem.py, qui hérite de problem_interface.py
+
+
+
+
+Ne pas oublier d'importer le fichier dont on hérite, ainsi que le fichier que l'on vient de créer.
+
+
+
+C'est parti :
+
+Pour pouvoir résoudre un problème de combinaison à trouver, il faudra tout d'abord....créer le problème à résoudre !
+
+Ainsi, il va falloir initialiser le calcul que nous souhaitons régler par notre algorithme et se faisant, générer une longueur de combinaison à trouver.
+
+
+```python
+
+class Problem(Problem_Interface) :
+ """
+ classe probleme : Combinaison Coffre-Fort
+ """
+
+ def __init__(self, calcul):
+ self.__size = #longueur du paramètre calcul
+ self.__combinaison = #paramètre calcul
+
+
+```
+
+
+Dans le fichier combinaison.py nous clonions des individus.
+Mais ici, nous allons implémenter la fonction qui permettra de générer cet individu pour un problème donné.
+
+```python
+
+
+def create_individual(self):
+ '''
+ create a randomly generated indidivual for this problem
+
+ :return: a randomly generated individual gfor this problem
+ :rtype: an Individual object
+ '''
+
+ #retourne un individu crée par la classe que nous avons définie dans combinaison.py
+
+
+```
+
+
+Un point important non abordé jusqu'ici : on parle de comparer les individus entre eux pour en selectionner les meilleurs.
+Mais comment les compare t-on ? Sur quel(s) critère(s) ?
+
+Et bien tout simplement en leur attribuant un score, selon leur positionnement par rapport à la bonne réponse :
+
+Plus un individu ressemblera au résultat recherché (donc à l'individu parfait dans notre résultat) plus son score sera élevé.
+
+Au contraire, un individu éloigné de la bonne réponse aura un score plus faible.
+
+```python
+
+
+def evaluate_fitness(self, individual):
+ '''
+ Calcule le score d'un individu pour un problème donné.
+
+ :param individual: l'individu à évaluer
+ :type individual: un individu
+ :return: le score de l'individu évalué
+ :rtype: un individu
+ '''
+
+ #retourner la somme de ([1 si calcul[element] est équivalent à self.__combinaison[element] sinon 0 pour chaque element dans la fourchette (longueur(calcul))])
+
+
+```
+
+
+Une fois que chaque individu aura obtenu un score, nous allons pouvoir ranger la population d'individu qui compose notre génétique.
+
+Pour cela, il suffit de trier par un ordre de score.
+
+```python
+
+ def sort_population(self, population):
+ '''
+ :param population : la liste d'individus à trier
+ effet souhaité : on obtient une liste triée d'individus en sortie
+
+
+ '''
+ #utiliser la méthode sort de la liste en paramètre afin de trier par score.
+
+
+
+
+
+```
+
+
+En supposant que notre liste soit bien triée, desormais, on va souhaiter garder le meilleur de la liste afin de ne conserver que les meilleurs gènes, comme la selection naturelle le fait.
+
+
+```python
+
+
+def best_individual(self, population):
+ '''
+ renvoie le meilleur individu d'une liste.
+ à vous de voir si c'est celui avec le plus grand score ou le plus petit
+ '''
+
+ #trier la population
+ #renvoie l'élement en tête de liste ou en bout
+
+```
+
+
+
+Maintenant que l'on a nos meilleurs individus, il est temps d'organiser un Mortal Kombat pour décider qui gagnera !
+
+```python
+
+def tournament(self, first, second):
+ '''
+ On organise un match entre deux individus, celui qui a le plus gros score remporte la victoire
+
+
+ :param first: un individu
+
+ :param second: un individu
+
+ :return: le vainqueur
+
+ '''
+ #si tel individu est plus grand qu'un autre, alors le resultat = individu_plusfort
+
+ #sinon, resultat = l'autre individu
+ #renvoie le resultat
+```
+----------------------
+
+Et maintenant j'ai terminé ? Et bien non.
+Si vous avez bien suivi il manquait en fait une chose importante : le fichier algo_gen.py, qui vous est fournit, n'est pas complet.
+
+Ce fichier va nous permettre d'initialiser le probleme, de créer une population d'individus, et de tester notre algorithme solution.
+
+Allez, on y est presque !
+
+
+Comme d'habitude, on n'oublie pas d'importer nos fichiers précédemment crées.
+
+
+```python
+
+
+BEST_KEPT = 5
+
+class AlgoGen(object):
+
+ def __init__(self, problem, population_size, crossover_rate, mutation_probability):
+ '''
+ build an genetic algorithm to solve problem using a population of size population_size and a probability of muation of mutation_probability
+
+ :param problem: Le probleme que l'on souhaite ré
+ :type problem: a Problem object
+ :param population_size: the size of the population (must be even)
+ :type population_size: int
+ :param mutation_probability: the mutation probability
+ :type mutation_probability: float
+ :UC: population_size must be even and mutation_probability must be 0<= and <1
+ '''
+ self.__problem = problem
+ self.__population_size = population_size
+ self.__population = []
+ self.__nb_crossover = crossover_rate
+ self.__mutation_probability = mutation_probability
+
+
+ def get_population(self):
+ return self.__population
+
+```
+
+Cette partie vous est donnée complète, elle permet de voir comment on initialise un problème à résoudre, et obtenir la population d'un problème - qui doit être paire, afin de pouvoir la diviser par deux.
+
+
+
+Nous allons commencer à modifier les fonctions qui sont incomplètes dans votre fichier algo_gen.py
+
+Tout d'abord, la fonction qui va se charger de créer la population, la genèse.
+Sachant qu'au dessus, nous avons noté
+ ```
+ self.__population = []
+ ```
+
+Que peut-on en conclure de population ?
+
+Du coup, pour générer la population, il suffira de compter chaque élément dans cette structure et d'utiliser la méthode permettant d'ajouter un élément à cette une structure de même type, que vous trouverez dans votre fichier problem.py
+
+
+
+
+```python
+
+
+ def genesis(self):
+ """
+ générer la population
+ """
+
+
+
+```
+
+
+Pour la fonction suivante, il s'agit d'évaluer non pas un individu spécifique, mais toute une population. C'est à dire chaque individu qui la compose.
+
+```python
+
+def evaluate_population(self, population):
+ """
+ evalue la population passée en paramètre
+ :param population: (list) la population
+ """
+
+ #Pour chaque individu, on evalue.
+
+
+```
+
+
+Une fois évalué, que fait - on ? On relance un Mortal Kombat !
+
+C'est ici que l'on exploitera la parité de votre population : On compare toujours deux individus entre eux. Sur une population complète, on peut rapporter cela à un test d'une moitié de la population envers une autre. Il nous restera donc...une moitié.
+
+```python
+
+def next_generation_tournament(self, population):
+ '''
+ organise un tournoi entre les individu d'une population .
+ chaque individu choisi une et une seule fois, dans un tournoi ,
+ vainqueur conservé taille résultat = 1/2 taille population
+
+ :param population: (list) la population
+ :return: (list) les vainqueurs du tournoi
+
+ '''
+
+
+```
+
+Comme fait précédemment, une fois le tournoi effectué, il faut croiser les individus pour, encore une fois,ne garder que les meilleurs des meilleurs.
+
+
+```python
+
+def crossover(self, population):
+ '''Croise les individus d'une population.
+
+ Chaque individu est sélectionné une et une seule fois, on
+ garde le meilleur descendant à chaque fois.
+
+ taille résultat = 1/2 taille population
+
+ :param population: (list) a population
+ :return: (list) new individuals
+ '''
+
+ #Une liste
+ #pour chaque individu dans une fourchette de la moitié de population
+ #individu_1 et individu_2 = croisement d'un individu dans la #liste population avec l'individu qui le précède
+
+ #Puis on évalue les deux individus
+ #On les ajoute à la liste initialisée plus haut
+ #et on suit les consignes jusqu'au bout
+
+
+```
+
+
+
+
+Enfin, il ne vous reste plus qu'à intégrer une fonction qui fera muter chaque individu dans une liste donnée en paramètre, qu'on appellera "individuals".
+
+Rappel : Au début de votre fichier se trouve "self.__mutation_probability" qui se révélera utile ici.
+
+
+Et c'est terminé.
+
+Une dernière chose : ça serait bien de tester.
+Alors allons y :
+
+```python
+
+if __name__ =="__main__":
+
+ probleme = problem('1','3','3','7')
+ #On initialise le probleme avec une combinaison
+
+ solution = AlgoGen(p,100,0,0.1)
+
+ solution.solve(100)
+
+
+```
\ No newline at end of file
diff --git a/Projets/src/Hamming.pdf b/Projets/src/Hamming.pdf
new file mode 100644
index 0000000..3a86e0b
Binary files /dev/null and b/Projets/src/Hamming.pdf differ
diff --git a/Projets/src/Images/1.png b/Projets/src/Images/1.png
new file mode 100644
index 0000000..5a228eb
Binary files /dev/null and b/Projets/src/Images/1.png differ
diff --git a/Projets/src/Images/10.png b/Projets/src/Images/10.png
new file mode 100644
index 0000000..81a8536
Binary files /dev/null and b/Projets/src/Images/10.png differ
diff --git a/Projets/src/Images/11.png b/Projets/src/Images/11.png
new file mode 100644
index 0000000..129eed5
Binary files /dev/null and b/Projets/src/Images/11.png differ
diff --git a/Projets/src/Images/12.png b/Projets/src/Images/12.png
new file mode 100644
index 0000000..3de0cea
Binary files /dev/null and b/Projets/src/Images/12.png differ
diff --git a/Projets/src/Images/13.png b/Projets/src/Images/13.png
new file mode 100644
index 0000000..4c05475
Binary files /dev/null and b/Projets/src/Images/13.png differ
diff --git a/Projets/src/Images/14.png b/Projets/src/Images/14.png
new file mode 100644
index 0000000..feb7021
Binary files /dev/null and b/Projets/src/Images/14.png differ
diff --git a/Projets/src/Images/15.png b/Projets/src/Images/15.png
new file mode 100644
index 0000000..cc39bac
Binary files /dev/null and b/Projets/src/Images/15.png differ
diff --git a/Projets/src/Images/16.png b/Projets/src/Images/16.png
new file mode 100644
index 0000000..8038a25
Binary files /dev/null and b/Projets/src/Images/16.png differ
diff --git a/Projets/src/Images/17.png b/Projets/src/Images/17.png
new file mode 100644
index 0000000..78b0848
Binary files /dev/null and b/Projets/src/Images/17.png differ
diff --git a/Projets/src/Images/18.png b/Projets/src/Images/18.png
new file mode 100644
index 0000000..f74a0a0
Binary files /dev/null and b/Projets/src/Images/18.png differ
diff --git a/Projets/src/Images/19.png b/Projets/src/Images/19.png
new file mode 100644
index 0000000..7937703
Binary files /dev/null and b/Projets/src/Images/19.png differ
diff --git a/Projets/src/Images/2.png b/Projets/src/Images/2.png
new file mode 100644
index 0000000..799f478
Binary files /dev/null and b/Projets/src/Images/2.png differ
diff --git a/Projets/src/Images/20.png b/Projets/src/Images/20.png
new file mode 100644
index 0000000..e476274
Binary files /dev/null and b/Projets/src/Images/20.png differ
diff --git a/Projets/src/Images/21.png b/Projets/src/Images/21.png
new file mode 100644
index 0000000..89f3210
Binary files /dev/null and b/Projets/src/Images/21.png differ
diff --git a/Projets/src/Images/22.png b/Projets/src/Images/22.png
new file mode 100644
index 0000000..d10272b
Binary files /dev/null and b/Projets/src/Images/22.png differ
diff --git a/Projets/src/Images/23.png b/Projets/src/Images/23.png
new file mode 100644
index 0000000..cc6c556
Binary files /dev/null and b/Projets/src/Images/23.png differ
diff --git a/Projets/src/Images/24.png b/Projets/src/Images/24.png
new file mode 100644
index 0000000..0ad8965
Binary files /dev/null and b/Projets/src/Images/24.png differ
diff --git a/Projets/src/Images/25.png b/Projets/src/Images/25.png
new file mode 100644
index 0000000..df045f1
Binary files /dev/null and b/Projets/src/Images/25.png differ
diff --git a/Projets/src/Images/26.png b/Projets/src/Images/26.png
new file mode 100644
index 0000000..08c20b0
Binary files /dev/null and b/Projets/src/Images/26.png differ
diff --git a/Projets/src/Images/27.png b/Projets/src/Images/27.png
new file mode 100644
index 0000000..ae09ec8
Binary files /dev/null and b/Projets/src/Images/27.png differ
diff --git a/Projets/src/Images/28.png b/Projets/src/Images/28.png
new file mode 100644
index 0000000..7a969e5
Binary files /dev/null and b/Projets/src/Images/28.png differ
diff --git a/Projets/src/Images/29.png b/Projets/src/Images/29.png
new file mode 100644
index 0000000..7aff12a
Binary files /dev/null and b/Projets/src/Images/29.png differ
diff --git a/Projets/src/Images/3.png b/Projets/src/Images/3.png
new file mode 100644
index 0000000..0f7fab5
Binary files /dev/null and b/Projets/src/Images/3.png differ
diff --git a/Projets/src/Images/30.png b/Projets/src/Images/30.png
new file mode 100644
index 0000000..1c7d85f
Binary files /dev/null and b/Projets/src/Images/30.png differ
diff --git a/Projets/src/Images/31.png b/Projets/src/Images/31.png
new file mode 100644
index 0000000..0eb3bfc
Binary files /dev/null and b/Projets/src/Images/31.png differ
diff --git a/Projets/src/Images/32.png b/Projets/src/Images/32.png
new file mode 100644
index 0000000..f37650a
Binary files /dev/null and b/Projets/src/Images/32.png differ
diff --git a/Projets/src/Images/33.png b/Projets/src/Images/33.png
new file mode 100644
index 0000000..8f8547b
Binary files /dev/null and b/Projets/src/Images/33.png differ
diff --git a/Projets/src/Images/34.png b/Projets/src/Images/34.png
new file mode 100644
index 0000000..4753460
Binary files /dev/null and b/Projets/src/Images/34.png differ
diff --git a/Projets/src/Images/35.png b/Projets/src/Images/35.png
new file mode 100644
index 0000000..20b864b
Binary files /dev/null and b/Projets/src/Images/35.png differ
diff --git a/Projets/src/Images/36.png b/Projets/src/Images/36.png
new file mode 100644
index 0000000..eff5439
Binary files /dev/null and b/Projets/src/Images/36.png differ
diff --git a/Projets/src/Images/37.png b/Projets/src/Images/37.png
new file mode 100644
index 0000000..188a4eb
Binary files /dev/null and b/Projets/src/Images/37.png differ
diff --git a/Projets/src/Images/38.png b/Projets/src/Images/38.png
new file mode 100644
index 0000000..28d6da3
Binary files /dev/null and b/Projets/src/Images/38.png differ
diff --git a/Projets/src/Images/4.png b/Projets/src/Images/4.png
new file mode 100644
index 0000000..b29c0ac
Binary files /dev/null and b/Projets/src/Images/4.png differ
diff --git a/Projets/src/Images/5.png b/Projets/src/Images/5.png
new file mode 100644
index 0000000..64a2a33
Binary files /dev/null and b/Projets/src/Images/5.png differ
diff --git a/Projets/src/Images/6.png b/Projets/src/Images/6.png
new file mode 100644
index 0000000..44714cb
Binary files /dev/null and b/Projets/src/Images/6.png differ
diff --git a/Projets/src/Images/7.png b/Projets/src/Images/7.png
new file mode 100644
index 0000000..74cc318
Binary files /dev/null and b/Projets/src/Images/7.png differ
diff --git a/Projets/src/Images/8.png b/Projets/src/Images/8.png
new file mode 100644
index 0000000..bd9f6a2
Binary files /dev/null and b/Projets/src/Images/8.png differ
diff --git a/Projets/src/Images/9.png b/Projets/src/Images/9.png
new file mode 100644
index 0000000..f894dd8
Binary files /dev/null and b/Projets/src/Images/9.png differ
diff --git a/Projets/src/Images/Programme.png b/Projets/src/Images/Programme.png
new file mode 100644
index 0000000..8d4ba2c
Binary files /dev/null and b/Projets/src/Images/Programme.png differ
diff --git a/Projets/src/Readme.pdf b/Projets/src/Readme.pdf
new file mode 100644
index 0000000..47191e4
Binary files /dev/null and b/Projets/src/Readme.pdf differ
diff --git a/Projets/src/TP_CN_Florian_Mathieu.md b/Projets/src/TP_CN_Florian_Mathieu.md
new file mode 100644
index 0000000..f9dc5d5
--- /dev/null
+++ b/Projets/src/TP_CN_Florian_Mathieu.md
@@ -0,0 +1,551 @@
+# TP d'introduction aux systèmes Unix
+
+Durée : 1h30
+
+Objectifs à atteindre : Créer / configurer une machine virtuelle VirtualBox, installer et découvrir le système d’exploitation linux Ubuntu, utiliser les commandes de base.
+
+Niveau des connaissances : Première
+Pré requis :