Mini-projets algorithmique, corrigé TP KNN, news, notebooks IA
This commit is contained in:
156
knn/CORRIGE_TP_KNN.md
Normal file
156
knn/CORRIGE_TP_KNN.md
Normal file
@@ -0,0 +1,156 @@
|
||||
# Corrigé — TP Choixpeau Magique et KNN
|
||||
|
||||
---
|
||||
|
||||
## Partie 1 : Modéliser un élève
|
||||
|
||||
### Question 1 — Modélisation d'Anthony
|
||||
|
||||
```python
|
||||
anthony = {"nom": "Anthony", "courage": 2, "loyauté": 8, "sagesse": 8, "malice": 3, "maison": "Serdaigle"}
|
||||
```
|
||||
|
||||
### Question 3 — Distance entre Hermione et Adrian
|
||||
|
||||
- Hermione : courage=8, loyauté=6, sagesse=6, malice=6
|
||||
- Adrian : courage=9, loyauté=4, sagesse=7, malice=10
|
||||
|
||||
```
|
||||
distance = |8-9| + |6-4| + |6-7| + |6-10|
|
||||
= 1 + 2 + 1 + 4
|
||||
= 8 ✓
|
||||
```
|
||||
|
||||
### Question 4 — Distance entre Arthur et Drago
|
||||
|
||||
- Arthur : courage=10, loyauté=4, sagesse=2, malice=5
|
||||
- Drago : courage=6, loyauté=6, sagesse=5, malice=8
|
||||
|
||||
```
|
||||
distance = |10-6| + |4-6| + |2-5| + |5-8|
|
||||
= 4 + 2 + 3 + 3
|
||||
= 12
|
||||
```
|
||||
|
||||
### Question 5 — Fonction distance
|
||||
|
||||
```python
|
||||
def distance(eleve1, eleve2):
|
||||
return (abs(eleve1["courage"] - eleve2["courage"]) +
|
||||
abs(eleve1["loyauté"] - eleve2["loyauté"]) +
|
||||
abs(eleve1["sagesse"] - eleve2["sagesse"]) +
|
||||
abs(eleve1["malice"] - eleve2["malice"]))
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Partie 2 : Charger les données en table
|
||||
|
||||
### Question 1 — Type de `eleve[0]`
|
||||
|
||||
`eleve[0]` est de type `str`. `csv.reader` retourne toutes les valeurs sous forme de chaînes de caractères.
|
||||
|
||||
### Question 2 — Pourquoi `int()` ?
|
||||
|
||||
`int(eleve[1])` est de type `int`. On a besoin de la conversion car `csv.reader` renvoie tout en `str`, et on a besoin de valeurs numériques pour calculer des distances.
|
||||
|
||||
### Question 3 — Type de `poudlard`
|
||||
|
||||
`poudlard` est de type `list` (une liste de dictionnaires).
|
||||
|
||||
---
|
||||
|
||||
## Partie 3 : Trouver la maison majoritaire
|
||||
|
||||
```python
|
||||
def maison_majoritaire(table):
|
||||
frequences = frequence_des_maisons(table)
|
||||
maison_max = None
|
||||
max_freq = 0
|
||||
for maison, freq in frequences.items():
|
||||
if freq > max_freq:
|
||||
max_freq = freq
|
||||
maison_max = maison
|
||||
return maison_max
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Partie 4 : Sept plus proches voisins
|
||||
|
||||
### Question 1 — Pseudo-code
|
||||
|
||||
```
|
||||
Algorithme sept_voisins(table, nouveau) :
|
||||
Données :
|
||||
- table : liste d'élèves avec leur maison
|
||||
- nouveau : élève sans maison
|
||||
Résultat : les 7 élèves de table les plus proches de nouveau
|
||||
|
||||
Pour chaque élève de table :
|
||||
Calculer la distance entre cet élève et nouveau
|
||||
Stocker (distance, élève)
|
||||
Trier la liste par distance croissante
|
||||
Retourner les 7 premiers éléments
|
||||
```
|
||||
|
||||
### Question 2 — Implémentation Python
|
||||
|
||||
```python
|
||||
def sept_voisins(table, nouveau):
|
||||
distances = []
|
||||
for eleve in table:
|
||||
d = distance(eleve, nouveau)
|
||||
distances.append((d, eleve))
|
||||
distances.sort(key=lambda x: x[0])
|
||||
return [eleve for d, eleve in distances[:7]]
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Partie 5 : Attribuer une maison
|
||||
|
||||
```python
|
||||
def attribuer_maison(table, nouveau):
|
||||
voisins = sept_voisins(table, nouveau)
|
||||
return maison_majoritaire(voisins)
|
||||
```
|
||||
|
||||
### Application aux quatre élèves
|
||||
|
||||
```python
|
||||
poudlard = charger_table("choixpeauMagique.csv")
|
||||
|
||||
hermione = {"nom": "Hermione", "courage": 8, "loyauté": 6, "sagesse": 6, "malice": 6}
|
||||
drago = {"nom": "Drago", "courage": 6, "loyauté": 6, "sagesse": 5, "malice": 8}
|
||||
cho = {"nom": "Cho", "courage": 7, "loyauté": 6, "sagesse": 9, "malice": 6}
|
||||
cedric = {"nom": "Cédric", "courage": 7, "loyauté": 10, "sagesse": 5, "malice": 6}
|
||||
|
||||
for eleve in [hermione, drago, cho, cedric]:
|
||||
maison = attribuer_maison(poudlard, eleve)
|
||||
print(f"{eleve['nom']} → {maison}")
|
||||
```
|
||||
|
||||
### Résultats attendus
|
||||
|
||||
```
|
||||
Hermione → Gryffondor
|
||||
Drago → Serpentard
|
||||
Cho → Serdaigle
|
||||
Cédric → Poufsouffle
|
||||
```
|
||||
|
||||
Détail des 7 voisins et du vote pour chaque élève :
|
||||
|
||||
| Élève | 7 plus proches voisins (distance) | Vote majoritaire |
|
||||
|----------|------------------------------------------------------------------------------------------|-------------------------|
|
||||
| Hermione | Cormac (4), Milicent (5), Neville (5), Padma (5), Susan (5), Angelina (6), Colin (6) | Gryffondor 4/7 ✓ |
|
||||
| Drago | Padma (2), Susan (4), Angelina (5), Gregory (5), Harper (5), Bole (6), Marcus (6) | Serpentard 4/7 ✓ |
|
||||
| Cho | Terry (5), Gilderoy (6), Lavande (6), Saemus (6), Eddie (7), Marcus (7), Padma (7) | Serdaigle 4/7 ✓ |
|
||||
| Cédric | Dean (6), Gregory (6), Hannah (6), Norbert (6), Pomona (6), Susan (7), Térence (7) | Poufsouffle 4/7 ✓ |
|
||||
|
||||
> Ces résultats sont cohérents avec les personnages du roman : Hermione et Drago sont bien placés dans leurs maisons respectives, Cho Chang est à Serdaigle et Cédric Diggory à Poufsouffle.
|
||||
|
||||
---
|
||||
|
||||
Auteur : Florian Mathieu — Licence CC BY NC
|
||||
@@ -26,7 +26,7 @@ Le Choixpeau magique dispose d'un [fichier csv](choixpeauMagique.csv) avec les
|
||||
|
||||
|
||||
|
||||
Et voici les élèves que le Choipeaux magique doit orienter :
|
||||
Et voici les élèves que le Choixpeau magique doit orienter :
|
||||
|
||||
| Nom | Courage | Loyauté | Sagesse | Malice |
|
||||
| -------- | ------- | ------- | ------- | ------ |
|
||||
@@ -78,7 +78,7 @@ def charger_table(nom_fichier):
|
||||
|
||||
table= []
|
||||
with open(nom_fichier, 'r',newline="",encoding="utf-8") as csvfile:
|
||||
eleve_reader = csv. reader(csvfile, delimiter=";")
|
||||
eleve_reader = csv.reader(csvfile, delimiter=";")
|
||||
eleve_reader.__next__()
|
||||
for eleve in eleve_reader:
|
||||
table.append({ "nom": eleve[0],
|
||||
@@ -97,9 +97,9 @@ L'instruction suivante permet de charger les informations dans une variable **po
|
||||
poudlard = charger_table("choixpeauMagique.csv")
|
||||
```
|
||||
|
||||
1. Dans le code de la fonction charger _table, à la ligne 14, quel est le type de la variable eleve[0] ?
|
||||
1. Dans le code de la fonction charger_table, à la ligne 14, quel est le type de la variable eleve[0] ?
|
||||
|
||||
2. Quel est le type de int ( eleve [ 0] ) ? Pourquoi a-t-on besoin de la fonction int() ici?
|
||||
2. Quel est le type de int(eleve[1]) ? Pourquoi a-t-on besoin de la fonction int() ici ?
|
||||
3. Quel est le type de la variable poudlard ?
|
||||
|
||||
|
||||
|
||||
@@ -1,51 +1,51 @@
|
||||
Nom;Courage;Loyauté;Sagesse;Malice;Maison
|
||||
Adrian;9;4;7;10;Serpentar
|
||||
Andrew;9;3;4;7;Griffondor
|
||||
Angelina;10;6;5;9;Griffondor
|
||||
Adrian;9;4;7;10;Serpentard
|
||||
Andrew;9;3;4;7;Gryffondor
|
||||
Angelina;10;6;5;9;Gryffondor
|
||||
Anthony;2;8;8;3;Serdaigle
|
||||
Arthur;10;4;2;5;Griffondor
|
||||
Bellatrix;10;4;9;9;Serpentar
|
||||
Bole;7;4;6;10;Serpentar
|
||||
Colin;10;7;4;7;Griffondor
|
||||
Cormac;9;6;5;4;Griffondor
|
||||
Dean;9;8;4;7;Griffondor
|
||||
Demelza;10;6;5;3;Griffondor
|
||||
Derrick;5;4;6;5;Serpentar
|
||||
Arthur;10;4;2;5;Gryffondor
|
||||
Bellatrix;10;4;9;9;Serpentard
|
||||
Bole;7;4;6;10;Serpentard
|
||||
Colin;10;7;4;7;Gryffondor
|
||||
Cormac;9;6;5;4;Gryffondor
|
||||
Dean;9;8;4;7;Gryffondor
|
||||
Demelza;10;6;5;3;Gryffondor
|
||||
Derrick;5;4;6;5;Serpentard
|
||||
Eddie;5;7;10;3;Serdaigle
|
||||
Ernie;4;8;7;4;Poufsouffle
|
||||
Euan;9;2;7;4;Griffondor
|
||||
Euan;9;2;7;4;Gryffondor
|
||||
Gilderoy;7;9;9;9;Serdaigle
|
||||
Gregory;6;9;7;8;Serpentar
|
||||
Gregory;6;9;7;8;Serpentard
|
||||
Hannah;8;10;2;4;Poufsouffle
|
||||
Harper;6;3;5;10;Serpentar
|
||||
Jimmy;9;9;9;10;Griffondor
|
||||
Harper;6;3;5;10;Serpentard
|
||||
Jimmy;9;9;9;10;Gryffondor
|
||||
Justin;5;10;7;10;Poufsouffle
|
||||
Katie;10;2;3;9;Griffondor
|
||||
Lavande;10;8;8;6;Griffondor
|
||||
Lee;10;2;2;8;Griffondor
|
||||
Katie;10;2;3;9;Gryffondor
|
||||
Lavande;10;8;8;6;Gryffondor
|
||||
Lee;10;2;2;8;Gryffondor
|
||||
Luna;2;9;9;2;Serdaigle
|
||||
Marcus;6;5;8;10;Serpentar
|
||||
Marcus;6;5;8;10;Serpentard
|
||||
Marietta;10;8;10;9;Serdaigle
|
||||
Michael;4;2;6;5;Serdaigle
|
||||
Milicent;9;3;5;6;Serpentar
|
||||
Milicent;9;3;5;6;Serpentard
|
||||
Mimi;4;4;9;10;Serdaigle
|
||||
Montague;5;7;2;10;Serpentar
|
||||
Neville;10;5;6;4;Griffondor
|
||||
Montague;5;7;2;10;Serpentard
|
||||
Neville;10;5;6;4;Gryffondor
|
||||
Norbert;3;10;7;6;Poufsouffle
|
||||
Nymphadora;2;5;3;8;Poufsouffle
|
||||
Padma;6;6;6;9;Serdaigle
|
||||
Paenny;2;8;9;8;Poufsouffle
|
||||
Pansy;4;4;10;8;Serpentar
|
||||
Parvati;10;5;2;6;Griffondor
|
||||
Pansy;4;4;10;8;Serpentard
|
||||
Parvati;10;5;2;6;Gryffondor
|
||||
Pomona;5;10;7;8;Poufsouffle
|
||||
Quirinus;7;10;10;2;Serdaigle
|
||||
Roger;9;10;10;8;Serdaigle
|
||||
Romilda;10;6;2;9;Griffondor
|
||||
Saemus;7;4;8;3;Griffondor
|
||||
Sirius;10;8;10;7;Griffondor
|
||||
Romilda;10;6;2;9;Gryffondor
|
||||
Saemus;7;4;8;3;Gryffondor
|
||||
Sirius;10;8;10;7;Gryffondor
|
||||
Susan;5;6;5;5;Poufsouffle
|
||||
Susan;4;10;10;5;Poufsouffle
|
||||
Ted;5;9;8;4;Poufsouffle
|
||||
Térence;6;9;2;8;Serpentar
|
||||
Térence;6;9;2;8;Serpentard
|
||||
Terry;8;4;10;5;Serdaigle
|
||||
Vincent;4;9;2;10;Serpentar
|
||||
Vincent;4;9;2;10;Serpentard
|
||||
|
||||
|
159
knn/test_choixpeau.py
Normal file
159
knn/test_choixpeau.py
Normal file
@@ -0,0 +1,159 @@
|
||||
import csv
|
||||
import time
|
||||
|
||||
# ── Chargement des données ────────────────────────────────────────────────────
|
||||
|
||||
def charger_table(nom_fichier):
|
||||
table = []
|
||||
with open(nom_fichier, 'r', newline="", encoding="utf-8") as csvfile:
|
||||
eleve_reader = csv.reader(csvfile, delimiter=";")
|
||||
eleve_reader.__next__()
|
||||
for eleve in eleve_reader:
|
||||
table.append({
|
||||
"nom": eleve[0],
|
||||
"courage": int(eleve[1]),
|
||||
"loyauté": int(eleve[2]),
|
||||
"sagesse": int(eleve[3]),
|
||||
"malice": int(eleve[4]),
|
||||
"maison": eleve[5].strip()
|
||||
})
|
||||
return table
|
||||
|
||||
# ── Algorithme KNN ────────────────────────────────────────────────────────────
|
||||
|
||||
def distance(eleve1, eleve2):
|
||||
return (abs(eleve1["courage"] - eleve2["courage"]) +
|
||||
abs(eleve1["loyauté"] - eleve2["loyauté"]) +
|
||||
abs(eleve1["sagesse"] - eleve2["sagesse"]) +
|
||||
abs(eleve1["malice"] - eleve2["malice"]))
|
||||
|
||||
def sept_voisins(table, nouveau):
|
||||
distances = [(distance(eleve, nouveau), eleve) for eleve in table]
|
||||
distances.sort(key=lambda x: x[0])
|
||||
return [eleve for d, eleve in distances[:7]]
|
||||
|
||||
def maison_majoritaire(voisins):
|
||||
frequences = {}
|
||||
for eleve in voisins:
|
||||
maison = eleve["maison"]
|
||||
frequences[maison] = frequences.get(maison, 0) + 1
|
||||
return max(frequences, key=frequences.get), frequences
|
||||
|
||||
# ── Affichage ─────────────────────────────────────────────────────────────────
|
||||
|
||||
MAISONS = {
|
||||
"Gryffondor": {
|
||||
"traits": "Courage, chevalerie et determination",
|
||||
"message": "Tu es du genre a te jeter dans la bataille sans trop reflechir.\nPoudlard a besoin de toi sur le terrain de Quidditch !"
|
||||
},
|
||||
"Serpentard": {
|
||||
"traits": "Malice, ambition et ressource",
|
||||
"message": "Tu sais ce que tu veux, et tu sais comment l'obtenir.\nMefie-toi quand meme de Lord Voldemort dans les couloirs."
|
||||
},
|
||||
"Serdaigle": {
|
||||
"traits": "Sagesse, creativite et esprit",
|
||||
"message": "Tu preferes comprendre avant d'agir. La bibliotheque\nde Poudlard va devenir ton deuxieme chez-toi."
|
||||
},
|
||||
"Poufsouffle": {
|
||||
"traits": "Loyaute, patience et equite",
|
||||
"message": "On peut compter sur toi. Toujours. Sans exception.\nCedric Diggory etait de Poufsouffle — ca dit tout."
|
||||
}
|
||||
}
|
||||
|
||||
def afficher_banniere(maison):
|
||||
largeur = 42
|
||||
print()
|
||||
print("=" * largeur)
|
||||
print("|" + " " * (largeur - 2) + "|")
|
||||
ligne = f" Le Choixpeau a decide : {maison.upper()}"
|
||||
print("|" + ligne.ljust(largeur - 2) + "|")
|
||||
print("|" + " " * (largeur - 2) + "|")
|
||||
infos = MAISONS.get(maison, {})
|
||||
traits = f" {infos.get('traits', '')}"
|
||||
print("|" + traits.ljust(largeur - 2) + "|")
|
||||
print("|" + " " * (largeur - 2) + "|")
|
||||
print("=" * largeur)
|
||||
print()
|
||||
print(infos.get("message", ""))
|
||||
print()
|
||||
|
||||
def afficher_voisins(voisins, moi):
|
||||
print("-" * 42)
|
||||
print(" Les 7 eleves de Poudlard qui te ressemblent le plus :")
|
||||
print()
|
||||
for v in voisins:
|
||||
d = distance(v, moi)
|
||||
print(f" {v['nom']:<12} ({v['maison']:<12}) distance : {d}")
|
||||
print("-" * 42)
|
||||
print()
|
||||
|
||||
# ── Saisie avec validation ────────────────────────────────────────────────────
|
||||
|
||||
QUESTIONS = [
|
||||
("courage", "Face au danger, tu fonces sans hesiter "),
|
||||
("loyauté", "Tu es fidele a tes amis, quoi qu'il arrive "),
|
||||
("sagesse", "Tu reflechis avant d'agir, tu observes, tu analyses "),
|
||||
("malice", "Tu sais trouver des strategies pour arriver a tes fins"),
|
||||
]
|
||||
|
||||
def poser_question(trait, description):
|
||||
while True:
|
||||
try:
|
||||
rep = input(f" {description} (1 a 10) : ").strip()
|
||||
valeur = int(rep)
|
||||
if 1 <= valeur <= 10:
|
||||
return valeur
|
||||
print(" --> Donne une valeur entre 1 et 10.")
|
||||
except ValueError:
|
||||
print(" --> Entre un nombre entier.")
|
||||
|
||||
# ── Programme principal ───────────────────────────────────────────────────────
|
||||
|
||||
def main():
|
||||
print()
|
||||
print("=" * 42)
|
||||
print("| |")
|
||||
print("| CHOIXPEAU MAGIQUE -- KNN |")
|
||||
print("| |")
|
||||
print("=" * 42)
|
||||
print()
|
||||
|
||||
try:
|
||||
poudlard = charger_table("choixpeauMagique.csv")
|
||||
except FileNotFoundError:
|
||||
print("Erreur : le fichier 'choixpeauMagique.csv' est introuvable.")
|
||||
print("Place-le dans le meme dossier que ce script.")
|
||||
return
|
||||
|
||||
prenom = input("Quel est ton prenom ? ").strip()
|
||||
if not prenom:
|
||||
prenom = "Mystere"
|
||||
|
||||
print()
|
||||
print(f"Bien, {prenom}. Reponds honnêtement à ces quatre questions.")
|
||||
print("Note-toi de 1 (pas du tout) à 10 (totalement).")
|
||||
print()
|
||||
|
||||
eleve = {"nom": prenom}
|
||||
for trait, description in QUESTIONS:
|
||||
eleve[trait] = poser_question(trait, description)
|
||||
|
||||
print()
|
||||
print("Le Choixpeau murmure quelque chose...")
|
||||
time.sleep(1)
|
||||
print("Il se tait.")
|
||||
time.sleep(1)
|
||||
print("Puis il crie :")
|
||||
time.sleep(0.8)
|
||||
|
||||
voisins = sept_voisins(poudlard, eleve)
|
||||
maison, frequences = maison_majoritaire(voisins)
|
||||
|
||||
afficher_banniere(maison)
|
||||
time.sleep(0.5)
|
||||
afficher_voisins(voisins, eleve)
|
||||
|
||||
print(f" Repartition du vote : {frequences}")
|
||||
print()
|
||||
|
||||
main()
|
||||
Reference in New Issue
Block a user