157 lines
4.6 KiB
Markdown
157 lines
4.6 KiB
Markdown
|
|
# 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
|