supprime le dossier evaluation du dépôt (évaluations sur Capytale)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -25,3 +25,4 @@ Licence_IA*.jpeg
|
||||
# Vidéos
|
||||
*.webm
|
||||
AMELIORATIONS.md
|
||||
representation_construits/evaluation/
|
||||
|
||||
@@ -1,476 +0,0 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"id": "cell-0",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"# TP Évaluation - Gestion de Playlists Spotify\n",
|
||||
"\n",
|
||||
"**Durée : 1h30**\n",
|
||||
"\n",
|
||||
"**Nom :** \n",
|
||||
"\n",
|
||||
"**Prénom :**\n",
|
||||
"\n",
|
||||
"---\n",
|
||||
"\n",
|
||||
"Dans ce TP, vous allez manipuler des structures de données Python pour gérer des playlists musicales.\n",
|
||||
"\n",
|
||||
"**Compétences évaluées :**\n",
|
||||
"- Manipulation de listes et dictionnaires\n",
|
||||
"- Parcours et filtrage de données\n",
|
||||
"- Écriture de fonctions"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"id": "cell-1",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Données initiales\n",
|
||||
"\n",
|
||||
"Voici les données avec lesquelles vous allez travailler. **Exécutez cette cellule avant de commencer.**"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "cell-2",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Base de données de chansons\n",
|
||||
"# Chaque chanson est un dictionnaire avec : titre, artiste, duree (en secondes), annee, streams\n",
|
||||
"catalogue = [\n",
|
||||
" {\"titre\": \"Blinding Lights\", \"artiste\": \"The Weeknd\", \"duree\": 203, \"annee\": 2020, \"streams\": 3500000000},\n",
|
||||
" {\"titre\": \"Shape of You\", \"artiste\": \"Ed Sheeran\", \"duree\": 234, \"annee\": 2017, \"streams\": 3400000000},\n",
|
||||
" {\"titre\": \"Dance Monkey\", \"artiste\": \"Tones and I\", \"duree\": 210, \"annee\": 2019, \"streams\": 2800000000},\n",
|
||||
" {\"titre\": \"Rockstar\", \"artiste\": \"Post Malone\", \"duree\": 218, \"annee\": 2017, \"streams\": 2700000000},\n",
|
||||
" {\"titre\": \"One Dance\", \"artiste\": \"Drake\", \"duree\": 173, \"annee\": 2016, \"streams\": 2600000000},\n",
|
||||
" {\"titre\": \"Sunflower\", \"artiste\": \"Post Malone\", \"duree\": 158, \"annee\": 2018, \"streams\": 2500000000},\n",
|
||||
" {\"titre\": \"Closer\", \"artiste\": \"The Chainsmokers\", \"duree\": 244, \"annee\": 2016, \"streams\": 2400000000},\n",
|
||||
" {\"titre\": \"Starboy\", \"artiste\": \"The Weeknd\", \"duree\": 230, \"annee\": 2016, \"streams\": 2300000000},\n",
|
||||
" {\"titre\": \"Perfect\", \"artiste\": \"Ed Sheeran\", \"duree\": 263, \"annee\": 2017, \"streams\": 2200000000},\n",
|
||||
" {\"titre\": \"Heat Waves\", \"artiste\": \"Glass Animals\", \"duree\": 239, \"annee\": 2020, \"streams\": 2100000000},\n",
|
||||
" {\"titre\": \"Bad Guy\", \"artiste\": \"Billie Eilish\", \"duree\": 194, \"annee\": 2019, \"streams\": 2000000000},\n",
|
||||
" {\"titre\": \"Levitating\", \"artiste\": \"Dua Lipa\", \"duree\": 203, \"annee\": 2020, \"streams\": 1900000000},\n",
|
||||
" {\"titre\": \"Save Your Tears\", \"artiste\": \"The Weeknd\", \"duree\": 216, \"annee\": 2020, \"streams\": 1800000000},\n",
|
||||
" {\"titre\": \"Thinking Out Loud\", \"artiste\": \"Ed Sheeran\", \"duree\": 281, \"annee\": 2014, \"streams\": 1700000000},\n",
|
||||
" {\"titre\": \"Stay\", \"artiste\": \"The Kid LAROI\", \"duree\": 141, \"annee\": 2021, \"streams\": 1600000000}\n",
|
||||
"]\n",
|
||||
"\n",
|
||||
"# Playlist de l'utilisateur (initialement vide)\n",
|
||||
"ma_playlist = []"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"id": "cell-3",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"---\n",
|
||||
"\n",
|
||||
"## Exercice 1 - Exploration du catalogue (25 min)\n",
|
||||
"\n",
|
||||
"### 1.1 Affichage formaté (4 pts)\n",
|
||||
"\n",
|
||||
"Écrivez une fonction `afficher_chanson(chanson)` qui prend un dictionnaire représentant une chanson et affiche ses informations.\n",
|
||||
"\n",
|
||||
"Exemple de sortie attendue :\n",
|
||||
"```\n",
|
||||
"Blinding Lights - The Weeknd (2020) | 3:23\n",
|
||||
"```\n",
|
||||
"\n",
|
||||
"*Aide : la durée est en secondes. Pour convertir : minutes = duree // 60, secondes = duree % 60*"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "cell-4",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"def afficher_chanson(chanson):\n",
|
||||
" # Récupérer les informations\n",
|
||||
" titre = chanson[\"titre\"]\n",
|
||||
" artiste = chanson[\"artiste\"]\n",
|
||||
" annee = chanson[\"annee\"]\n",
|
||||
" duree = chanson[\"duree\"]\n",
|
||||
" \n",
|
||||
" # Convertir la durée en minutes:secondes\n",
|
||||
" minutes = duree // 60\n",
|
||||
" secondes = duree % 60\n",
|
||||
" \n",
|
||||
" # Afficher (compléter le print)\n",
|
||||
" # Votre code ici\n",
|
||||
" pass\n",
|
||||
"\n",
|
||||
"# Test\n",
|
||||
"afficher_chanson(catalogue[0])"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"id": "cell-5",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"### 1.2 Statistiques de base (4 pts)\n",
|
||||
"\n",
|
||||
"Écrivez une fonction `statistiques_catalogue(liste_chansons)` qui renvoie un dictionnaire contenant :\n",
|
||||
"- `\"nombre\"` : le nombre total de chansons\n",
|
||||
"- `\"duree_totale\"` : la durée totale en secondes\n",
|
||||
"- `\"streams_total\"` : le nombre total de streams"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "cell-6",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"def statistiques_catalogue(liste_chansons):\n",
|
||||
" nombre = 0\n",
|
||||
" duree_totale = 0\n",
|
||||
" streams_total = 0\n",
|
||||
" \n",
|
||||
" for chanson in liste_chansons:\n",
|
||||
" # Votre code ici\n",
|
||||
" pass\n",
|
||||
" \n",
|
||||
" return {\n",
|
||||
" \"nombre\": nombre,\n",
|
||||
" \"duree_totale\": duree_totale,\n",
|
||||
" \"streams_total\": streams_total\n",
|
||||
" }\n",
|
||||
"\n",
|
||||
"# Test\n",
|
||||
"stats = statistiques_catalogue(catalogue)\n",
|
||||
"print(\"Nombre de chansons :\", stats[\"nombre\"])\n",
|
||||
"print(\"Duree totale :\", stats[\"duree_totale\"], \"secondes\")\n",
|
||||
"print(\"Streams total :\", stats[\"streams_total\"])"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"id": "cell-7",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"### 1.3 Liste des artistes (4 pts)\n",
|
||||
"\n",
|
||||
"Écrivez une fonction `artistes_uniques(liste_chansons)` qui renvoie la **liste sans doublons** de tous les artistes présents dans le catalogue, triée par ordre alphabétique.\n",
|
||||
"\n",
|
||||
"*Aide : vous pouvez utiliser `liste.sort()` pour trier une liste, et vérifier si un élément est déjà dans la liste avec `if element not in liste`*"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "cell-8",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"def artistes_uniques(liste_chansons):\n",
|
||||
" artistes = []\n",
|
||||
" \n",
|
||||
" for chanson in liste_chansons:\n",
|
||||
" artiste = chanson[\"artiste\"]\n",
|
||||
" # Ajouter l'artiste s'il n'est pas déjà dans la liste\n",
|
||||
" # Votre code ici\n",
|
||||
" pass\n",
|
||||
" \n",
|
||||
" # Trier la liste\n",
|
||||
" artistes.sort()\n",
|
||||
" return artistes\n",
|
||||
"\n",
|
||||
"# Test\n",
|
||||
"print(\"Artistes :\", artistes_uniques(catalogue))"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"id": "cell-9",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"---\n",
|
||||
"\n",
|
||||
"## Exercice 2 - Gestion de playlist (35 min)\n",
|
||||
"\n",
|
||||
"### 2.1 Recherche de chansons (5 pts)\n",
|
||||
"\n",
|
||||
"Écrivez une fonction `rechercher_par_artiste(liste_chansons, artiste)` qui renvoie la liste des chansons d'un artiste donné."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "cell-10",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"def rechercher_par_artiste(liste_chansons, artiste):\n",
|
||||
" resultats = []\n",
|
||||
" \n",
|
||||
" for chanson in liste_chansons:\n",
|
||||
" # Votre code ici\n",
|
||||
" pass\n",
|
||||
" \n",
|
||||
" return resultats\n",
|
||||
"\n",
|
||||
"# Test\n",
|
||||
"print(\"Chansons de The Weeknd :\")\n",
|
||||
"for c in rechercher_par_artiste(catalogue, \"The Weeknd\"):\n",
|
||||
" afficher_chanson(c)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"id": "cell-11",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"### 2.2 Recherche par année (5 pts)\n",
|
||||
"\n",
|
||||
"Écrivez une fonction `rechercher_par_annee(liste_chansons, annee)` qui renvoie la liste des chansons d'une année donnée."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "cell-12",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"def rechercher_par_annee(liste_chansons, annee):\n",
|
||||
" resultats = []\n",
|
||||
" \n",
|
||||
" for chanson in liste_chansons:\n",
|
||||
" # Votre code ici\n",
|
||||
" pass\n",
|
||||
" \n",
|
||||
" return resultats\n",
|
||||
"\n",
|
||||
"# Test\n",
|
||||
"print(\"Chansons de 2020 :\")\n",
|
||||
"for c in rechercher_par_annee(catalogue, 2020):\n",
|
||||
" afficher_chanson(c)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"id": "cell-13",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"### 2.3 Ajouter et retirer des chansons (6 pts)\n",
|
||||
"\n",
|
||||
"Écrivez deux fonctions :\n",
|
||||
"\n",
|
||||
"1. `ajouter_a_playlist(playlist, chanson)` : ajoute une chanson à la playlist **si elle n'y est pas déjà** (vérification par le titre). Renvoie `True` si l'ajout a réussi, `False` sinon.\n",
|
||||
"\n",
|
||||
"2. `retirer_de_playlist(playlist, titre)` : retire la chanson ayant ce titre de la playlist. Renvoie `True` si la suppression a réussi, `False` si la chanson n'était pas dans la playlist."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "cell-14",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"def ajouter_a_playlist(playlist, chanson):\n",
|
||||
" # Vérifier si la chanson est déjà dans la playlist\n",
|
||||
" for c in playlist:\n",
|
||||
" if c[\"titre\"] == chanson[\"titre\"]:\n",
|
||||
" return False\n",
|
||||
" \n",
|
||||
" # Si on arrive ici, la chanson n'est pas dans la playlist\n",
|
||||
" # Votre code ici\n",
|
||||
" pass\n",
|
||||
"\n",
|
||||
"def retirer_de_playlist(playlist, titre):\n",
|
||||
" # Chercher la chanson avec ce titre\n",
|
||||
" for i in range(len(playlist)):\n",
|
||||
" if playlist[i][\"titre\"] == titre:\n",
|
||||
" # Votre code ici (utiliser del ou pop)\n",
|
||||
" pass\n",
|
||||
" \n",
|
||||
" return False\n",
|
||||
"\n",
|
||||
"# Tests\n",
|
||||
"ma_playlist = []\n",
|
||||
"print(ajouter_a_playlist(ma_playlist, catalogue[0])) # True\n",
|
||||
"print(ajouter_a_playlist(ma_playlist, catalogue[0])) # False (deja present)\n",
|
||||
"print(ajouter_a_playlist(ma_playlist, catalogue[1])) # True\n",
|
||||
"print(\"Playlist :\", len(ma_playlist), \"chansons\")\n",
|
||||
"print(retirer_de_playlist(ma_playlist, \"Blinding Lights\")) # True\n",
|
||||
"print(retirer_de_playlist(ma_playlist, \"Blinding Lights\")) # False\n",
|
||||
"print(\"Playlist :\", len(ma_playlist), \"chansons\")"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"id": "cell-15",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"### 2.4 Top artistes (6 pts)\n",
|
||||
"\n",
|
||||
"Écrivez une fonction `compter_streams_par_artiste(liste_chansons)` qui renvoie un **dictionnaire** où les clés sont les noms d'artistes et les valeurs sont leur nombre total de streams.\n",
|
||||
"\n",
|
||||
"*Aide : utilisez `dico.get(cle, 0)` pour récupérer une valeur avec une valeur par défaut de 0 si la clé n'existe pas*"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "cell-16",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"def compter_streams_par_artiste(liste_chansons):\n",
|
||||
" streams_par_artiste = {}\n",
|
||||
" \n",
|
||||
" for chanson in liste_chansons:\n",
|
||||
" artiste = chanson[\"artiste\"]\n",
|
||||
" streams = chanson[\"streams\"]\n",
|
||||
" \n",
|
||||
" # Ajouter les streams au total de l'artiste\n",
|
||||
" # Votre code ici\n",
|
||||
" pass\n",
|
||||
" \n",
|
||||
" return streams_par_artiste\n",
|
||||
"\n",
|
||||
"# Test\n",
|
||||
"streams = compter_streams_par_artiste(catalogue)\n",
|
||||
"print(\"Streams par artiste :\")\n",
|
||||
"for artiste, total in streams.items():\n",
|
||||
" print(\" \", artiste, \":\", total)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"id": "cell-17",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"---\n",
|
||||
"\n",
|
||||
"## Exercice 3 - Bonus (20 min)\n",
|
||||
"\n",
|
||||
"### 3.1 Chanson la plus populaire (4 pts)\n",
|
||||
"\n",
|
||||
"Écrivez une fonction `chanson_plus_populaire(liste_chansons)` qui renvoie la chanson (dictionnaire) ayant le plus de streams."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "cell-18",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"def chanson_plus_populaire(liste_chansons):\n",
|
||||
" if len(liste_chansons) == 0:\n",
|
||||
" return None\n",
|
||||
" \n",
|
||||
" meilleure = liste_chansons[0]\n",
|
||||
" \n",
|
||||
" for chanson in liste_chansons:\n",
|
||||
" # Votre code ici\n",
|
||||
" pass\n",
|
||||
" \n",
|
||||
" return meilleure\n",
|
||||
"\n",
|
||||
"# Test\n",
|
||||
"top = chanson_plus_populaire(catalogue)\n",
|
||||
"print(\"Chanson la plus populaire :\")\n",
|
||||
"afficher_chanson(top)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"id": "cell-19",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"### 3.2 Trier par streams (4 pts)\n",
|
||||
"\n",
|
||||
"Écrivez une fonction `trier_par_streams(liste_chansons)` qui renvoie une **nouvelle liste** des chansons triées par nombre de streams décroissant.\n",
|
||||
"\n",
|
||||
"*Aide : utilisez `sorted(liste, key=..., reverse=True)`. La clé peut être une fonction lambda : `lambda c: c[\"streams\"]`*"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "cell-20",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"def trier_par_streams(liste_chansons):\n",
|
||||
" # Votre code ici\n",
|
||||
" pass\n",
|
||||
"\n",
|
||||
"# Test\n",
|
||||
"print(\"Top 5 des chansons :\")\n",
|
||||
"top5 = trier_par_streams(catalogue)[:5]\n",
|
||||
"for c in top5:\n",
|
||||
" afficher_chanson(c)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"id": "cell-21",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"### 3.3 Créer une playlist automatique (6 pts)\n",
|
||||
"\n",
|
||||
"Écrivez une fonction `creer_playlist_auto(liste_chansons, duree_max)` qui crée une playlist en ajoutant les chansons les plus populaires tant que la durée totale ne dépasse pas `duree_max` (en secondes).\n",
|
||||
"\n",
|
||||
"Renvoie la playlist créée."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "cell-22",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"def creer_playlist_auto(liste_chansons, duree_max):\n",
|
||||
" # Trier par streams décroissant\n",
|
||||
" chansons_triees = trier_par_streams(liste_chansons)\n",
|
||||
" \n",
|
||||
" playlist = []\n",
|
||||
" duree_actuelle = 0\n",
|
||||
" \n",
|
||||
" for chanson in chansons_triees:\n",
|
||||
" # Vérifier si on peut ajouter cette chanson\n",
|
||||
" # Votre code ici\n",
|
||||
" pass\n",
|
||||
" \n",
|
||||
" return playlist\n",
|
||||
"\n",
|
||||
"# Test : playlist de 10 minutes max (600 secondes)\n",
|
||||
"playlist_auto = creer_playlist_auto(catalogue, 600)\n",
|
||||
"print(\"Playlist automatique :\")\n",
|
||||
"duree_totale = 0\n",
|
||||
"for c in playlist_auto:\n",
|
||||
" afficher_chanson(c)\n",
|
||||
" duree_totale = duree_totale + c[\"duree\"]\n",
|
||||
"print(\"Duree totale :\", duree_totale, \"secondes\")"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"kernelspec": {
|
||||
"display_name": "Python 3",
|
||||
"language": "python",
|
||||
"name": "python3"
|
||||
},
|
||||
"language_info": {
|
||||
"name": "python",
|
||||
"version": "3.9.0"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 5
|
||||
}
|
||||
@@ -1,128 +0,0 @@
|
||||
# Aide - TP01 Spotify
|
||||
|
||||
## Rappels utiles
|
||||
|
||||
### Acceder aux elements d'un dictionnaire
|
||||
```python
|
||||
chanson = {"titre": "Blinding Lights", "artiste": "The Weeknd", "duree": 203}
|
||||
print(chanson["titre"]) # Blinding Lights
|
||||
print(chanson.get("note", 0)) # 0 (valeur par defaut si cle absente)
|
||||
```
|
||||
|
||||
### Convertir des secondes en minutes:secondes
|
||||
```python
|
||||
duree = 203 # secondes
|
||||
minutes = duree // 60 # Division entiere
|
||||
secondes = duree % 60 # Reste (modulo)
|
||||
print(minutes, ":", secondes) # 3 : 23
|
||||
```
|
||||
|
||||
### Parcourir une liste de dictionnaires
|
||||
```python
|
||||
for chanson in catalogue:
|
||||
print(chanson["titre"])
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Exercice 1
|
||||
|
||||
### 1.1 - Affichage formate
|
||||
- Utilisez print() avec des virgules : `print("Titre:", titre)`
|
||||
- Pour le formatage minutes:secondes, pensez a `//` et `%`
|
||||
- Concatenation avec `+` si besoin : `str(minutes) + ":" + str(secondes)`
|
||||
|
||||
### 1.2 - Statistiques
|
||||
- Initialisez un dictionnaire vide pour le resultat
|
||||
- Parcourez la liste avec une boucle for pour calculer la somme
|
||||
- `round(valeur)` arrondit a l'entier
|
||||
|
||||
```python
|
||||
total = 0
|
||||
for chanson in catalogue:
|
||||
total = total + chanson["duree"]
|
||||
```
|
||||
|
||||
### 1.3 - Artistes uniques
|
||||
- Parcourez et ajoutez dans une liste si pas deja present
|
||||
- `sorted(liste)` trie par ordre alphabetique
|
||||
|
||||
```python
|
||||
artistes = []
|
||||
for chanson in catalogue:
|
||||
if chanson["artiste"] not in artistes:
|
||||
artistes.append(chanson["artiste"])
|
||||
artistes.sort()
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Exercice 2
|
||||
|
||||
### 2.1 - Recherche
|
||||
- Utilisez `if critere == "artiste":` pour differencier les cas
|
||||
- Pour la recherche insensible a la casse : `"star".lower() in titre.lower()`
|
||||
- Renvoyez une nouvelle liste (ne modifiez pas l'originale)
|
||||
|
||||
### 2.2 - Ajouter/Retirer
|
||||
- Pour verifier si un titre existe deja :
|
||||
```python
|
||||
for chanson in playlist:
|
||||
if chanson["titre"] == nouveau_titre:
|
||||
return False # Deja present
|
||||
```
|
||||
|
||||
- Pour retirer, parcourez avec l'indice :
|
||||
```python
|
||||
for i in range(len(playlist)):
|
||||
if playlist[i]["titre"] == titre:
|
||||
playlist.pop(i)
|
||||
return True
|
||||
```
|
||||
|
||||
### 2.3 - Top artistes
|
||||
- Creez d'abord un dictionnaire `{artiste: total_streams}`
|
||||
- Parcourez le catalogue et cumulez les streams
|
||||
- Triez avec `sorted(dico.items(), key=lambda x: x[1], reverse=True)`
|
||||
|
||||
```python
|
||||
compteur = {}
|
||||
for chanson in catalogue:
|
||||
artiste = chanson["artiste"]
|
||||
if artiste not in compteur:
|
||||
compteur[artiste] = 0
|
||||
compteur[artiste] = compteur[artiste] + chanson["streams"]
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Exercice 3 (Bonus)
|
||||
|
||||
### 3.1 - Filtrage
|
||||
```python
|
||||
# Filtrer les chansons courtes
|
||||
resultat = []
|
||||
for chanson in catalogue:
|
||||
if chanson["duree"] < 200:
|
||||
resultat.append(chanson["titre"])
|
||||
```
|
||||
|
||||
### 3.2 - Recommandations
|
||||
1. D'abord, recuperez les artistes de la playlist utilisateur
|
||||
2. Ensuite, filtrez le catalogue pour ces artistes
|
||||
3. Excluez les chansons deja dans la playlist
|
||||
4. Triez par streams decroissant
|
||||
|
||||
### 3.3 - Playlist automatique
|
||||
- Triez d'abord le catalogue par streams decroissant
|
||||
- Parcourez et ajoutez si `duree_actuelle + chanson["duree"] <= duree_cible + tolerance`
|
||||
- Arretez quand `duree_actuelle >= duree_cible - tolerance`
|
||||
|
||||
---
|
||||
|
||||
## Pieges a eviter
|
||||
|
||||
1. **Ne pas modifier la liste originale** lors des recherches
|
||||
2. **Attention aux comparaisons de chaines** : utilisez `.lower()` pour ignorer la casse
|
||||
3. **Division par zero** : verifiez que la liste n'est pas vide avant de calculer une moyenne
|
||||
4. **Arrondi** : `round(x, 2)` pour 2 decimales, `round(x)` pour un entier
|
||||
@@ -1,491 +0,0 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"id": "cell-0",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"# TP Évaluation - Système d'inventaire Minecraft\n",
|
||||
"\n",
|
||||
"**Durée : 1h30**\n",
|
||||
"\n",
|
||||
"**Nom :** \n",
|
||||
"\n",
|
||||
"**Prénom :**\n",
|
||||
"\n",
|
||||
"---\n",
|
||||
"\n",
|
||||
"Dans ce TP, vous allez créer un système de gestion d'inventaire et de craft inspiré de Minecraft.\n",
|
||||
"\n",
|
||||
"**Compétences évaluées :**\n",
|
||||
"- Manipulation de dictionnaires\n",
|
||||
"- Parcours et modification de structures\n",
|
||||
"- Algorithmes de vérification"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"id": "cell-1",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Données initiales\n",
|
||||
"\n",
|
||||
"**Exécutez cette cellule avant de commencer.**"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "cell-2",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Inventaire du joueur : {nom_item: quantite}\n",
|
||||
"inventaire = {\n",
|
||||
" \"bois\": 64,\n",
|
||||
" \"pierre\": 128,\n",
|
||||
" \"fer\": 32,\n",
|
||||
" \"or\": 8,\n",
|
||||
" \"diamant\": 3,\n",
|
||||
" \"charbon\": 45,\n",
|
||||
" \"cuir\": 12,\n",
|
||||
" \"plume\": 24,\n",
|
||||
" \"ficelle\": 16\n",
|
||||
"}\n",
|
||||
"\n",
|
||||
"# Recettes de craft : {nom_resultat: {ingredient: quantite_necessaire}}\n",
|
||||
"recettes = {\n",
|
||||
" \"planche\": {\"bois\": 1},\n",
|
||||
" \"baton\": {\"planche\": 2},\n",
|
||||
" \"torche\": {\"baton\": 1, \"charbon\": 1},\n",
|
||||
" \"pioche_bois\": {\"planche\": 3, \"baton\": 2},\n",
|
||||
" \"pioche_pierre\": {\"pierre\": 3, \"baton\": 2},\n",
|
||||
" \"pioche_fer\": {\"fer\": 3, \"baton\": 2},\n",
|
||||
" \"pioche_diamant\": {\"diamant\": 3, \"baton\": 2},\n",
|
||||
" \"epee_fer\": {\"fer\": 2, \"baton\": 1},\n",
|
||||
" \"epee_diamant\": {\"diamant\": 2, \"baton\": 1},\n",
|
||||
" \"coffre\": {\"planche\": 8},\n",
|
||||
" \"four\": {\"pierre\": 8}\n",
|
||||
"}\n",
|
||||
"\n",
|
||||
"# Quantites produites par craft (par defaut 1, sauf exceptions)\n",
|
||||
"quantites_produites = {\n",
|
||||
" \"planche\": 4,\n",
|
||||
" \"baton\": 4,\n",
|
||||
" \"torche\": 4\n",
|
||||
"}\n",
|
||||
"\n",
|
||||
"# Valeurs des items en emeraudes\n",
|
||||
"valeurs = {\n",
|
||||
" \"bois\": 1, \"pierre\": 1, \"fer\": 5, \"or\": 10, \"diamant\": 50,\n",
|
||||
" \"charbon\": 2, \"cuir\": 3, \"plume\": 1, \"ficelle\": 2,\n",
|
||||
" \"planche\": 1, \"baton\": 1, \"torche\": 3\n",
|
||||
"}"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"id": "cell-3",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"---\n",
|
||||
"\n",
|
||||
"## Exercice 1 - Gestion de l'inventaire (25 min)\n",
|
||||
"\n",
|
||||
"### 1.1 Affichage de l'inventaire (4 pts)\n",
|
||||
"\n",
|
||||
"Écrivez une fonction `afficher_inventaire(inv)` qui affiche l'inventaire de manière formatée.\n",
|
||||
"\n",
|
||||
"Exemple de sortie :\n",
|
||||
"```\n",
|
||||
"=== INVENTAIRE ===\n",
|
||||
"bois : 64\n",
|
||||
"pierre : 128\n",
|
||||
"fer : 32\n",
|
||||
"...\n",
|
||||
"==================\n",
|
||||
"```"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "cell-4",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"def afficher_inventaire(inv):\n",
|
||||
" print(\"=== INVENTAIRE ===\")\n",
|
||||
" \n",
|
||||
" for item, quantite in inv.items():\n",
|
||||
" # Votre code ici\n",
|
||||
" pass\n",
|
||||
" \n",
|
||||
" print(\"==================\")\n",
|
||||
"\n",
|
||||
"# Test\n",
|
||||
"afficher_inventaire(inventaire)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"id": "cell-5",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"### 1.2 Ajouter un item (4 pts)\n",
|
||||
"\n",
|
||||
"Écrivez une fonction `ajouter_item(inv, item, quantite)` qui ajoute la quantité à l'item.\n",
|
||||
"\n",
|
||||
"Si l'item n'existe pas dans l'inventaire, il doit être créé.\n",
|
||||
"\n",
|
||||
"*Aide : utilisez `inv.get(item, 0)` pour obtenir la quantité actuelle (0 si l'item n'existe pas)*"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "cell-6",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"def ajouter_item(inv, item, quantite):\n",
|
||||
" # Votre code ici\n",
|
||||
" pass\n",
|
||||
"\n",
|
||||
"# Tests\n",
|
||||
"test_inv = {\"bois\": 10}\n",
|
||||
"ajouter_item(test_inv, \"bois\", 5)\n",
|
||||
"print(\"Apres ajout de 5 bois :\", test_inv)\n",
|
||||
"ajouter_item(test_inv, \"fer\", 3)\n",
|
||||
"print(\"Apres ajout de 3 fer :\", test_inv)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"id": "cell-7",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"### 1.3 Retirer un item (4 pts)\n",
|
||||
"\n",
|
||||
"Écrivez une fonction `retirer_item(inv, item, quantite)` qui retire la quantité de l'item.\n",
|
||||
"\n",
|
||||
"- Renvoie `True` si le retrait a réussi\n",
|
||||
"- Renvoie `False` si la quantité est insuffisante (et ne modifie pas l'inventaire)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "cell-8",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"def retirer_item(inv, item, quantite):\n",
|
||||
" # Verifier si l'item existe et en quantite suffisante\n",
|
||||
" quantite_actuelle = inv.get(item, 0)\n",
|
||||
" \n",
|
||||
" if quantite_actuelle < quantite:\n",
|
||||
" return False\n",
|
||||
" \n",
|
||||
" # Retirer la quantite\n",
|
||||
" # Votre code ici\n",
|
||||
" pass\n",
|
||||
"\n",
|
||||
"# Tests\n",
|
||||
"test_inv = {\"bois\": 10, \"pierre\": 5}\n",
|
||||
"print(\"Retirer 5 bois :\", retirer_item(test_inv, \"bois\", 5))\n",
|
||||
"print(\"Inventaire :\", test_inv)\n",
|
||||
"print(\"Retirer 100 bois :\", retirer_item(test_inv, \"bois\", 100))\n",
|
||||
"print(\"Inventaire :\", test_inv)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"id": "cell-9",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"### 1.4 Valeur de l'inventaire (4 pts)\n",
|
||||
"\n",
|
||||
"Écrivez une fonction `calculer_valeur(inv, valeurs)` qui renvoie la valeur totale de l'inventaire.\n",
|
||||
"\n",
|
||||
"*Note : si un item n'a pas de valeur définie, il vaut 0*"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "cell-10",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"def calculer_valeur(inv, valeurs):\n",
|
||||
" total = 0\n",
|
||||
" \n",
|
||||
" for item, quantite in inv.items():\n",
|
||||
" # Recuperer la valeur de l'item (0 si pas definie)\n",
|
||||
" valeur_unitaire = valeurs.get(item, 0)\n",
|
||||
" # Votre code ici\n",
|
||||
" pass\n",
|
||||
" \n",
|
||||
" return total\n",
|
||||
"\n",
|
||||
"# Test\n",
|
||||
"print(\"Valeur totale :\", calculer_valeur(inventaire, valeurs), \"emeraudes\")"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"id": "cell-11",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"---\n",
|
||||
"\n",
|
||||
"## Exercice 2 - Système de craft (35 min)\n",
|
||||
"\n",
|
||||
"### 2.1 Vérifier si un craft est possible (5 pts)\n",
|
||||
"\n",
|
||||
"Écrivez une fonction `peut_crafter(inv, recette)` qui renvoie `True` si l'inventaire contient tous les ingrédients nécessaires pour la recette, `False` sinon.\n",
|
||||
"\n",
|
||||
"*Note : `recette` est un dictionnaire `{ingredient: quantite_necessaire}`*"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "cell-12",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"def peut_crafter(inv, recette):\n",
|
||||
" for ingredient, quantite_necessaire in recette.items():\n",
|
||||
" quantite_disponible = inv.get(ingredient, 0)\n",
|
||||
" \n",
|
||||
" # Verifier si on a assez\n",
|
||||
" # Votre code ici\n",
|
||||
" pass\n",
|
||||
" \n",
|
||||
" return True\n",
|
||||
"\n",
|
||||
"# Tests\n",
|
||||
"print(\"Peut crafter planche ?\", peut_crafter(inventaire, recettes[\"planche\"]))\n",
|
||||
"print(\"Peut crafter pioche_diamant ?\", peut_crafter(inventaire, recettes[\"pioche_diamant\"]))"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"id": "cell-13",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"### 2.2 Effectuer un craft (6 pts)\n",
|
||||
"\n",
|
||||
"Écrivez une fonction `crafter(inv, nom_item, recettes, quantites_produites)` qui :\n",
|
||||
"1. Vérifie si le craft est possible\n",
|
||||
"2. Si oui, retire les ingrédients et ajoute le résultat\n",
|
||||
"3. Renvoie `True` si le craft a réussi, `False` sinon\n",
|
||||
"\n",
|
||||
"*Note : utilisez `quantites_produites.get(nom_item, 1)` pour obtenir la quantité produite (1 par défaut)*"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "cell-14",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"def crafter(inv, nom_item, recettes, quantites_produites):\n",
|
||||
" # Verifier que la recette existe\n",
|
||||
" if nom_item not in recettes:\n",
|
||||
" print(\"Recette inconnue :\", nom_item)\n",
|
||||
" return False\n",
|
||||
" \n",
|
||||
" recette = recettes[nom_item]\n",
|
||||
" \n",
|
||||
" # Verifier si le craft est possible\n",
|
||||
" if not peut_crafter(inv, recette):\n",
|
||||
" print(\"Ingredients insuffisants pour\", nom_item)\n",
|
||||
" return False\n",
|
||||
" \n",
|
||||
" # Retirer les ingredients\n",
|
||||
" for ingredient, quantite in recette.items():\n",
|
||||
" retirer_item(inv, ingredient, quantite)\n",
|
||||
" \n",
|
||||
" # Ajouter le resultat\n",
|
||||
" quantite_produite = quantites_produites.get(nom_item, 1)\n",
|
||||
" # Votre code ici\n",
|
||||
" pass\n",
|
||||
"\n",
|
||||
"# Test\n",
|
||||
"test_inv = {\"bois\": 10, \"charbon\": 5}\n",
|
||||
"print(\"Inventaire avant :\", test_inv)\n",
|
||||
"\n",
|
||||
"crafter(test_inv, \"planche\", recettes, quantites_produites)\n",
|
||||
"print(\"Apres craft de planches :\", test_inv)\n",
|
||||
"\n",
|
||||
"crafter(test_inv, \"baton\", recettes, quantites_produites)\n",
|
||||
"print(\"Apres craft de batons :\", test_inv)\n",
|
||||
"\n",
|
||||
"crafter(test_inv, \"torche\", recettes, quantites_produites)\n",
|
||||
"print(\"Apres craft de torches :\", test_inv)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"id": "cell-15",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"### 2.3 Lister les crafts possibles (6 pts)\n",
|
||||
"\n",
|
||||
"Écrivez une fonction `lister_crafts_possibles(inv, recettes)` qui renvoie la **liste des noms** de tous les items qu'il est possible de crafter avec l'inventaire actuel."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "cell-16",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"def lister_crafts_possibles(inv, recettes):\n",
|
||||
" possibles = []\n",
|
||||
" \n",
|
||||
" for nom_item, recette in recettes.items():\n",
|
||||
" # Votre code ici\n",
|
||||
" pass\n",
|
||||
" \n",
|
||||
" return possibles\n",
|
||||
"\n",
|
||||
"# Test\n",
|
||||
"print(\"Crafts possibles :\")\n",
|
||||
"print(lister_crafts_possibles(inventaire, recettes))"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"id": "cell-17",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"---\n",
|
||||
"\n",
|
||||
"## Exercice 3 - Bonus (20 min)\n",
|
||||
"\n",
|
||||
"### 3.1 Nombre maximum de crafts (5 pts)\n",
|
||||
"\n",
|
||||
"Écrivez une fonction `nb_max_craft(inv, recette)` qui renvoie le nombre maximum de fois qu'on peut effectuer un craft avec l'inventaire actuel.\n",
|
||||
"\n",
|
||||
"*Aide : pour chaque ingrédient, calculez `quantite_disponible // quantite_necessaire`, puis prenez le minimum*"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "cell-18",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"def nb_max_craft(inv, recette):\n",
|
||||
" if not peut_crafter(inv, recette):\n",
|
||||
" return 0\n",
|
||||
" \n",
|
||||
" ratios = []\n",
|
||||
" \n",
|
||||
" for ingredient, quantite_necessaire in recette.items():\n",
|
||||
" quantite_disponible = inv.get(ingredient, 0)\n",
|
||||
" # Calculer combien de crafts possibles avec cet ingredient\n",
|
||||
" # Votre code ici\n",
|
||||
" pass\n",
|
||||
" \n",
|
||||
" return min(ratios)\n",
|
||||
"\n",
|
||||
"# Tests\n",
|
||||
"print(\"Nb max de planches :\", nb_max_craft(inventaire, recettes[\"planche\"]))\n",
|
||||
"print(\"Nb max de torches :\", nb_max_craft(inventaire, recettes[\"torche\"]))\n",
|
||||
"print(\"Nb max de pioche_diamant :\", nb_max_craft(inventaire, recettes[\"pioche_diamant\"]))"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"id": "cell-19",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"### 3.2 Crafts avec compteur (5 pts)\n",
|
||||
"\n",
|
||||
"Écrivez une fonction `crafts_avec_compteur(inv, recettes)` qui renvoie un **dictionnaire** `{nom_item: nombre_max}` pour tous les items qu'on peut crafter au moins une fois."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "cell-20",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"def crafts_avec_compteur(inv, recettes):\n",
|
||||
" resultat = {}\n",
|
||||
" \n",
|
||||
" for nom_item, recette in recettes.items():\n",
|
||||
" nb = nb_max_craft(inv, recette)\n",
|
||||
" # Ajouter au resultat si nb > 0\n",
|
||||
" # Votre code ici\n",
|
||||
" pass\n",
|
||||
" \n",
|
||||
" return resultat\n",
|
||||
"\n",
|
||||
"# Test\n",
|
||||
"print(\"Crafts disponibles :\")\n",
|
||||
"for item, nb in crafts_avec_compteur(inventaire, recettes).items():\n",
|
||||
" print(\" \", item, \":\", nb, \"x\")"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"id": "cell-21",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"### 3.3 Item le plus rentable (4 pts)\n",
|
||||
"\n",
|
||||
"Écrivez une fonction `item_plus_rentable(inv, recettes, valeurs)` qui renvoie le nom de l'item craftable qui a la meilleure valeur de revente parmi ceux qu'on peut crafter."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "cell-22",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"def item_plus_rentable(inv, recettes, valeurs):\n",
|
||||
" possibles = lister_crafts_possibles(inv, recettes)\n",
|
||||
" \n",
|
||||
" if len(possibles) == 0:\n",
|
||||
" return None\n",
|
||||
" \n",
|
||||
" meilleur = possibles[0]\n",
|
||||
" meilleure_valeur = valeurs.get(meilleur, 0)\n",
|
||||
" \n",
|
||||
" for item in possibles:\n",
|
||||
" valeur = valeurs.get(item, 0)\n",
|
||||
" # Votre code ici\n",
|
||||
" pass\n",
|
||||
" \n",
|
||||
" return meilleur\n",
|
||||
"\n",
|
||||
"# Test\n",
|
||||
"print(\"Item le plus rentable a crafter :\", item_plus_rentable(inventaire, recettes, valeurs))"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"kernelspec": {
|
||||
"display_name": "Python 3",
|
||||
"language": "python",
|
||||
"name": "python3"
|
||||
},
|
||||
"language_info": {
|
||||
"name": "python",
|
||||
"version": "3.9.0"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 5
|
||||
}
|
||||
@@ -1,133 +0,0 @@
|
||||
# Aide - TP02 Minecraft
|
||||
|
||||
## Rappels utiles
|
||||
|
||||
### Verifier si une cle existe dans un dictionnaire
|
||||
```python
|
||||
inventaire = {"bois": 64, "pierre": 32}
|
||||
|
||||
if "fer" in inventaire:
|
||||
print("Vous avez du fer")
|
||||
else:
|
||||
print("Pas de fer")
|
||||
|
||||
# Ou avec get (renvoie 0 si absent)
|
||||
quantite = inventaire.get("fer", 0)
|
||||
```
|
||||
|
||||
### Modifier un dictionnaire
|
||||
```python
|
||||
# Ajouter ou modifier
|
||||
inventaire["fer"] = 10
|
||||
|
||||
# Supprimer
|
||||
del inventaire["fer"]
|
||||
|
||||
# Ajouter a une valeur existante
|
||||
inventaire["bois"] = inventaire.get("bois", 0) + 5
|
||||
```
|
||||
|
||||
### Trier un dictionnaire par valeur
|
||||
```python
|
||||
# Trier par valeur decroissante
|
||||
items_tries = sorted(inventaire.items(), key=lambda x: x[1], reverse=True)
|
||||
# Resultat : [("bois", 64), ("pierre", 32)]
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Exercice 1
|
||||
|
||||
### 1.1 - Affichage inventaire
|
||||
- `sorted(inv.items(), key=lambda x: x[1], reverse=True)` pour trier par quantite
|
||||
- Utilisez print() avec des virgules pour afficher
|
||||
|
||||
```python
|
||||
for item, quantite in inventaire.items():
|
||||
print(item, ":", quantite)
|
||||
```
|
||||
|
||||
### 1.2 - Operations
|
||||
- Pour ajouter : `inv[item] = inv.get(item, 0) + quantite`
|
||||
- Pour retirer, **verifiez d'abord** que la quantite est suffisante
|
||||
- Ne modifiez l'inventaire que si l'operation est possible
|
||||
|
||||
### 1.3 - Valeur
|
||||
```python
|
||||
total = 0
|
||||
for item, qte in inv.items():
|
||||
if item in valeurs:
|
||||
total = total + qte * valeurs[item]
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Exercice 2
|
||||
|
||||
### 2.1 - Verifier craft possible
|
||||
```python
|
||||
def peut_crafter(inv, recette):
|
||||
for ingredient, qte_necessaire in recette.items():
|
||||
if inv.get(ingredient, 0) < qte_necessaire:
|
||||
return False
|
||||
return True
|
||||
```
|
||||
|
||||
### 2.2 - Effectuer un craft
|
||||
1. Verifiez d'abord avec `peut_crafter`
|
||||
2. Si possible, retirez les ingredients
|
||||
3. Ajoutez le resultat (attention a `quantites_produites`)
|
||||
```python
|
||||
qte_produite = quantites.get(nom_item, 1) # Par defaut 1
|
||||
```
|
||||
|
||||
### 2.3 - Crafts disponibles
|
||||
- Pour chaque recette, calculez combien de fois on peut la faire
|
||||
- Le nombre max = minimum des ratios `inv[ingredient] // qte_necessaire`
|
||||
```python
|
||||
def nb_max_craft(inv, recette):
|
||||
ratios = []
|
||||
for ing, qte in recette.items():
|
||||
if inv.get(ing, 0) < qte:
|
||||
return 0
|
||||
ratios.append(inv[ing] // qte)
|
||||
return min(ratios)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Exercice 3 (Bonus)
|
||||
|
||||
### 3.1 - Chaine de craft (recursivite)
|
||||
```python
|
||||
def ingredients_totaux(nom_item, recettes, quantite):
|
||||
if nom_item not in recettes:
|
||||
# C'est une matiere premiere
|
||||
return {nom_item: quantite}
|
||||
|
||||
resultat = {}
|
||||
for ingredient, qte in recettes[nom_item].items():
|
||||
sous_ingredients = ingredients_totaux(ingredient, recettes, qte * quantite)
|
||||
for ing, q in sous_ingredients.items():
|
||||
resultat[ing] = resultat.get(ing, 0) + q
|
||||
return resultat
|
||||
```
|
||||
|
||||
### 3.2 - Meilleur equipement
|
||||
- Definissez les tiers : `tiers = {"diamant": 4, "fer": 3, "pierre": 2, "bois": 1}`
|
||||
- Pour chaque type (pioche, epee, armure), testez du meilleur au moins bon
|
||||
- Utilisez `peut_crafter` pour verifier
|
||||
|
||||
### 3.3 - Liste de courses
|
||||
1. Calculez les ingredients totaux pour chaque objectif
|
||||
2. Soustrayez ce qui est deja dans l'inventaire
|
||||
3. Ne gardez que les quantites positives (ce qui manque)
|
||||
|
||||
---
|
||||
|
||||
## Pieges a eviter
|
||||
|
||||
1. **Quantites produites** : un craft de planches donne 4 planches, pas 1 !
|
||||
2. **Modification de dictionnaire** : creez une copie si necessaire avec `inv.copy()`
|
||||
3. **Division entiere** : utilisez `//` pour obtenir un entier
|
||||
4. **Recette inexistante** : verifiez que `nom_item in recettes`
|
||||
@@ -1,509 +0,0 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"id": "cell-0",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"# TP Évaluation - Analyse de réseau social Instagram\n",
|
||||
"\n",
|
||||
"**Durée : 1h30**\n",
|
||||
"\n",
|
||||
"**Nom :** \n",
|
||||
"\n",
|
||||
"**Prénom :**\n",
|
||||
"\n",
|
||||
"---\n",
|
||||
"\n",
|
||||
"Dans ce TP, vous allez analyser un mini réseau social inspiré d'Instagram.\n",
|
||||
"\n",
|
||||
"**Compétences évaluées :**\n",
|
||||
"- Manipulation de dictionnaires imbriqués\n",
|
||||
"- Parcours de structures complexes\n",
|
||||
"- Algorithmes de recherche et filtrage"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"id": "cell-1",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Données initiales\n",
|
||||
"\n",
|
||||
"**Exécutez cette cellule avant de commencer.**"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "cell-2",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Base de données des utilisateurs\n",
|
||||
"# Structure : {username: {infos du profil}}\n",
|
||||
"utilisateurs = {\n",
|
||||
" \"@music_lover\": {\n",
|
||||
" \"nom\": \"Emma Martin\",\n",
|
||||
" \"bio\": \"Fan de musique\",\n",
|
||||
" \"verifie\": False,\n",
|
||||
" \"followers\": [\"@tech_geek\", \"@foodie_paris\", \"@travel_adventures\"],\n",
|
||||
" \"following\": [\"@tech_geek\", \"@fashion_style\"],\n",
|
||||
" \"posts\": [\n",
|
||||
" {\"id\": 1, \"type\": \"photo\", \"likes\": 234, \"commentaires\": 12},\n",
|
||||
" {\"id\": 2, \"type\": \"reel\", \"likes\": 1520, \"commentaires\": 89}\n",
|
||||
" ]\n",
|
||||
" },\n",
|
||||
" \"@tech_geek\": {\n",
|
||||
" \"nom\": \"Lucas Bernard\",\n",
|
||||
" \"bio\": \"Developpeur Python\",\n",
|
||||
" \"verifie\": True,\n",
|
||||
" \"followers\": [\"@music_lover\", \"@foodie_paris\", \"@fashion_style\", \"@travel_adventures\"],\n",
|
||||
" \"following\": [\"@music_lover\", \"@foodie_paris\"],\n",
|
||||
" \"posts\": [\n",
|
||||
" {\"id\": 3, \"type\": \"photo\", \"likes\": 567, \"commentaires\": 34},\n",
|
||||
" {\"id\": 4, \"type\": \"photo\", \"likes\": 892, \"commentaires\": 67},\n",
|
||||
" {\"id\": 5, \"type\": \"reel\", \"likes\": 3420, \"commentaires\": 156}\n",
|
||||
" ]\n",
|
||||
" },\n",
|
||||
" \"@foodie_paris\": {\n",
|
||||
" \"nom\": \"Sophie Dubois\",\n",
|
||||
" \"bio\": \"Food blogger Paris\",\n",
|
||||
" \"verifie\": True,\n",
|
||||
" \"followers\": [\"@tech_geek\", \"@fashion_style\"],\n",
|
||||
" \"following\": [\"@music_lover\", \"@tech_geek\", \"@fashion_style\", \"@travel_adventures\"],\n",
|
||||
" \"posts\": [\n",
|
||||
" {\"id\": 6, \"type\": \"photo\", \"likes\": 1205, \"commentaires\": 78},\n",
|
||||
" {\"id\": 7, \"type\": \"reel\", \"likes\": 4532, \"commentaires\": 234}\n",
|
||||
" ]\n",
|
||||
" },\n",
|
||||
" \"@fashion_style\": {\n",
|
||||
" \"nom\": \"Marie Laurent\",\n",
|
||||
" \"bio\": \"Mode et tendances\",\n",
|
||||
" \"verifie\": False,\n",
|
||||
" \"followers\": [\"@music_lover\", \"@foodie_paris\"],\n",
|
||||
" \"following\": [\"@tech_geek\", \"@foodie_paris\", \"@travel_adventures\"],\n",
|
||||
" \"posts\": [\n",
|
||||
" {\"id\": 8, \"type\": \"photo\", \"likes\": 2341, \"commentaires\": 123},\n",
|
||||
" {\"id\": 9, \"type\": \"photo\", \"likes\": 1876, \"commentaires\": 98},\n",
|
||||
" {\"id\": 10, \"type\": \"reel\", \"likes\": 5678, \"commentaires\": 321}\n",
|
||||
" ]\n",
|
||||
" },\n",
|
||||
" \"@travel_adventures\": {\n",
|
||||
" \"nom\": \"Pierre Moreau\",\n",
|
||||
" \"bio\": \"Tour du monde\",\n",
|
||||
" \"verifie\": True,\n",
|
||||
" \"followers\": [\"@foodie_paris\", \"@fashion_style\"],\n",
|
||||
" \"following\": [\"@music_lover\"],\n",
|
||||
" \"posts\": [\n",
|
||||
" {\"id\": 11, \"type\": \"photo\", \"likes\": 3456, \"commentaires\": 187},\n",
|
||||
" {\"id\": 12, \"type\": \"reel\", \"likes\": 8901, \"commentaires\": 456}\n",
|
||||
" ]\n",
|
||||
" }\n",
|
||||
"}"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"id": "cell-3",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"---\n",
|
||||
"\n",
|
||||
"## Exercice 1 - Exploration des profils (25 min)\n",
|
||||
"\n",
|
||||
"### 1.1 Afficher un profil (4 pts)\n",
|
||||
"\n",
|
||||
"Écrivez une fonction `afficher_profil(username, utilisateurs)` qui affiche les informations d'un utilisateur.\n",
|
||||
"\n",
|
||||
"Exemple de sortie :\n",
|
||||
"```\n",
|
||||
"@tech_geek (verifie)\n",
|
||||
"Nom : Lucas Bernard\n",
|
||||
"Bio : Developpeur Python\n",
|
||||
"Followers : 4 | Following : 2\n",
|
||||
"Posts : 3\n",
|
||||
"```"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "cell-4",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"def afficher_profil(username, utilisateurs):\n",
|
||||
" # Verifier que l'utilisateur existe\n",
|
||||
" if username not in utilisateurs:\n",
|
||||
" print(\"Utilisateur non trouve\")\n",
|
||||
" return\n",
|
||||
" \n",
|
||||
" profil = utilisateurs[username]\n",
|
||||
" \n",
|
||||
" # Afficher le badge verifie si necessaire\n",
|
||||
" badge = \"\"\n",
|
||||
" if profil[\"verifie\"]:\n",
|
||||
" badge = \" (verifie)\"\n",
|
||||
" \n",
|
||||
" print(username + badge)\n",
|
||||
" print(\"Nom :\", profil[\"nom\"])\n",
|
||||
" # Completer l'affichage\n",
|
||||
" # Votre code ici\n",
|
||||
" pass\n",
|
||||
"\n",
|
||||
"# Test\n",
|
||||
"afficher_profil(\"@tech_geek\", utilisateurs)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"id": "cell-5",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"### 1.2 Compter les likes et commentaires (4 pts)\n",
|
||||
"\n",
|
||||
"Écrivez une fonction `stats_engagement(username, utilisateurs)` qui renvoie un dictionnaire contenant :\n",
|
||||
"- `\"total_likes\"` : somme des likes de tous les posts\n",
|
||||
"- `\"total_commentaires\"` : somme des commentaires\n",
|
||||
"- `\"nb_posts\"` : nombre de posts"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "cell-6",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"def stats_engagement(username, utilisateurs):\n",
|
||||
" profil = utilisateurs[username]\n",
|
||||
" posts = profil[\"posts\"]\n",
|
||||
" \n",
|
||||
" total_likes = 0\n",
|
||||
" total_commentaires = 0\n",
|
||||
" \n",
|
||||
" for post in posts:\n",
|
||||
" # Votre code ici\n",
|
||||
" pass\n",
|
||||
" \n",
|
||||
" return {\n",
|
||||
" \"total_likes\": total_likes,\n",
|
||||
" \"total_commentaires\": total_commentaires,\n",
|
||||
" \"nb_posts\": len(posts)\n",
|
||||
" }\n",
|
||||
"\n",
|
||||
"# Test\n",
|
||||
"stats = stats_engagement(\"@tech_geek\", utilisateurs)\n",
|
||||
"print(\"Stats de @tech_geek :\")\n",
|
||||
"print(\" Likes :\", stats[\"total_likes\"])\n",
|
||||
"print(\" Commentaires :\", stats[\"total_commentaires\"])\n",
|
||||
"print(\" Posts :\", stats[\"nb_posts\"])"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"id": "cell-7",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"### 1.3 Liste des comptes vérifiés (4 pts)\n",
|
||||
"\n",
|
||||
"Écrivez une fonction `comptes_verifies(utilisateurs)` qui renvoie la liste des usernames des comptes vérifiés."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "cell-8",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"def comptes_verifies(utilisateurs):\n",
|
||||
" verifies = []\n",
|
||||
" \n",
|
||||
" for username, profil in utilisateurs.items():\n",
|
||||
" # Votre code ici\n",
|
||||
" pass\n",
|
||||
" \n",
|
||||
" return verifies\n",
|
||||
"\n",
|
||||
"# Test\n",
|
||||
"print(\"Comptes verifies :\", comptes_verifies(utilisateurs))"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"id": "cell-9",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"---\n",
|
||||
"\n",
|
||||
"## Exercice 2 - Relations entre utilisateurs (35 min)\n",
|
||||
"\n",
|
||||
"### 2.1 Vérifier si deux utilisateurs sont amis mutuels (5 pts)\n",
|
||||
"\n",
|
||||
"Deux utilisateurs sont \"amis mutuels\" s'ils se suivent mutuellement (A suit B ET B suit A).\n",
|
||||
"\n",
|
||||
"Écrivez une fonction `sont_amis_mutuels(user1, user2, utilisateurs)` qui renvoie `True` ou `False`."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "cell-10",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"def sont_amis_mutuels(user1, user2, utilisateurs):\n",
|
||||
" # Recuperer les listes de following\n",
|
||||
" following_user1 = utilisateurs[user1][\"following\"]\n",
|
||||
" following_user2 = utilisateurs[user2][\"following\"]\n",
|
||||
" \n",
|
||||
" # Verifier si user1 suit user2 ET user2 suit user1\n",
|
||||
" # Votre code ici\n",
|
||||
" pass\n",
|
||||
"\n",
|
||||
"# Tests\n",
|
||||
"print(\"@music_lover et @tech_geek sont amis mutuels ?\", sont_amis_mutuels(\"@music_lover\", \"@tech_geek\", utilisateurs))\n",
|
||||
"print(\"@foodie_paris et @travel_adventures sont amis mutuels ?\", sont_amis_mutuels(\"@foodie_paris\", \"@travel_adventures\", utilisateurs))"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"id": "cell-11",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"### 2.2 Trouver tous les amis mutuels d'un utilisateur (6 pts)\n",
|
||||
"\n",
|
||||
"Écrivez une fonction `liste_amis_mutuels(username, utilisateurs)` qui renvoie la liste des usernames avec lesquels cet utilisateur est ami mutuel."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "cell-12",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"def liste_amis_mutuels(username, utilisateurs):\n",
|
||||
" amis = []\n",
|
||||
" \n",
|
||||
" # Pour chaque utilisateur qu'on suit\n",
|
||||
" for user_suivi in utilisateurs[username][\"following\"]:\n",
|
||||
" # Verifier s'il nous suit aussi\n",
|
||||
" # Votre code ici\n",
|
||||
" pass\n",
|
||||
" \n",
|
||||
" return amis\n",
|
||||
"\n",
|
||||
"# Test\n",
|
||||
"print(\"Amis mutuels de @tech_geek :\", liste_amis_mutuels(\"@tech_geek\", utilisateurs))"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"id": "cell-13",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"### 2.3 Classement par nombre de followers (6 pts)\n",
|
||||
"\n",
|
||||
"Écrivez une fonction `classement_followers(utilisateurs)` qui renvoie une liste de tuples `(username, nb_followers)` triée par nombre de followers décroissant.\n",
|
||||
"\n",
|
||||
"*Aide : utilisez `sorted(liste, key=lambda x: x[1], reverse=True)`*"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "cell-14",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"def classement_followers(utilisateurs):\n",
|
||||
" classement = []\n",
|
||||
" \n",
|
||||
" for username, profil in utilisateurs.items():\n",
|
||||
" nb_followers = len(profil[\"followers\"])\n",
|
||||
" # Ajouter le tuple (username, nb_followers)\n",
|
||||
" # Votre code ici\n",
|
||||
" pass\n",
|
||||
" \n",
|
||||
" # Trier par nb_followers decroissant\n",
|
||||
" classement = sorted(classement, key=lambda x: x[1], reverse=True)\n",
|
||||
" return classement\n",
|
||||
"\n",
|
||||
"# Test\n",
|
||||
"print(\"Classement par followers :\")\n",
|
||||
"for username, nb in classement_followers(utilisateurs):\n",
|
||||
" print(\" \", username, \":\", nb, \"followers\")"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"id": "cell-15",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"### 2.4 Suggestions d'amis (6 pts)\n",
|
||||
"\n",
|
||||
"Écrivez une fonction `suggestions_amis(username, utilisateurs)` qui suggère des comptes à suivre.\n",
|
||||
"\n",
|
||||
"Une suggestion est un compte que nos amis suivent mais que nous ne suivons pas encore (et qui n'est pas nous-même)."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "cell-16",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"def suggestions_amis(username, utilisateurs):\n",
|
||||
" suggestions = []\n",
|
||||
" mes_suivis = utilisateurs[username][\"following\"]\n",
|
||||
" \n",
|
||||
" # Pour chaque personne que je suis\n",
|
||||
" for ami in mes_suivis:\n",
|
||||
" # Regarder qui cet ami suit\n",
|
||||
" for suggestion in utilisateurs[ami][\"following\"]:\n",
|
||||
" # Verifier que ce n'est pas moi et que je ne le suis pas deja\n",
|
||||
" # Votre code ici\n",
|
||||
" pass\n",
|
||||
" \n",
|
||||
" return suggestions\n",
|
||||
"\n",
|
||||
"# Test\n",
|
||||
"print(\"Suggestions pour @music_lover :\", suggestions_amis(\"@music_lover\", utilisateurs))"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"id": "cell-17",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"---\n",
|
||||
"\n",
|
||||
"## Exercice 3 - Bonus (20 min)\n",
|
||||
"\n",
|
||||
"### 3.1 Posts populaires (5 pts)\n",
|
||||
"\n",
|
||||
"Écrivez une fonction `posts_populaires(utilisateurs, seuil_likes)` qui renvoie la liste de tous les posts ayant plus de `seuil_likes` likes.\n",
|
||||
"\n",
|
||||
"Chaque élément de la liste est un dictionnaire avec `\"auteur\"`, `\"post_id\"` et `\"likes\"`."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "cell-18",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"def posts_populaires(utilisateurs, seuil_likes):\n",
|
||||
" populaires = []\n",
|
||||
" \n",
|
||||
" for username, profil in utilisateurs.items():\n",
|
||||
" for post in profil[\"posts\"]:\n",
|
||||
" if post[\"likes\"] > seuil_likes:\n",
|
||||
" # Ajouter le post a la liste\n",
|
||||
" # Votre code ici\n",
|
||||
" pass\n",
|
||||
" \n",
|
||||
" return populaires\n",
|
||||
"\n",
|
||||
"# Test\n",
|
||||
"print(\"Posts avec plus de 3000 likes :\")\n",
|
||||
"for p in posts_populaires(utilisateurs, 3000):\n",
|
||||
" print(\" \", p[\"auteur\"], \"- post\", p[\"post_id\"], \":\", p[\"likes\"], \"likes\")"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"id": "cell-19",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"### 3.2 Meilleur taux d'engagement (5 pts)\n",
|
||||
"\n",
|
||||
"Le taux d'engagement = (total_likes + total_commentaires) / nb_followers\n",
|
||||
"\n",
|
||||
"Écrivez une fonction `meilleur_engagement(utilisateurs)` qui renvoie le username ayant le meilleur taux d'engagement."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "cell-20",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"def meilleur_engagement(utilisateurs):\n",
|
||||
" meilleur_user = None\n",
|
||||
" meilleur_taux = 0\n",
|
||||
" \n",
|
||||
" for username, profil in utilisateurs.items():\n",
|
||||
" # Calculer les stats\n",
|
||||
" stats = stats_engagement(username, utilisateurs)\n",
|
||||
" nb_followers = len(profil[\"followers\"])\n",
|
||||
" \n",
|
||||
" # Eviter division par zero\n",
|
||||
" if nb_followers == 0:\n",
|
||||
" continue\n",
|
||||
" \n",
|
||||
" taux = (stats[\"total_likes\"] + stats[\"total_commentaires\"]) / nb_followers\n",
|
||||
" \n",
|
||||
" # Comparer avec le meilleur\n",
|
||||
" # Votre code ici\n",
|
||||
" pass\n",
|
||||
" \n",
|
||||
" return meilleur_user\n",
|
||||
"\n",
|
||||
"# Test\n",
|
||||
"print(\"Meilleur taux d'engagement :\", meilleur_engagement(utilisateurs))"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"id": "cell-21",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"### 3.3 Compter les reels (4 pts)\n",
|
||||
"\n",
|
||||
"Écrivez une fonction `compter_par_type(utilisateurs)` qui renvoie un dictionnaire avec le nombre total de posts de chaque type (\"photo\" et \"reel\")."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "cell-22",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"def compter_par_type(utilisateurs):\n",
|
||||
" compteur = {\"photo\": 0, \"reel\": 0}\n",
|
||||
" \n",
|
||||
" for username, profil in utilisateurs.items():\n",
|
||||
" for post in profil[\"posts\"]:\n",
|
||||
" type_post = post[\"type\"]\n",
|
||||
" # Votre code ici\n",
|
||||
" pass\n",
|
||||
" \n",
|
||||
" return compteur\n",
|
||||
"\n",
|
||||
"# Test\n",
|
||||
"print(\"Nombre de posts par type :\", compter_par_type(utilisateurs))"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"kernelspec": {
|
||||
"display_name": "Python 3",
|
||||
"language": "python",
|
||||
"name": "python3"
|
||||
},
|
||||
"language_info": {
|
||||
"name": "python",
|
||||
"version": "3.9.0"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 5
|
||||
}
|
||||
@@ -1,181 +0,0 @@
|
||||
# Aide - TP03 Instagram
|
||||
|
||||
## Rappels utiles
|
||||
|
||||
### Acceder a des structures imbriquees
|
||||
```python
|
||||
utilisateurs = {
|
||||
"@music_lover": {
|
||||
"nom": "Emma Martin",
|
||||
"followers": ["@tech_geek", "@foodie_paris"],
|
||||
"posts": [
|
||||
{"id": 1, "likes": 234}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
# Acceder au nom
|
||||
nom = utilisateurs["@music_lover"]["nom"]
|
||||
|
||||
# Acceder au premier post
|
||||
premier_post = utilisateurs["@music_lover"]["posts"][0]
|
||||
|
||||
# Nombre de followers
|
||||
nb_followers = len(utilisateurs["@music_lover"]["followers"])
|
||||
```
|
||||
|
||||
### Parcourir un dictionnaire de dictionnaires
|
||||
```python
|
||||
for username, profil in utilisateurs.items():
|
||||
print(username, ":", profil["nom"])
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Exercice 1
|
||||
|
||||
### 1.1 - Affichage profil
|
||||
- Verifiez `profil["verifie"]` pour le badge
|
||||
- `len(profil["posts"])` pour le nombre de posts
|
||||
- `len(profil["followers"])` et `len(profil["following"])`
|
||||
|
||||
```python
|
||||
def afficher_profil(username, users):
|
||||
profil = users[username]
|
||||
print(username, "-", profil["nom"])
|
||||
print("Followers:", len(profil["followers"]))
|
||||
print("Posts:", len(profil["posts"]))
|
||||
```
|
||||
|
||||
### 1.2 - Statistiques d'engagement
|
||||
```python
|
||||
total_likes = 0
|
||||
for post in profil["posts"]:
|
||||
total_likes = total_likes + post["likes"]
|
||||
|
||||
total_commentaires = 0
|
||||
for post in profil["posts"]:
|
||||
total_commentaires = total_commentaires + post["commentaires"]
|
||||
|
||||
nb_followers = len(profil["followers"])
|
||||
|
||||
# Attention a la division par zero !
|
||||
if nb_followers > 0:
|
||||
taux = (total_likes + total_commentaires) / nb_followers
|
||||
else:
|
||||
taux = 0
|
||||
```
|
||||
|
||||
### 1.3 - Relations mutuelles
|
||||
```python
|
||||
def sont_amis_mutuels(user1, user2, users):
|
||||
# user1 suit user2 ET user2 suit user1
|
||||
suit_user2 = user2 in users[user1]["following"]
|
||||
suit_user1 = user1 in users[user2]["following"]
|
||||
return suit_user2 and suit_user1
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Exercice 2
|
||||
|
||||
### 2.1 - Top influenceurs
|
||||
```python
|
||||
# Creer liste de tuples (username, nb_followers)
|
||||
classement = []
|
||||
for user, profil in users.items():
|
||||
classement.append((user, len(profil["followers"])))
|
||||
|
||||
# Trier par nb_followers decroissant
|
||||
classement = sorted(classement, key=lambda x: x[1], reverse=True)
|
||||
|
||||
# Renvoyer les n premiers
|
||||
return classement[:n]
|
||||
```
|
||||
|
||||
### 2.2 - Posts viraux
|
||||
1. Parcourez tous les utilisateurs et leurs posts
|
||||
2. Filtrez les posts avec likes > 2000
|
||||
3. Creez un dictionnaire avec les infos demandees
|
||||
4. Triez par likes decroissant
|
||||
|
||||
```python
|
||||
viraux = []
|
||||
for username, profil in users.items():
|
||||
for post in profil["posts"]:
|
||||
if post["likes"] > 2000:
|
||||
viraux.append({
|
||||
"auteur": username,
|
||||
"post_id": post["id"],
|
||||
"likes": post["likes"]
|
||||
})
|
||||
```
|
||||
|
||||
### 2.3 - Suggestions
|
||||
1. Recuperez qui l'utilisateur suit
|
||||
2. Pour chacun, recuperez qui ILS suivent
|
||||
3. Comptez les occurrences (dictionnaire)
|
||||
4. Excluez l'utilisateur et ceux deja suivis
|
||||
|
||||
```python
|
||||
suggestions = {}
|
||||
for ami in users[username]["following"]:
|
||||
for suggestion in users[ami]["following"]:
|
||||
if suggestion != username and suggestion not in users[username]["following"]:
|
||||
if suggestion not in suggestions:
|
||||
suggestions[suggestion] = 0
|
||||
suggestions[suggestion] = suggestions[suggestion] + 1
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Exercice 3 (Bonus)
|
||||
|
||||
### 3.1 - Comptes verifies
|
||||
```python
|
||||
verifies = []
|
||||
for user, profil in users.items():
|
||||
if profil["verifie"]:
|
||||
verifies.append(user)
|
||||
```
|
||||
|
||||
### 3.2 - Total likes par user
|
||||
```python
|
||||
likes_par_user = {}
|
||||
for user, profil in users.items():
|
||||
total = 0
|
||||
for post in profil["posts"]:
|
||||
total = total + post["likes"]
|
||||
likes_par_user[user] = total
|
||||
```
|
||||
|
||||
### 3.3 - Feed personnalise
|
||||
```python
|
||||
def generer_feed(username, users, n):
|
||||
posts_feed = []
|
||||
suivis = users[username]["following"]
|
||||
|
||||
for auteur in suivis:
|
||||
est_ami_mutuel = username in users[auteur]["following"]
|
||||
|
||||
for post in users[auteur]["posts"]:
|
||||
score = post["likes"] + post["commentaires"] * 3
|
||||
if post["type"] == "reel":
|
||||
score = score * 1.5
|
||||
if est_ami_mutuel:
|
||||
score = score * 1.2
|
||||
|
||||
posts_feed.append({"auteur": auteur, "post": post, "score": score})
|
||||
|
||||
posts_feed = sorted(posts_feed, key=lambda x: x["score"], reverse=True)
|
||||
return posts_feed[:n]
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Pieges a eviter
|
||||
|
||||
1. **KeyError** : utilisez `users.get(username)` ou verifiez `if username in users`
|
||||
2. **Doublons** : verifiez avec `if element not in liste` avant d'ajouter
|
||||
3. **Ami mutuel vs follower** : un follower vous suit, un ami mutuel = vous vous suivez mutuellement
|
||||
4. **Division par zero** : verifiez `nb_followers > 0` avant de diviser
|
||||
@@ -1,500 +0,0 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"id": "cell-0",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"# TP Évaluation - Catalogue Netflix\n",
|
||||
"\n",
|
||||
"**Durée : 1h30**\n",
|
||||
"\n",
|
||||
"**Nom :** \n",
|
||||
"\n",
|
||||
"**Prénom :**\n",
|
||||
"\n",
|
||||
"---\n",
|
||||
"\n",
|
||||
"Dans ce TP, vous allez manipuler un catalogue de films et séries inspiré de Netflix.\n",
|
||||
"\n",
|
||||
"**Compétences évaluées :**\n",
|
||||
"- Manipulation de listes de dictionnaires\n",
|
||||
"- Filtrage et tri de données\n",
|
||||
"- Algorithmes de recherche"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"id": "cell-1",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Données initiales\n",
|
||||
"\n",
|
||||
"**Exécutez cette cellule avant de commencer.**"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "cell-2",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Catalogue de contenus\n",
|
||||
"# type: \"film\" ou \"serie\"\n",
|
||||
"# duree: en minutes (pour les films)\n",
|
||||
"# saisons et duree_moy: pour les series (duree moyenne par episode)\n",
|
||||
"catalogue = [\n",
|
||||
" {\"titre\": \"Stranger Things\", \"type\": \"serie\", \"genre\": [\"SF\", \"Horreur\"], \"annee\": 2016, \"note\": 8.7, \"saisons\": 4, \"duree_moy\": 50},\n",
|
||||
" {\"titre\": \"Breaking Bad\", \"type\": \"serie\", \"genre\": [\"Drame\", \"Thriller\"], \"annee\": 2008, \"note\": 9.5, \"saisons\": 5, \"duree_moy\": 47},\n",
|
||||
" {\"titre\": \"The Crown\", \"type\": \"serie\", \"genre\": [\"Drame\", \"Historique\"], \"annee\": 2016, \"note\": 8.6, \"saisons\": 6, \"duree_moy\": 58},\n",
|
||||
" {\"titre\": \"Squid Game\", \"type\": \"serie\", \"genre\": [\"Thriller\", \"Drame\"], \"annee\": 2021, \"note\": 8.0, \"saisons\": 1, \"duree_moy\": 55},\n",
|
||||
" {\"titre\": \"Wednesday\", \"type\": \"serie\", \"genre\": [\"Comedie\", \"Fantastique\"], \"annee\": 2022, \"note\": 8.1, \"saisons\": 1, \"duree_moy\": 45},\n",
|
||||
" {\"titre\": \"Inception\", \"type\": \"film\", \"genre\": [\"SF\", \"Action\"], \"annee\": 2010, \"note\": 8.8, \"duree\": 148},\n",
|
||||
" {\"titre\": \"The Dark Knight\", \"type\": \"film\", \"genre\": [\"Action\", \"Drame\"], \"annee\": 2008, \"note\": 9.0, \"duree\": 152},\n",
|
||||
" {\"titre\": \"Pulp Fiction\", \"type\": \"film\", \"genre\": [\"Drame\", \"Thriller\"], \"annee\": 1994, \"note\": 8.9, \"duree\": 154},\n",
|
||||
" {\"titre\": \"Interstellar\", \"type\": \"film\", \"genre\": [\"SF\", \"Drame\"], \"annee\": 2014, \"note\": 8.6, \"duree\": 169},\n",
|
||||
" {\"titre\": \"The Matrix\", \"type\": \"film\", \"genre\": [\"SF\", \"Action\"], \"annee\": 1999, \"note\": 8.7, \"duree\": 136},\n",
|
||||
" {\"titre\": \"Parasite\", \"type\": \"film\", \"genre\": [\"Thriller\", \"Comedie\"], \"annee\": 2019, \"note\": 8.5, \"duree\": 132},\n",
|
||||
" {\"titre\": \"Don't Look Up\", \"type\": \"film\", \"genre\": [\"Comedie\", \"SF\"], \"annee\": 2021, \"note\": 7.2, \"duree\": 138}\n",
|
||||
"]\n",
|
||||
"\n",
|
||||
"# Historique de visionnage\n",
|
||||
"historique = [\n",
|
||||
" {\"titre\": \"Stranger Things\", \"episodes_vus\": 34, \"note_perso\": 9},\n",
|
||||
" {\"titre\": \"Inception\", \"note_perso\": 10},\n",
|
||||
" {\"titre\": \"The Matrix\", \"note_perso\": 8},\n",
|
||||
" {\"titre\": \"Wednesday\", \"episodes_vus\": 8, \"note_perso\": 7}\n",
|
||||
"]\n",
|
||||
"\n",
|
||||
"# Ma liste (watchlist)\n",
|
||||
"ma_liste = [\"Breaking Bad\", \"Interstellar\", \"Parasite\"]"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"id": "cell-3",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"---\n",
|
||||
"\n",
|
||||
"## Exercice 1 - Exploration du catalogue (25 min)\n",
|
||||
"\n",
|
||||
"### 1.1 Afficher un contenu (4 pts)\n",
|
||||
"\n",
|
||||
"Écrivez une fonction `afficher_contenu(contenu)` qui affiche les informations d'un film ou d'une série.\n",
|
||||
"\n",
|
||||
"Pour un film : `Inception (2010) - Film | 2h28 | Note: 8.8`\n",
|
||||
"\n",
|
||||
"Pour une série : `Stranger Things (2016) - Serie | 4 saisons | Note: 8.7`\n",
|
||||
"\n",
|
||||
"*Aide : pour convertir les minutes en heures, utilisez `duree // 60` et `duree % 60`*"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "cell-4",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"def afficher_contenu(contenu):\n",
|
||||
" titre = contenu[\"titre\"]\n",
|
||||
" annee = contenu[\"annee\"]\n",
|
||||
" note = contenu[\"note\"]\n",
|
||||
" \n",
|
||||
" if contenu[\"type\"] == \"film\":\n",
|
||||
" duree = contenu[\"duree\"]\n",
|
||||
" heures = duree // 60\n",
|
||||
" minutes = duree % 60\n",
|
||||
" # Afficher les infos du film\n",
|
||||
" # Votre code ici\n",
|
||||
" pass\n",
|
||||
" else:\n",
|
||||
" saisons = contenu[\"saisons\"]\n",
|
||||
" # Afficher les infos de la serie\n",
|
||||
" # Votre code ici\n",
|
||||
" pass\n",
|
||||
"\n",
|
||||
"# Tests\n",
|
||||
"afficher_contenu(catalogue[0]) # Serie\n",
|
||||
"afficher_contenu(catalogue[5]) # Film"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"id": "cell-5",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"### 1.2 Compter films et séries (4 pts)\n",
|
||||
"\n",
|
||||
"Écrivez une fonction `compter_par_type(catalogue)` qui renvoie un dictionnaire avec le nombre de films et de séries."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "cell-6",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"def compter_par_type(catalogue):\n",
|
||||
" compteur = {\"film\": 0, \"serie\": 0}\n",
|
||||
" \n",
|
||||
" for contenu in catalogue:\n",
|
||||
" # Votre code ici\n",
|
||||
" pass\n",
|
||||
" \n",
|
||||
" return compteur\n",
|
||||
"\n",
|
||||
"# Test\n",
|
||||
"print(\"Contenu du catalogue :\", compter_par_type(catalogue))"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"id": "cell-7",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"### 1.3 Liste des genres (4 pts)\n",
|
||||
"\n",
|
||||
"Écrivez une fonction `tous_les_genres(catalogue)` qui renvoie la liste de tous les genres présents dans le catalogue, sans doublons, triée par ordre alphabétique."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "cell-8",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"def tous_les_genres(catalogue):\n",
|
||||
" genres = []\n",
|
||||
" \n",
|
||||
" for contenu in catalogue:\n",
|
||||
" for genre in contenu[\"genre\"]:\n",
|
||||
" if genre not in genres:\n",
|
||||
" # Votre code ici\n",
|
||||
" pass\n",
|
||||
" \n",
|
||||
" genres.sort()\n",
|
||||
" return genres\n",
|
||||
"\n",
|
||||
"# Test\n",
|
||||
"print(\"Genres disponibles :\", tous_les_genres(catalogue))"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"id": "cell-9",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"---\n",
|
||||
"\n",
|
||||
"## Exercice 2 - Recherche et filtrage (35 min)\n",
|
||||
"\n",
|
||||
"### 2.1 Rechercher par genre (5 pts)\n",
|
||||
"\n",
|
||||
"Écrivez une fonction `rechercher_par_genre(catalogue, genre)` qui renvoie la liste des contenus ayant ce genre."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "cell-10",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"def rechercher_par_genre(catalogue, genre):\n",
|
||||
" resultats = []\n",
|
||||
" \n",
|
||||
" for contenu in catalogue:\n",
|
||||
" if genre in contenu[\"genre\"]:\n",
|
||||
" # Votre code ici\n",
|
||||
" pass\n",
|
||||
" \n",
|
||||
" return resultats\n",
|
||||
"\n",
|
||||
"# Test\n",
|
||||
"print(\"Contenus SF :\")\n",
|
||||
"for c in rechercher_par_genre(catalogue, \"SF\"):\n",
|
||||
" afficher_contenu(c)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"id": "cell-11",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"### 2.2 Filtrer par note minimum (5 pts)\n",
|
||||
"\n",
|
||||
"Écrivez une fonction `filtrer_par_note(catalogue, note_min)` qui renvoie la liste des contenus ayant une note supérieure ou égale à `note_min`."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "cell-12",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"def filtrer_par_note(catalogue, note_min):\n",
|
||||
" resultats = []\n",
|
||||
" \n",
|
||||
" for contenu in catalogue:\n",
|
||||
" # Votre code ici\n",
|
||||
" pass\n",
|
||||
" \n",
|
||||
" return resultats\n",
|
||||
"\n",
|
||||
"# Test\n",
|
||||
"print(\"Contenus avec note >= 8.5 :\")\n",
|
||||
"for c in filtrer_par_note(catalogue, 8.5):\n",
|
||||
" afficher_contenu(c)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"id": "cell-13",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"### 2.3 Trier par note (6 pts)\n",
|
||||
"\n",
|
||||
"Écrivez une fonction `trier_par_note(catalogue)` qui renvoie une nouvelle liste triée par note décroissante.\n",
|
||||
"\n",
|
||||
"*Aide : utilisez `sorted(liste, key=lambda x: x[\"note\"], reverse=True)`*"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "cell-14",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"def trier_par_note(catalogue):\n",
|
||||
" # Votre code ici\n",
|
||||
" pass\n",
|
||||
"\n",
|
||||
"# Test\n",
|
||||
"print(\"Top 5 par note :\")\n",
|
||||
"for c in trier_par_note(catalogue)[:5]:\n",
|
||||
" afficher_contenu(c)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"id": "cell-15",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"### 2.4 Recherche combinée (6 pts)\n",
|
||||
"\n",
|
||||
"Écrivez une fonction `recherche_avancee(catalogue, type_contenu, genre, note_min)` qui filtre selon plusieurs critères.\n",
|
||||
"\n",
|
||||
"- `type_contenu` : \"film\", \"serie\" ou None (tous)\n",
|
||||
"- `genre` : un genre ou None (tous)\n",
|
||||
"- `note_min` : note minimum ou None (pas de filtre)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "cell-16",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"def recherche_avancee(catalogue, type_contenu, genre, note_min):\n",
|
||||
" resultats = []\n",
|
||||
" \n",
|
||||
" for contenu in catalogue:\n",
|
||||
" # Verifier le type (si specifie)\n",
|
||||
" if type_contenu != None and contenu[\"type\"] != type_contenu:\n",
|
||||
" continue\n",
|
||||
" \n",
|
||||
" # Verifier le genre (si specifie)\n",
|
||||
" if genre != None and genre not in contenu[\"genre\"]:\n",
|
||||
" continue\n",
|
||||
" \n",
|
||||
" # Verifier la note (si specifiee)\n",
|
||||
" # Votre code ici\n",
|
||||
" \n",
|
||||
" resultats.append(contenu)\n",
|
||||
" \n",
|
||||
" return resultats\n",
|
||||
"\n",
|
||||
"# Test\n",
|
||||
"print(\"Films SF avec note >= 8.5 :\")\n",
|
||||
"for c in recherche_avancee(catalogue, \"film\", \"SF\", 8.5):\n",
|
||||
" afficher_contenu(c)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"id": "cell-17",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"---\n",
|
||||
"\n",
|
||||
"## Exercice 3 - Bonus (20 min)\n",
|
||||
"\n",
|
||||
"### 3.1 Temps de visionnage (5 pts)\n",
|
||||
"\n",
|
||||
"Écrivez une fonction `temps_visionne(historique, catalogue)` qui calcule le temps total de visionnage en minutes.\n",
|
||||
"\n",
|
||||
"Pour un film : la durée complète.\n",
|
||||
"Pour une série : `episodes_vus * duree_moy`"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "cell-18",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"def temps_visionne(historique, catalogue):\n",
|
||||
" total_minutes = 0\n",
|
||||
" \n",
|
||||
" for h in historique:\n",
|
||||
" # Trouver le contenu dans le catalogue\n",
|
||||
" contenu = None\n",
|
||||
" for c in catalogue:\n",
|
||||
" if c[\"titre\"] == h[\"titre\"]:\n",
|
||||
" contenu = c\n",
|
||||
" break\n",
|
||||
" \n",
|
||||
" if contenu == None:\n",
|
||||
" continue\n",
|
||||
" \n",
|
||||
" if contenu[\"type\"] == \"film\":\n",
|
||||
" # Ajouter la duree du film\n",
|
||||
" # Votre code ici\n",
|
||||
" pass\n",
|
||||
" else:\n",
|
||||
" # Ajouter duree des episodes vus\n",
|
||||
" # Votre code ici\n",
|
||||
" pass\n",
|
||||
" \n",
|
||||
" return total_minutes\n",
|
||||
"\n",
|
||||
"# Test\n",
|
||||
"minutes = temps_visionne(historique, catalogue)\n",
|
||||
"heures = minutes // 60\n",
|
||||
"print(\"Temps total visionne :\", heures, \"h\", minutes % 60, \"min\")"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"id": "cell-19",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"### 3.2 Recommandation simple (5 pts)\n",
|
||||
"\n",
|
||||
"Écrivez une fonction `recommander(historique, catalogue)` qui recommande un contenu basé sur les genres préférés de l'utilisateur.\n",
|
||||
"\n",
|
||||
"1. Trouvez les genres des contenus dans l'historique\n",
|
||||
"2. Trouvez un contenu non vu qui a au moins un genre en commun\n",
|
||||
"3. Renvoyez le contenu avec la meilleure note"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "cell-20",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"def recommander(historique, catalogue):\n",
|
||||
" # Collecter les genres des contenus vus\n",
|
||||
" genres_aimes = []\n",
|
||||
" titres_vus = []\n",
|
||||
" \n",
|
||||
" for h in historique:\n",
|
||||
" titres_vus.append(h[\"titre\"])\n",
|
||||
" # Trouver le contenu pour recuperer ses genres\n",
|
||||
" for c in catalogue:\n",
|
||||
" if c[\"titre\"] == h[\"titre\"]:\n",
|
||||
" for g in c[\"genre\"]:\n",
|
||||
" if g not in genres_aimes:\n",
|
||||
" genres_aimes.append(g)\n",
|
||||
" \n",
|
||||
" # Trouver le meilleur contenu non vu avec un genre en commun\n",
|
||||
" meilleur = None\n",
|
||||
" meilleure_note = 0\n",
|
||||
" \n",
|
||||
" for c in catalogue:\n",
|
||||
" # Verifier que non vu\n",
|
||||
" if c[\"titre\"] in titres_vus:\n",
|
||||
" continue\n",
|
||||
" \n",
|
||||
" # Verifier qu'il a un genre en commun\n",
|
||||
" # Votre code ici\n",
|
||||
" pass\n",
|
||||
" \n",
|
||||
" return meilleur\n",
|
||||
"\n",
|
||||
"# Test\n",
|
||||
"reco = recommander(historique, catalogue)\n",
|
||||
"if reco:\n",
|
||||
" print(\"Recommandation :\")\n",
|
||||
" afficher_contenu(reco)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"id": "cell-21",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"### 3.3 Note moyenne par genre (4 pts)\n",
|
||||
"\n",
|
||||
"Écrivez une fonction `note_moyenne_par_genre(catalogue)` qui renvoie un dictionnaire `{genre: note_moyenne}`."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "cell-22",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"def note_moyenne_par_genre(catalogue):\n",
|
||||
" # Dictionnaire pour stocker somme et compteur par genre\n",
|
||||
" sommes = {}\n",
|
||||
" compteurs = {}\n",
|
||||
" \n",
|
||||
" for contenu in catalogue:\n",
|
||||
" for genre in contenu[\"genre\"]:\n",
|
||||
" if genre not in sommes:\n",
|
||||
" sommes[genre] = 0\n",
|
||||
" compteurs[genre] = 0\n",
|
||||
" sommes[genre] = sommes[genre] + contenu[\"note\"]\n",
|
||||
" compteurs[genre] = compteurs[genre] + 1\n",
|
||||
" \n",
|
||||
" # Calculer les moyennes\n",
|
||||
" moyennes = {}\n",
|
||||
" for genre in sommes:\n",
|
||||
" moyennes[genre] = round(sommes[genre] / compteurs[genre], 1)\n",
|
||||
" \n",
|
||||
" return moyennes\n",
|
||||
"\n",
|
||||
"# Test\n",
|
||||
"print(\"Note moyenne par genre :\")\n",
|
||||
"for genre, note in note_moyenne_par_genre(catalogue).items():\n",
|
||||
" print(\" \", genre, \":\", note)"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"kernelspec": {
|
||||
"display_name": "Python 3",
|
||||
"language": "python",
|
||||
"name": "python3"
|
||||
},
|
||||
"language_info": {
|
||||
"name": "python",
|
||||
"version": "3.9.0"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 5
|
||||
}
|
||||
@@ -1,232 +0,0 @@
|
||||
# Aide - TP04 Netflix
|
||||
|
||||
## Rappels utiles
|
||||
|
||||
### Differencier films et series
|
||||
```python
|
||||
contenu = catalogue[0]
|
||||
|
||||
if contenu["type"] == "serie":
|
||||
print(contenu["saisons"], "saisons")
|
||||
else:
|
||||
print("Duree:", contenu["duree"], "min")
|
||||
```
|
||||
|
||||
### Verifier si un element est dans une liste
|
||||
```python
|
||||
genres = ["SF", "Action"]
|
||||
if "SF" in genres:
|
||||
print("C'est de la science-fiction")
|
||||
```
|
||||
|
||||
### Joindre une liste en chaine
|
||||
```python
|
||||
genres = ["SF", "Action", "Thriller"]
|
||||
genres_str = ", ".join(genres) # "SF, Action, Thriller"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Exercice 1
|
||||
|
||||
### 1.1 - Affichage formate
|
||||
- Films : affichez la duree en heures:minutes (`duree // 60` et `duree % 60`)
|
||||
- Series : affichez le nombre de saisons et la duree moyenne par episode
|
||||
- Genres : `", ".join(contenu["genre"])` pour les separer par des virgules
|
||||
|
||||
```python
|
||||
def afficher_contenu(contenu):
|
||||
print(contenu["titre"], "(", contenu["annee"], ")")
|
||||
print("Genres:", ", ".join(contenu["genre"]))
|
||||
|
||||
if contenu["type"] == "film":
|
||||
heures = contenu["duree"] // 60
|
||||
minutes = contenu["duree"] % 60
|
||||
print("Duree:", heures, "h", minutes, "min")
|
||||
else:
|
||||
print("Saisons:", contenu["saisons"])
|
||||
```
|
||||
|
||||
### 1.2 - Statistiques
|
||||
```python
|
||||
nb_films = 0
|
||||
nb_series = 0
|
||||
for c in catalogue:
|
||||
if c["type"] == "film":
|
||||
nb_films = nb_films + 1
|
||||
else:
|
||||
nb_series = nb_series + 1
|
||||
```
|
||||
|
||||
Pour les genres uniques :
|
||||
```python
|
||||
tous_genres = []
|
||||
for c in catalogue:
|
||||
for g in c["genre"]:
|
||||
if g not in tous_genres:
|
||||
tous_genres.append(g)
|
||||
genres_tries = sorted(tous_genres)
|
||||
```
|
||||
|
||||
### 1.3 - Recherche par criteres
|
||||
```python
|
||||
def rechercher(catalogue, type_contenu, genre, note_min):
|
||||
resultats = []
|
||||
|
||||
for c in catalogue:
|
||||
# Verifier chaque critere
|
||||
if type_contenu is not None and c["type"] != type_contenu:
|
||||
continue
|
||||
if genre is not None and genre not in c["genre"]:
|
||||
continue
|
||||
if note_min is not None and c["note"] < note_min:
|
||||
continue
|
||||
|
||||
resultats.append(c)
|
||||
|
||||
return resultats
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Exercice 2
|
||||
|
||||
### 2.1 - Temps de visionnage
|
||||
```python
|
||||
def temps_visionne(hist, cat):
|
||||
total_minutes = 0
|
||||
|
||||
for h in hist:
|
||||
# Trouver le contenu dans le catalogue
|
||||
contenu = None
|
||||
for c in cat:
|
||||
if c["titre"] == h["titre"]:
|
||||
contenu = c
|
||||
break
|
||||
|
||||
if contenu == None:
|
||||
continue
|
||||
|
||||
if contenu["type"] == "serie":
|
||||
total_minutes = total_minutes + h["episodes_vus"] * contenu["duree_moy"]
|
||||
else:
|
||||
total_minutes = total_minutes + contenu["duree"]
|
||||
|
||||
heures = total_minutes // 60
|
||||
minutes = total_minutes % 60
|
||||
return total_minutes, str(heures) + "h" + str(minutes)
|
||||
```
|
||||
|
||||
### 2.2 - Profil preferences
|
||||
- Comptez les genres ponderes par les notes utilisateur
|
||||
- Utilisez un dictionnaire `{genre: score_total}`
|
||||
- Triez par score decroissant
|
||||
|
||||
```python
|
||||
scores_genres = {}
|
||||
for h in historique:
|
||||
# Trouver le contenu
|
||||
for c in catalogue:
|
||||
if c["titre"] == h["titre"]:
|
||||
for genre in c["genre"]:
|
||||
if genre not in scores_genres:
|
||||
scores_genres[genre] = 0
|
||||
scores_genres[genre] = scores_genres[genre] + h["note"]
|
||||
break
|
||||
```
|
||||
|
||||
### 2.3 - Gestion watchlist
|
||||
```python
|
||||
def trier_watchlist(wl, cat, critere):
|
||||
# Creer une liste avec les infos completes
|
||||
avec_infos = []
|
||||
for titre in wl:
|
||||
for c in cat:
|
||||
if c["titre"] == titre:
|
||||
avec_infos.append(c)
|
||||
break
|
||||
|
||||
# Trier selon le critere
|
||||
if critere == "note":
|
||||
avec_infos = sorted(avec_infos, key=lambda x: x["note"], reverse=True)
|
||||
elif critere == "annee":
|
||||
avec_infos = sorted(avec_infos, key=lambda x: x["annee"], reverse=True)
|
||||
|
||||
# Renvoyer juste les titres
|
||||
titres = []
|
||||
for c in avec_infos:
|
||||
titres.append(c["titre"])
|
||||
return titres
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Exercice 3 (Bonus)
|
||||
|
||||
### 3.1 - Recommandations similaires
|
||||
```python
|
||||
def similarite(c1, c2):
|
||||
score = 0
|
||||
# Genres en commun
|
||||
for g in c1["genre"]:
|
||||
if g in c2["genre"]:
|
||||
score = score + 2
|
||||
# Meme type
|
||||
if c1["type"] == c2["type"]:
|
||||
score = score + 1
|
||||
# Meme decennie
|
||||
if c1["annee"] // 10 == c2["annee"] // 10:
|
||||
score = score + 1
|
||||
return score
|
||||
```
|
||||
|
||||
### 3.2 - Recommandations personnalisees
|
||||
1. Calculez le profil utilisateur (genres preferes, note moyenne)
|
||||
2. Pour chaque contenu non vu, calculez un score
|
||||
3. Triez par score decroissant
|
||||
|
||||
### 3.3 - Soiree cinema
|
||||
C'est un probleme d'optimisation (type "sac a dos") :
|
||||
```python
|
||||
def soiree_cinema(cat, duree_max, genres_voulus):
|
||||
# Filtrer les contenus valides
|
||||
valides = []
|
||||
for c in cat:
|
||||
for g in c["genre"]:
|
||||
if g in genres_voulus:
|
||||
valides.append(c)
|
||||
break
|
||||
|
||||
# Trier par note decroissante
|
||||
valides = sorted(valides, key=lambda x: x["note"], reverse=True)
|
||||
|
||||
selection = []
|
||||
duree_totale = 0
|
||||
a_serie = False
|
||||
|
||||
for c in valides:
|
||||
if c["type"] == "film":
|
||||
duree_c = c["duree"]
|
||||
else:
|
||||
duree_c = c["duree_moy"] * 3
|
||||
|
||||
if c["type"] == "serie" and a_serie:
|
||||
continue # Deja une serie
|
||||
|
||||
if duree_totale + duree_c <= duree_max:
|
||||
selection.append(c)
|
||||
duree_totale = duree_totale + duree_c
|
||||
if c["type"] == "serie":
|
||||
a_serie = True
|
||||
|
||||
return selection, duree_totale
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Pieges a eviter
|
||||
|
||||
1. **Films vs series** : les films ont `duree`, les series ont `duree_moy` et `saisons`
|
||||
2. **Genre est une liste** : utilisez `in` pour verifier si un genre est present
|
||||
3. **Contenu non trouve** : verifiez que le titre existe avant d'acceder a ses proprietes
|
||||
4. **Tri stable** : si deux elements ont le meme score, leur ordre relatif est conserve
|
||||
@@ -1,527 +0,0 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"id": "cell-0",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"# TP Évaluation - Gestion d'équipe de Football\n",
|
||||
"\n",
|
||||
"**Durée : 1h30**\n",
|
||||
"\n",
|
||||
"**Nom :** \n",
|
||||
"\n",
|
||||
"**Prénom :**\n",
|
||||
"\n",
|
||||
"---\n",
|
||||
"\n",
|
||||
"Dans ce TP, vous allez créer un système de gestion d'équipe de football.\n",
|
||||
"\n",
|
||||
"**Compétences évaluées :**\n",
|
||||
"- Manipulation de tuples et listes\n",
|
||||
"- Dictionnaires et structures imbriquées\n",
|
||||
"- Algorithmes de sélection"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"id": "cell-1",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Données initiales\n",
|
||||
"\n",
|
||||
"**Exécutez cette cellule avant de commencer.**"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "cell-2",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Effectif de l'equipe\n",
|
||||
"# Chaque joueur est un tuple : (nom, poste, note_globale, stats)\n",
|
||||
"# stats est un dictionnaire avec les caracteristiques\n",
|
||||
"\n",
|
||||
"effectif = [\n",
|
||||
" (\"Mbappe\", \"ATT\", 91, {\"vitesse\": 97, \"tir\": 89, \"passe\": 80, \"dribble\": 92, \"defense\": 36, \"physique\": 78}),\n",
|
||||
" (\"Griezmann\", \"ATT\", 87, {\"vitesse\": 80, \"tir\": 86, \"passe\": 84, \"dribble\": 88, \"defense\": 56, \"physique\": 72}),\n",
|
||||
" (\"Dembele\", \"ATT\", 86, {\"vitesse\": 93, \"tir\": 78, \"passe\": 82, \"dribble\": 90, \"defense\": 32, \"physique\": 63}),\n",
|
||||
" (\"Thuram\", \"ATT\", 84, {\"vitesse\": 86, \"tir\": 80, \"passe\": 72, \"dribble\": 82, \"defense\": 42, \"physique\": 84}),\n",
|
||||
" (\"Tchouameni\", \"MIL\", 86, {\"vitesse\": 74, \"tir\": 72, \"passe\": 80, \"dribble\": 76, \"defense\": 82, \"physique\": 86}),\n",
|
||||
" (\"Kante\", \"MIL\", 88, {\"vitesse\": 78, \"tir\": 66, \"passe\": 75, \"dribble\": 81, \"defense\": 87, \"physique\": 82}),\n",
|
||||
" (\"Rabiot\", \"MIL\", 82, {\"vitesse\": 72, \"tir\": 75, \"passe\": 79, \"dribble\": 80, \"defense\": 76, \"physique\": 80}),\n",
|
||||
" (\"Camavinga\", \"MIL\", 83, {\"vitesse\": 82, \"tir\": 64, \"passe\": 78, \"dribble\": 82, \"defense\": 76, \"physique\": 78}),\n",
|
||||
" (\"Hernandez\", \"DEF\", 85, {\"vitesse\": 84, \"tir\": 65, \"passe\": 76, \"dribble\": 78, \"defense\": 82, \"physique\": 82}),\n",
|
||||
" (\"Upamecano\", \"DEF\", 84, {\"vitesse\": 80, \"tir\": 48, \"passe\": 62, \"dribble\": 58, \"defense\": 86, \"physique\": 88}),\n",
|
||||
" (\"Konate\", \"DEF\", 84, {\"vitesse\": 78, \"tir\": 42, \"passe\": 56, \"dribble\": 52, \"defense\": 87, \"physique\": 86}),\n",
|
||||
" (\"Saliba\", \"DEF\", 86, {\"vitesse\": 76, \"tir\": 38, \"passe\": 65, \"dribble\": 60, \"defense\": 88, \"physique\": 84}),\n",
|
||||
" (\"Maignan\", \"GK\", 87, {\"plongeon\": 88, \"reflexes\": 89, \"placement\": 84, \"jeu_pied\": 78}),\n",
|
||||
" (\"Lloris\", \"GK\", 85, {\"plongeon\": 86, \"reflexes\": 87, \"placement\": 86, \"jeu_pied\": 72})\n",
|
||||
"]\n",
|
||||
"\n",
|
||||
"# Formation 4-3-3 : nombre de joueurs par poste\n",
|
||||
"formation = {\n",
|
||||
" \"GK\": 1, # Gardien\n",
|
||||
" \"DEF\": 4, # Defenseurs\n",
|
||||
" \"MIL\": 3, # Milieux\n",
|
||||
" \"ATT\": 3 # Attaquants\n",
|
||||
"}\n",
|
||||
"\n",
|
||||
"# Historique des matchs : (adversaire, buts_pour, buts_contre, buteurs)\n",
|
||||
"matchs = [\n",
|
||||
" (\"Allemagne\", 2, 1, [\"Mbappe\", \"Griezmann\"]),\n",
|
||||
" (\"Belgique\", 3, 0, [\"Mbappe\", \"Mbappe\", \"Dembele\"]),\n",
|
||||
" (\"Espagne\", 1, 2, [\"Thuram\"]),\n",
|
||||
" (\"Italie\", 2, 2, [\"Griezmann\", \"Mbappe\"]),\n",
|
||||
" (\"Portugal\", 0, 1, []),\n",
|
||||
" (\"Angleterre\", 3, 1, [\"Mbappe\", \"Griezmann\", \"Dembele\"])\n",
|
||||
"]"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"id": "cell-3",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"---\n",
|
||||
"\n",
|
||||
"## Exercice 1 - Gestion de l'effectif (25 min)\n",
|
||||
"\n",
|
||||
"### 1.1 Affichage des joueurs (4 pts)\n",
|
||||
"\n",
|
||||
"Écrivez une fonction `afficher_joueur(joueur)` qui affiche un joueur de manière formatée.\n",
|
||||
"\n",
|
||||
"Exemple pour un joueur de champ :\n",
|
||||
"```\n",
|
||||
"Mbappe (ATT) - Note: 91\n",
|
||||
" VIT:97 | TIR:89 | PAS:80 | DRI:92\n",
|
||||
"```\n",
|
||||
"\n",
|
||||
"Pour les gardiens (poste \"GK\"), afficher leurs stats spécifiques (plongeon, reflexes, etc.)."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "cell-4",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"def afficher_joueur(joueur):\n",
|
||||
" # Extraire les infos du tuple\n",
|
||||
" nom = joueur[0]\n",
|
||||
" poste = joueur[1]\n",
|
||||
" note = joueur[2]\n",
|
||||
" stats = joueur[3]\n",
|
||||
" \n",
|
||||
" print(nom, \"(\" + poste + \") - Note:\", note)\n",
|
||||
" \n",
|
||||
" if poste == \"GK\":\n",
|
||||
" # Afficher stats gardien\n",
|
||||
" # Votre code ici\n",
|
||||
" pass\n",
|
||||
" else:\n",
|
||||
" # Afficher stats joueur de champ\n",
|
||||
" # Votre code ici\n",
|
||||
" pass\n",
|
||||
"\n",
|
||||
"# Tests\n",
|
||||
"afficher_joueur(effectif[0]) # Joueur de champ\n",
|
||||
"print()\n",
|
||||
"afficher_joueur(effectif[12]) # Gardien"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"id": "cell-5",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"### 1.2 Filtrage par poste (4 pts)\n",
|
||||
"\n",
|
||||
"Écrivez une fonction `joueurs_par_poste(effectif, poste)` qui renvoie la liste des joueurs d'un poste donné, triés par note décroissante."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "cell-6",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"def joueurs_par_poste(effectif, poste):\n",
|
||||
" joueurs = []\n",
|
||||
" \n",
|
||||
" for joueur in effectif:\n",
|
||||
" if joueur[1] == poste:\n",
|
||||
" joueurs.append(joueur)\n",
|
||||
" \n",
|
||||
" # Trier par note (indice 2) decroissante\n",
|
||||
" joueurs = sorted(joueurs, key=lambda j: j[2], reverse=True)\n",
|
||||
" return joueurs\n",
|
||||
"\n",
|
||||
"# Test\n",
|
||||
"print(\"Attaquants :\")\n",
|
||||
"for j in joueurs_par_poste(effectif, \"ATT\"):\n",
|
||||
" print(\" \", j[0], \"-\", j[2])"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"id": "cell-7",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"### 1.3 Meilleur dans une stat (4 pts)\n",
|
||||
"\n",
|
||||
"Écrivez une fonction `meilleur_stat(effectif, stat)` qui renvoie le tuple `(nom_joueur, valeur)` du joueur ayant la meilleure valeur pour cette statistique.\n",
|
||||
"\n",
|
||||
"*Attention : les gardiens n'ont pas les mêmes stats que les joueurs de champ.*"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "cell-8",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"def meilleur_stat(effectif, stat):\n",
|
||||
" meilleur_nom = None\n",
|
||||
" meilleure_valeur = -1\n",
|
||||
" \n",
|
||||
" for joueur in effectif:\n",
|
||||
" nom = joueur[0]\n",
|
||||
" stats = joueur[3]\n",
|
||||
" \n",
|
||||
" # Verifier si le joueur a cette stat\n",
|
||||
" if stat in stats:\n",
|
||||
" valeur = stats[stat]\n",
|
||||
" # Votre code ici\n",
|
||||
" pass\n",
|
||||
" \n",
|
||||
" return (meilleur_nom, meilleure_valeur)\n",
|
||||
"\n",
|
||||
"# Tests\n",
|
||||
"print(\"Plus rapide :\", meilleur_stat(effectif, \"vitesse\"))\n",
|
||||
"print(\"Meilleur tireur :\", meilleur_stat(effectif, \"tir\"))\n",
|
||||
"print(\"Meilleurs reflexes :\", meilleur_stat(effectif, \"reflexes\"))"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"id": "cell-9",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"---\n",
|
||||
"\n",
|
||||
"## Exercice 2 - Composition d'équipe (35 min)\n",
|
||||
"\n",
|
||||
"### 2.1 Générer le XI de départ (6 pts)\n",
|
||||
"\n",
|
||||
"Écrivez une fonction `generer_xi(effectif, formation)` qui génère automatiquement le meilleur XI possible.\n",
|
||||
"\n",
|
||||
"Pour chaque poste, sélectionner les meilleurs joueurs (par note globale) en respectant le nombre requis.\n",
|
||||
"\n",
|
||||
"Renvoie un dictionnaire `{poste: [liste des joueurs sélectionnés]}`"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "cell-10",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"def generer_xi(effectif, formation):\n",
|
||||
" xi = {}\n",
|
||||
" \n",
|
||||
" for poste, nb_joueurs in formation.items():\n",
|
||||
" # Recuperer les joueurs de ce poste, tries par note\n",
|
||||
" candidats = joueurs_par_poste(effectif, poste)\n",
|
||||
" \n",
|
||||
" # Prendre les n meilleurs\n",
|
||||
" # Votre code ici\n",
|
||||
" pass\n",
|
||||
" \n",
|
||||
" return xi\n",
|
||||
"\n",
|
||||
"# Test\n",
|
||||
"xi = generer_xi(effectif, formation)\n",
|
||||
"print(\"=== XI de depart ===\")\n",
|
||||
"for poste, joueurs in xi.items():\n",
|
||||
" print(poste + \":\")\n",
|
||||
" for j in joueurs:\n",
|
||||
" print(\" -\", j[0], \"(\", j[2], \")\")"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"id": "cell-11",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"### 2.2 Note moyenne du XI (5 pts)\n",
|
||||
"\n",
|
||||
"Écrivez une fonction `note_equipe(xi)` qui calcule la note moyenne de l'équipe sélectionnée."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "cell-12",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"def note_equipe(xi):\n",
|
||||
" total_notes = 0\n",
|
||||
" nb_joueurs = 0\n",
|
||||
" \n",
|
||||
" for poste, joueurs in xi.items():\n",
|
||||
" for joueur in joueurs:\n",
|
||||
" # Votre code ici\n",
|
||||
" pass\n",
|
||||
" \n",
|
||||
" if nb_joueurs == 0:\n",
|
||||
" return 0\n",
|
||||
" \n",
|
||||
" return round(total_notes / nb_joueurs, 1)\n",
|
||||
"\n",
|
||||
"# Test\n",
|
||||
"print(\"Note de l'equipe :\", note_equipe(xi))"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"id": "cell-13",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"### 2.3 Statistiques des matchs (6 pts)\n",
|
||||
"\n",
|
||||
"Écrivez une fonction `stats_matchs(matchs)` qui renvoie un dictionnaire avec :\n",
|
||||
"- `\"victoires\"` : nombre de victoires\n",
|
||||
"- `\"nuls\"` : nombre de matchs nuls\n",
|
||||
"- `\"defaites\"` : nombre de défaites\n",
|
||||
"- `\"buts_pour\"` : total des buts marqués\n",
|
||||
"- `\"buts_contre\"` : total des buts encaissés"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "cell-14",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"def stats_matchs(matchs):\n",
|
||||
" victoires = 0\n",
|
||||
" nuls = 0\n",
|
||||
" defaites = 0\n",
|
||||
" buts_pour = 0\n",
|
||||
" buts_contre = 0\n",
|
||||
" \n",
|
||||
" for match in matchs:\n",
|
||||
" adversaire = match[0]\n",
|
||||
" bp = match[1] # buts pour\n",
|
||||
" bc = match[2] # buts contre\n",
|
||||
" \n",
|
||||
" buts_pour = buts_pour + bp\n",
|
||||
" buts_contre = buts_contre + bc\n",
|
||||
" \n",
|
||||
" if bp > bc:\n",
|
||||
" victoires = victoires + 1\n",
|
||||
" elif bp == bc:\n",
|
||||
" nuls = nuls + 1\n",
|
||||
" else:\n",
|
||||
" # Votre code ici\n",
|
||||
" pass\n",
|
||||
" \n",
|
||||
" return {\n",
|
||||
" \"victoires\": victoires,\n",
|
||||
" \"nuls\": nuls,\n",
|
||||
" \"defaites\": defaites,\n",
|
||||
" \"buts_pour\": buts_pour,\n",
|
||||
" \"buts_contre\": buts_contre\n",
|
||||
" }\n",
|
||||
"\n",
|
||||
"# Test\n",
|
||||
"stats = stats_matchs(matchs)\n",
|
||||
"print(\"Bilan :\", stats[\"victoires\"], \"V\", stats[\"nuls\"], \"N\", stats[\"defaites\"], \"D\")\n",
|
||||
"print(\"Buts :\", stats[\"buts_pour\"], \"-\", stats[\"buts_contre\"])"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"id": "cell-15",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"### 2.4 Classement des buteurs (6 pts)\n",
|
||||
"\n",
|
||||
"Écrivez une fonction `classement_buteurs(matchs)` qui renvoie une liste de tuples `(joueur, nb_buts)` triée par nombre de buts décroissant."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "cell-16",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"def classement_buteurs(matchs):\n",
|
||||
" # Dictionnaire pour compter les buts par joueur\n",
|
||||
" buts_par_joueur = {}\n",
|
||||
" \n",
|
||||
" for match in matchs:\n",
|
||||
" buteurs = match[3] # liste des buteurs\n",
|
||||
" for buteur in buteurs:\n",
|
||||
" if buteur not in buts_par_joueur:\n",
|
||||
" buts_par_joueur[buteur] = 0\n",
|
||||
" buts_par_joueur[buteur] = buts_par_joueur[buteur] + 1\n",
|
||||
" \n",
|
||||
" # Convertir en liste de tuples et trier\n",
|
||||
" classement = []\n",
|
||||
" for joueur, buts in buts_par_joueur.items():\n",
|
||||
" classement.append((joueur, buts))\n",
|
||||
" \n",
|
||||
" classement = sorted(classement, key=lambda x: x[1], reverse=True)\n",
|
||||
" return classement\n",
|
||||
"\n",
|
||||
"# Test\n",
|
||||
"print(\"Classement des buteurs :\")\n",
|
||||
"for i, (joueur, buts) in enumerate(classement_buteurs(matchs), 1):\n",
|
||||
" print(\" \", i, \".\", joueur, \":\", buts, \"but(s)\")"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"id": "cell-17",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"---\n",
|
||||
"\n",
|
||||
"## Exercice 3 - Bonus (20 min)\n",
|
||||
"\n",
|
||||
"### 3.1 Points forts et faibles (5 pts)\n",
|
||||
"\n",
|
||||
"Écrivez une fonction `analyser_joueur(joueur)` qui renvoie un dictionnaire avec :\n",
|
||||
"- `\"points_forts\"` : liste des stats >= 85\n",
|
||||
"- `\"points_faibles\"` : liste des stats <= 60"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "cell-18",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"def analyser_joueur(joueur):\n",
|
||||
" stats = joueur[3]\n",
|
||||
" points_forts = []\n",
|
||||
" points_faibles = []\n",
|
||||
" \n",
|
||||
" for stat, valeur in stats.items():\n",
|
||||
" if valeur >= 85:\n",
|
||||
" points_forts.append(stat)\n",
|
||||
" # Votre code ici pour les points faibles\n",
|
||||
" pass\n",
|
||||
" \n",
|
||||
" return {\n",
|
||||
" \"points_forts\": points_forts,\n",
|
||||
" \"points_faibles\": points_faibles\n",
|
||||
" }\n",
|
||||
"\n",
|
||||
"# Test\n",
|
||||
"analyse = analyser_joueur(effectif[0]) # Mbappe\n",
|
||||
"print(\"Analyse de Mbappe :\")\n",
|
||||
"print(\" Points forts :\", analyse[\"points_forts\"])\n",
|
||||
"print(\" Points faibles :\", analyse[\"points_faibles\"])"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"id": "cell-19",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"### 3.2 Rechercher un joueur (4 pts)\n",
|
||||
"\n",
|
||||
"Écrivez une fonction `rechercher_joueur(effectif, nom)` qui renvoie le joueur correspondant au nom (ou None si non trouvé)."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "cell-20",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"def rechercher_joueur(effectif, nom):\n",
|
||||
" for joueur in effectif:\n",
|
||||
" if joueur[0] == nom:\n",
|
||||
" return joueur\n",
|
||||
" return None\n",
|
||||
"\n",
|
||||
"# Test\n",
|
||||
"joueur = rechercher_joueur(effectif, \"Kante\")\n",
|
||||
"if joueur:\n",
|
||||
" afficher_joueur(joueur)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"id": "cell-21",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"### 3.3 Performance d'un joueur (5 pts)\n",
|
||||
"\n",
|
||||
"Écrivez une fonction `performance_buteur(nom, matchs)` qui renvoie le nombre de buts et la moyenne de buts par match pour un joueur donné."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "cell-22",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"def performance_buteur(nom, matchs):\n",
|
||||
" nb_buts = 0\n",
|
||||
" nb_matchs = len(matchs)\n",
|
||||
" \n",
|
||||
" for match in matchs:\n",
|
||||
" buteurs = match[3]\n",
|
||||
" for buteur in buteurs:\n",
|
||||
" if buteur == nom:\n",
|
||||
" nb_buts = nb_buts + 1\n",
|
||||
" \n",
|
||||
" moyenne = 0\n",
|
||||
" if nb_matchs > 0:\n",
|
||||
" moyenne = round(nb_buts / nb_matchs, 2)\n",
|
||||
" \n",
|
||||
" return {\n",
|
||||
" \"buts\": nb_buts,\n",
|
||||
" \"matchs\": nb_matchs,\n",
|
||||
" \"moyenne\": moyenne\n",
|
||||
" }\n",
|
||||
"\n",
|
||||
"# Test\n",
|
||||
"perf = performance_buteur(\"Mbappe\", matchs)\n",
|
||||
"print(\"Performance de Mbappe :\")\n",
|
||||
"print(\" Buts :\", perf[\"buts\"])\n",
|
||||
"print(\" Moyenne par match :\", perf[\"moyenne\"])"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"kernelspec": {
|
||||
"display_name": "Python 3",
|
||||
"language": "python",
|
||||
"name": "python3"
|
||||
},
|
||||
"language_info": {
|
||||
"name": "python",
|
||||
"version": "3.9.0"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 5
|
||||
}
|
||||
@@ -1,201 +0,0 @@
|
||||
# Aide - TP05 Football
|
||||
|
||||
## Rappels utiles
|
||||
|
||||
### Structure des tuples
|
||||
```python
|
||||
# Joueur = (nom, poste, note_globale, stats)
|
||||
joueur = effectif[0]
|
||||
nom = joueur[0] # "Mbappe"
|
||||
poste = joueur[1] # "ATT"
|
||||
note = joueur[2] # 91
|
||||
stats = joueur[3] # {"vitesse": 97, "tir": 89, ...}
|
||||
|
||||
# Acces direct
|
||||
vitesse = joueur[3]["vitesse"]
|
||||
```
|
||||
|
||||
### Parcourir une liste de tuples
|
||||
```python
|
||||
for joueur in effectif:
|
||||
nom = joueur[0]
|
||||
poste = joueur[1]
|
||||
note = joueur[2]
|
||||
stats = joueur[3]
|
||||
print(nom, "-", poste, "- Note:", note)
|
||||
```
|
||||
|
||||
### Filtrer une liste de tuples
|
||||
```python
|
||||
attaquants = []
|
||||
for j in effectif:
|
||||
if j[1] == "ATT":
|
||||
attaquants.append(j)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Exercice 1
|
||||
|
||||
### 1.1 - Affichage joueur
|
||||
- Verifiez si c'est un gardien (`poste == "GK"`) car les stats sont differentes
|
||||
|
||||
```python
|
||||
def afficher_joueur(joueur):
|
||||
nom = joueur[0]
|
||||
poste = joueur[1]
|
||||
note = joueur[2]
|
||||
stats = joueur[3]
|
||||
|
||||
print(nom, "(", poste, ") - Note:", note)
|
||||
|
||||
if poste == "GK":
|
||||
print(" Plongeon:", stats["plongeon"])
|
||||
print(" Reflexes:", stats["reflexes"])
|
||||
else:
|
||||
print(" Vitesse:", stats["vitesse"])
|
||||
print(" Tir:", stats["tir"])
|
||||
```
|
||||
|
||||
### 1.2 - Filtrage par poste
|
||||
```python
|
||||
def joueurs_par_poste(eff, poste):
|
||||
filtre = []
|
||||
for j in eff:
|
||||
if j[1] == poste:
|
||||
filtre.append(j)
|
||||
# Trier par note (indice 2) decroissante
|
||||
filtre = sorted(filtre, key=lambda j: j[2], reverse=True)
|
||||
return filtre
|
||||
```
|
||||
|
||||
### 1.3 - Meilleur dans une stat
|
||||
```python
|
||||
def meilleur_stat(eff, stat):
|
||||
meilleur = None
|
||||
max_val = -1
|
||||
|
||||
for joueur in eff:
|
||||
nom = joueur[0]
|
||||
stats = joueur[3]
|
||||
if stat in stats and stats[stat] > max_val:
|
||||
max_val = stats[stat]
|
||||
meilleur = nom
|
||||
|
||||
return (meilleur, max_val)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Exercice 2
|
||||
|
||||
### 2.1 - Generer le XI
|
||||
```python
|
||||
def generer_xi(eff, formation):
|
||||
xi = {}
|
||||
for poste, nb_joueurs in formation.items():
|
||||
# Recuperer les joueurs de ce poste, tries par note
|
||||
candidats = joueurs_par_poste(eff, poste)
|
||||
# Prendre les n meilleurs
|
||||
xi[poste] = candidats[:nb_joueurs]
|
||||
return xi
|
||||
```
|
||||
|
||||
### 2.2 - Note moyenne ponderee
|
||||
```python
|
||||
def note_equipe(xi):
|
||||
poids = {"ATT": 1.2, "MIL": 1.1, "DEF": 1.0, "GK": 0.9}
|
||||
total_pondere = 0
|
||||
total_poids = 0
|
||||
|
||||
for poste, joueurs in xi.items():
|
||||
for j in joueurs:
|
||||
note = j[2]
|
||||
p = poids[poste]
|
||||
total_pondere = total_pondere + note * p
|
||||
total_poids = total_poids + p
|
||||
|
||||
return total_pondere / total_poids
|
||||
```
|
||||
|
||||
### 2.3 - Equipe specialisee
|
||||
```python
|
||||
def score_priorite(joueur, priorite):
|
||||
stats = joueur[3]
|
||||
if priorite == "offensive":
|
||||
return stats.get("tir", 0) + stats.get("dribble", 0)
|
||||
elif priorite == "defensive":
|
||||
return stats.get("defense", 0) + stats.get("physique", 0)
|
||||
elif priorite == "technique":
|
||||
return stats.get("passe", 0) + stats.get("dribble", 0)
|
||||
return 0
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Exercice 3 (Bonus)
|
||||
|
||||
### 3.1 - Statistiques des matchs
|
||||
```python
|
||||
def stats_matchs(matchs):
|
||||
victoires = 0
|
||||
nuls = 0
|
||||
defaites = 0
|
||||
buts_pour = 0
|
||||
buts_contre = 0
|
||||
|
||||
for match in matchs:
|
||||
adversaire = match[0]
|
||||
score_eq = match[1]
|
||||
score_adv = match[2]
|
||||
buteurs = match[3]
|
||||
|
||||
buts_pour = buts_pour + score_eq
|
||||
buts_contre = buts_contre + score_adv
|
||||
|
||||
if score_eq > score_adv:
|
||||
victoires = victoires + 1
|
||||
elif score_eq == score_adv:
|
||||
nuls = nuls + 1
|
||||
else:
|
||||
defaites = defaites + 1
|
||||
|
||||
return {
|
||||
"victoires": victoires,
|
||||
"nuls": nuls,
|
||||
"defaites": defaites,
|
||||
"buts_pour": buts_pour,
|
||||
"buts_contre": buts_contre,
|
||||
"difference": buts_pour - buts_contre,
|
||||
"points": victoires * 3 + nuls
|
||||
}
|
||||
```
|
||||
|
||||
### 3.2 - Classement buteurs
|
||||
```python
|
||||
def classement_buteurs(matchs):
|
||||
compteur = {}
|
||||
for match in matchs:
|
||||
buteurs = match[3]
|
||||
for buteur in buteurs:
|
||||
if buteur not in compteur:
|
||||
compteur[buteur] = 0
|
||||
compteur[buteur] = compteur[buteur] + 1
|
||||
|
||||
# sorted renvoie une liste de tuples triee
|
||||
return sorted(compteur.items(), key=lambda x: x[1], reverse=True)
|
||||
```
|
||||
|
||||
### 3.3 - Performance joueur
|
||||
- Trouvez le joueur dans l'effectif pour ses stats
|
||||
- Comptez ses buts dans les matchs
|
||||
- Identifiez ses points forts (>= 85) et faibles (<= 60)
|
||||
|
||||
---
|
||||
|
||||
## Pieges a eviter
|
||||
|
||||
1. **Gardiens differents** : les GK n'ont pas les memes stats (pas de "vitesse", mais "plongeon", "reflexes"...)
|
||||
2. **Tuples immutables** : vous ne pouvez pas modifier un tuple, creez-en un nouveau si besoin
|
||||
3. **Division par zero** : verifiez que le diviseur est > 0
|
||||
4. **Acces par indice** : joueur[0] = nom, joueur[1] = poste, joueur[2] = note, joueur[3] = stats
|
||||
@@ -1,471 +0,0 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"# TP Évaluation - Pokédex\n",
|
||||
"\n",
|
||||
"**Durée : 1h30**\n",
|
||||
"\n",
|
||||
"**Nom :** \n",
|
||||
"\n",
|
||||
"**Prénom :**\n",
|
||||
"\n",
|
||||
"---\n",
|
||||
"\n",
|
||||
"Dans ce TP, vous allez créer un système de gestion de Pokédex.\n",
|
||||
"\n",
|
||||
"**Compétences évaluées :**\n",
|
||||
"- Manipulation de tuples et listes\n",
|
||||
"- Dictionnaires et structures imbriquées\n",
|
||||
"- Algorithmes de filtrage et tri"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Données initiales\n",
|
||||
"\n",
|
||||
"**Exécutez cette cellule avant de commencer.**"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Pokedex (liste de tuples)\n",
|
||||
"# Chaque Pokemon : (nom, types, pv, attaque, defense, vitesse, evolution)\n",
|
||||
"# types est un tuple de 1 ou 2 types\n",
|
||||
"# evolution est None si pas d'evolution\n",
|
||||
"\n",
|
||||
"pokedex = [\n",
|
||||
" (\"Bulbizarre\", (\"Plante\", \"Poison\"), 45, 49, 49, 45, \"Herbizarre\"),\n",
|
||||
" (\"Herbizarre\", (\"Plante\", \"Poison\"), 60, 62, 63, 60, \"Florizarre\"),\n",
|
||||
" (\"Florizarre\", (\"Plante\", \"Poison\"), 80, 82, 83, 80, None),\n",
|
||||
" (\"Salameche\", (\"Feu\",), 39, 52, 43, 65, \"Reptincel\"),\n",
|
||||
" (\"Reptincel\", (\"Feu\",), 58, 64, 58, 80, \"Dracaufeu\"),\n",
|
||||
" (\"Dracaufeu\", (\"Feu\", \"Vol\"), 78, 84, 78, 100, None),\n",
|
||||
" (\"Carapuce\", (\"Eau\",), 44, 48, 65, 43, \"Carabaffe\"),\n",
|
||||
" (\"Carabaffe\", (\"Eau\",), 59, 63, 80, 58, \"Tortank\"),\n",
|
||||
" (\"Tortank\", (\"Eau\",), 79, 83, 100, 78, None),\n",
|
||||
" (\"Pikachu\", (\"Electrique\",), 35, 55, 40, 90, \"Raichu\"),\n",
|
||||
" (\"Raichu\", (\"Electrique\",), 60, 90, 55, 110, None),\n",
|
||||
" (\"Evoli\", (\"Normal\",), 55, 55, 50, 55, \"Multiple\"),\n",
|
||||
" (\"Aquali\", (\"Eau\",), 130, 65, 60, 65, None),\n",
|
||||
" (\"Voltali\", (\"Electrique\",), 65, 65, 60, 130, None),\n",
|
||||
" (\"Pyroli\", (\"Feu\",), 65, 130, 60, 65, None),\n",
|
||||
" (\"Mewtwo\", (\"Psy\",), 106, 110, 90, 130, None),\n",
|
||||
" (\"Mew\", (\"Psy\",), 100, 100, 100, 100, None),\n",
|
||||
" (\"Dracolosse\", (\"Dragon\", \"Vol\"), 91, 134, 95, 80, None),\n",
|
||||
" (\"Leviator\", (\"Eau\", \"Vol\"), 95, 125, 79, 81, None),\n",
|
||||
" (\"Lokhlass\", (\"Eau\", \"Glace\"), 130, 85, 80, 60, None)\n",
|
||||
"]\n",
|
||||
"\n",
|
||||
"# Table des faiblesses (type_attaquant -> liste des types faibles)\n",
|
||||
"faiblesses = {\n",
|
||||
" \"Feu\": [\"Plante\", \"Glace\"],\n",
|
||||
" \"Eau\": [\"Feu\", \"Sol\"],\n",
|
||||
" \"Plante\": [\"Eau\", \"Sol\"],\n",
|
||||
" \"Electrique\": [\"Eau\", \"Vol\"],\n",
|
||||
" \"Glace\": [\"Dragon\", \"Vol\", \"Plante\"],\n",
|
||||
" \"Psy\": [\"Poison\"],\n",
|
||||
" \"Dragon\": [\"Dragon\"],\n",
|
||||
" \"Vol\": [\"Plante\"]\n",
|
||||
"}\n",
|
||||
"\n",
|
||||
"# Equipe du joueur (liste de noms)\n",
|
||||
"mon_equipe = [\"Pikachu\", \"Dracaufeu\", \"Tortank\", \"Dracolosse\", \"Mewtwo\", \"Evoli\"]"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"---\n",
|
||||
"\n",
|
||||
"## Exercice 1 - Exploration du Pokédex (25 min)\n",
|
||||
"\n",
|
||||
"### 1.1 Affichage d'un Pokémon (4 pts)\n",
|
||||
"\n",
|
||||
"Écrivez une fonction `afficher_pokemon(pokemon)` qui affiche les infos d'un Pokémon.\n",
|
||||
"\n",
|
||||
"Exemple :\n",
|
||||
"```\n",
|
||||
"DRACAUFEU (Feu/Vol)\n",
|
||||
"PV: 78 | ATK: 84 | DEF: 78 | VIT: 100\n",
|
||||
"Evolution: Forme finale\n",
|
||||
"```\n",
|
||||
"\n",
|
||||
"*Rappel : pokemon[0] = nom, pokemon[1] = types, pokemon[2] = pv, pokemon[3] = attaque, pokemon[4] = defense, pokemon[5] = vitesse, pokemon[6] = evolution*"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"def afficher_pokemon(pokemon):\n",
|
||||
" nom = pokemon[0]\n",
|
||||
" types = pokemon[1]\n",
|
||||
" pv = pokemon[2]\n",
|
||||
" attaque = pokemon[3]\n",
|
||||
" defense = pokemon[4]\n",
|
||||
" vitesse = pokemon[5]\n",
|
||||
" evolution = pokemon[6]\n",
|
||||
" \n",
|
||||
" # Afficher le nom et les types\n",
|
||||
" # Votre code ici\n",
|
||||
" pass\n",
|
||||
" \n",
|
||||
" # Afficher les stats\n",
|
||||
" # Votre code ici\n",
|
||||
" pass\n",
|
||||
" \n",
|
||||
" # Afficher l'evolution (\"Forme finale\" si None)\n",
|
||||
" # Votre code ici\n",
|
||||
" pass\n",
|
||||
"\n",
|
||||
"# Test\n",
|
||||
"afficher_pokemon(pokedex[5]) # Dracaufeu"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"### 1.2 Recherche par type (4 pts)\n",
|
||||
"\n",
|
||||
"Écrivez une fonction `pokemon_par_type(dex, type_recherche)` qui renvoie tous les Pokémon ayant ce type (principal ou secondaire), triés par PV décroissants.\n",
|
||||
"\n",
|
||||
"*Aide : utilisez `sorted(liste, key=lambda p: p[2], reverse=True)` pour trier par PV*"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"def pokemon_par_type(dex, type_recherche):\n",
|
||||
" resultats = []\n",
|
||||
" \n",
|
||||
" for pokemon in dex:\n",
|
||||
" types = pokemon[1]\n",
|
||||
" # Verifier si le type recherche est dans les types du pokemon\n",
|
||||
" # Votre code ici\n",
|
||||
" pass\n",
|
||||
" \n",
|
||||
" # Trier par PV (indice 2) decroissants\n",
|
||||
" # Votre code ici\n",
|
||||
" pass\n",
|
||||
" \n",
|
||||
" return resultats\n",
|
||||
"\n",
|
||||
"# Test\n",
|
||||
"print(\"Pokemon de type Eau :\")\n",
|
||||
"for p in pokemon_par_type(pokedex, \"Eau\"):\n",
|
||||
" print(\" \", p[0], \"-\", p[2], \"PV\")"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"### 1.3 Compter les types (4 pts)\n",
|
||||
"\n",
|
||||
"Écrivez une fonction `compter_types(dex)` qui renvoie un dictionnaire `{type: nombre}` comptant combien de Pokémon ont chaque type."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"def compter_types(dex):\n",
|
||||
" compteur = {}\n",
|
||||
" \n",
|
||||
" for pokemon in dex:\n",
|
||||
" types = pokemon[1]\n",
|
||||
" for t in types:\n",
|
||||
" # Ajouter le type au compteur\n",
|
||||
" # Votre code ici\n",
|
||||
" pass\n",
|
||||
" \n",
|
||||
" return compteur\n",
|
||||
"\n",
|
||||
"# Test\n",
|
||||
"print(\"Nombre de Pokemon par type :\")\n",
|
||||
"types_compteur = compter_types(pokedex)\n",
|
||||
"for t, nb in types_compteur.items():\n",
|
||||
" print(\" \", t, \":\", nb)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"---\n",
|
||||
"\n",
|
||||
"## Exercice 2 - Gestion d'équipe (35 min)\n",
|
||||
"\n",
|
||||
"### 2.1 Charger une équipe (5 pts)\n",
|
||||
"\n",
|
||||
"Écrivez une fonction `charger_equipe(noms, dex)` qui renvoie la liste des tuples Pokemon correspondant aux noms donnés.\n",
|
||||
"\n",
|
||||
"Si un nom n'existe pas dans le Pokédex, l'ignorer."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"def charger_equipe(noms, dex):\n",
|
||||
" equipe = []\n",
|
||||
" \n",
|
||||
" for nom_recherche in noms:\n",
|
||||
" # Chercher le pokemon dans le pokedex\n",
|
||||
" for pokemon in dex:\n",
|
||||
" # Votre code ici\n",
|
||||
" pass\n",
|
||||
" \n",
|
||||
" return equipe\n",
|
||||
"\n",
|
||||
"# Test\n",
|
||||
"equipe = charger_equipe(mon_equipe, pokedex)\n",
|
||||
"print(\"Equipe chargee :\")\n",
|
||||
"for p in equipe:\n",
|
||||
" print(\" \", p[0])"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"### 2.2 Force totale de l'équipe (5 pts)\n",
|
||||
"\n",
|
||||
"Écrivez une fonction `force_equipe(equipe)` qui calcule la force totale de l'équipe.\n",
|
||||
"\n",
|
||||
"Force d'un Pokémon = PV + Attaque + Défense + Vitesse"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"def force_equipe(equipe):\n",
|
||||
" force_totale = 0\n",
|
||||
" \n",
|
||||
" for pokemon in equipe:\n",
|
||||
" # Calculer la force du pokemon et l'ajouter au total\n",
|
||||
" # Votre code ici\n",
|
||||
" pass\n",
|
||||
" \n",
|
||||
" return force_totale\n",
|
||||
"\n",
|
||||
"# Test\n",
|
||||
"print(\"Force totale de l'equipe :\", force_equipe(equipe))"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"### 2.3 Pokémon le plus fort (5 pts)\n",
|
||||
"\n",
|
||||
"Écrivez une fonction `plus_fort(equipe)` qui renvoie le Pokémon ayant la meilleure attaque."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"def plus_fort(equipe):\n",
|
||||
" if len(equipe) == 0:\n",
|
||||
" return None\n",
|
||||
" \n",
|
||||
" meilleur = equipe[0]\n",
|
||||
" meilleure_attaque = equipe[0][3]\n",
|
||||
" \n",
|
||||
" for pokemon in equipe:\n",
|
||||
" # Comparer l'attaque avec la meilleure\n",
|
||||
" # Votre code ici\n",
|
||||
" pass\n",
|
||||
" \n",
|
||||
" return meilleur\n",
|
||||
"\n",
|
||||
"# Test\n",
|
||||
"fort = plus_fort(equipe)\n",
|
||||
"if fort:\n",
|
||||
" print(\"Pokemon le plus fort :\", fort[0], \"avec\", fort[3], \"d'attaque\")"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"### 2.4 Types couverts par l'équipe (6 pts)\n",
|
||||
"\n",
|
||||
"Écrivez une fonction `types_couverts(equipe)` qui renvoie la liste (sans doublons) de tous les types présents dans l'équipe."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"def types_couverts(equipe):\n",
|
||||
" types_liste = []\n",
|
||||
" \n",
|
||||
" for pokemon in equipe:\n",
|
||||
" types = pokemon[1]\n",
|
||||
" for t in types:\n",
|
||||
" # Ajouter le type s'il n'est pas deja dans la liste\n",
|
||||
" # Votre code ici\n",
|
||||
" pass\n",
|
||||
" \n",
|
||||
" return types_liste\n",
|
||||
"\n",
|
||||
"# Test\n",
|
||||
"print(\"Types couverts par l'equipe :\", types_couverts(equipe))"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"---\n",
|
||||
"\n",
|
||||
"## Exercice 3 - Bonus (20 min)\n",
|
||||
"\n",
|
||||
"### 3.1 Chaîne d'évolution (5 pts)\n",
|
||||
"\n",
|
||||
"Écrivez une fonction `chaine_evolution(nom, dex)` qui renvoie la chaîne d'évolution complète d'un Pokémon.\n",
|
||||
"\n",
|
||||
"Exemple : `chaine_evolution(\"Bulbizarre\", pokedex)` → `[\"Bulbizarre\", \"Herbizarre\", \"Florizarre\"]`"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"def chaine_evolution(nom, dex):\n",
|
||||
" chaine = [nom]\n",
|
||||
" \n",
|
||||
" # Chercher le pokemon actuel\n",
|
||||
" pokemon_actuel = None\n",
|
||||
" for p in dex:\n",
|
||||
" if p[0] == nom:\n",
|
||||
" pokemon_actuel = p\n",
|
||||
" break\n",
|
||||
" \n",
|
||||
" if pokemon_actuel == None:\n",
|
||||
" return chaine\n",
|
||||
" \n",
|
||||
" # Suivre les evolutions\n",
|
||||
" # Votre code ici\n",
|
||||
" pass\n",
|
||||
" \n",
|
||||
" return chaine\n",
|
||||
"\n",
|
||||
"# Tests\n",
|
||||
"print(chaine_evolution(\"Bulbizarre\", pokedex))\n",
|
||||
"print(chaine_evolution(\"Pikachu\", pokedex))\n",
|
||||
"print(chaine_evolution(\"Mewtwo\", pokedex))"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"### 3.2 Vérifier efficacité (5 pts)\n",
|
||||
"\n",
|
||||
"Écrivez une fonction `est_efficace(attaquant, defenseur, faiblesses)` qui renvoie `True` si l'attaquant a un type efficace contre le défenseur."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"def est_efficace(attaquant, defenseur, faiblesses):\n",
|
||||
" types_attaquant = attaquant[1]\n",
|
||||
" types_defenseur = defenseur[1]\n",
|
||||
" \n",
|
||||
" # Pour chaque type de l'attaquant, verifier s'il est efficace\n",
|
||||
" # Votre code ici\n",
|
||||
" pass\n",
|
||||
" \n",
|
||||
" return False\n",
|
||||
"\n",
|
||||
"# Tests\n",
|
||||
"pikachu = pokedex[9]\n",
|
||||
"tortank = pokedex[8]\n",
|
||||
"dracaufeu = pokedex[5]\n",
|
||||
"\n",
|
||||
"print(\"Pikachu efficace contre Tortank ?\", est_efficace(pikachu, tortank, faiblesses))\n",
|
||||
"print(\"Dracaufeu efficace contre Tortank ?\", est_efficace(dracaufeu, tortank, faiblesses))"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"### 3.3 Meilleur contre un adversaire (4 pts)\n",
|
||||
"\n",
|
||||
"Écrivez une fonction `meilleur_contre(adversaire, equipe, faiblesses)` qui renvoie le Pokémon de l'équipe le plus efficace contre l'adversaire.\n",
|
||||
"\n",
|
||||
"S'il n'y a pas de Pokémon efficace, renvoyer le plus fort en attaque."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"def meilleur_contre(adversaire, equipe, faiblesses):\n",
|
||||
" # D'abord chercher un pokemon efficace\n",
|
||||
" # Votre code ici\n",
|
||||
" pass\n",
|
||||
" \n",
|
||||
" # Sinon renvoyer le plus fort en attaque\n",
|
||||
" return plus_fort(equipe)\n",
|
||||
"\n",
|
||||
"# Test\n",
|
||||
"leviator = pokedex[18]\n",
|
||||
"choix = meilleur_contre(leviator, equipe, faiblesses)\n",
|
||||
"if choix:\n",
|
||||
" print(\"Meilleur choix contre Leviator :\", choix[0])"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"kernelspec": {
|
||||
"display_name": "Python 3",
|
||||
"language": "python",
|
||||
"name": "python3"
|
||||
},
|
||||
"language_info": {
|
||||
"name": "python",
|
||||
"version": "3.9.0"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 4
|
||||
}
|
||||
@@ -1,214 +0,0 @@
|
||||
# Aide - TP06 Pokemon
|
||||
|
||||
## Rappels utiles
|
||||
|
||||
### Structure des tuples Pokemon
|
||||
```python
|
||||
# Pokemon = (nom, types, pv, attaque, defense, vitesse, evolution)
|
||||
pokemon = pokedex[0]
|
||||
nom = pokemon[0] # "Bulbizarre"
|
||||
types = pokemon[1] # ("Plante", "Poison")
|
||||
pv = pokemon[2] # 45
|
||||
attaque = pokemon[3] # 49
|
||||
defense = pokemon[4] # 49
|
||||
vitesse = pokemon[5] # 45
|
||||
evolution = pokemon[6] # "Herbizarre"
|
||||
```
|
||||
|
||||
### Types multiples
|
||||
```python
|
||||
pokemon = pokedex[5] # Dracaufeu
|
||||
# types est un tuple : ("Feu", "Vol")
|
||||
print(pokemon[1][0]) # "Feu" (type principal)
|
||||
|
||||
if "Feu" in pokemon[1]:
|
||||
print("C'est un type Feu")
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Exercice 1
|
||||
|
||||
### 1.1 - Affichage Pokemon
|
||||
```python
|
||||
def afficher_pokemon(pokemon):
|
||||
nom = pokemon[0]
|
||||
types = pokemon[1]
|
||||
pv = pokemon[2]
|
||||
attaque = pokemon[3]
|
||||
defense = pokemon[4]
|
||||
vitesse = pokemon[5]
|
||||
evolution = pokemon[6]
|
||||
|
||||
# Afficher les types
|
||||
if len(types) == 2:
|
||||
types_str = types[0] + "/" + types[1]
|
||||
else:
|
||||
types_str = types[0]
|
||||
|
||||
print(nom, "(", types_str, ")")
|
||||
print("PV:", pv, "| ATK:", attaque, "| DEF:", defense, "| VIT:", vitesse)
|
||||
|
||||
if evolution == None:
|
||||
print("Evolution: Forme finale")
|
||||
else:
|
||||
print("Evolution:", evolution)
|
||||
```
|
||||
|
||||
### 1.2 - Recherche par type
|
||||
```python
|
||||
def pokemon_par_type(dex, type_recherche):
|
||||
resultat = []
|
||||
for p in dex:
|
||||
if type_recherche in p[1]: # p[1] = types
|
||||
resultat.append(p)
|
||||
# Trier par PV (indice 2) decroissants
|
||||
resultat = sorted(resultat, key=lambda p: p[2], reverse=True)
|
||||
return resultat
|
||||
```
|
||||
|
||||
### 1.3 - Compter les types
|
||||
```python
|
||||
def compter_types(dex):
|
||||
compteur = {}
|
||||
for pokemon in dex:
|
||||
types = pokemon[1]
|
||||
for t in types:
|
||||
if t not in compteur:
|
||||
compteur[t] = 0
|
||||
compteur[t] = compteur[t] + 1
|
||||
return compteur
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Exercice 2
|
||||
|
||||
### 2.1 - Charger equipe
|
||||
```python
|
||||
def charger_equipe(noms, dex):
|
||||
equipe = []
|
||||
for nom_recherche in noms:
|
||||
# Chercher le pokemon dans le pokedex
|
||||
for pokemon in dex:
|
||||
if pokemon[0] == nom_recherche:
|
||||
equipe.append(pokemon)
|
||||
break
|
||||
return equipe
|
||||
```
|
||||
|
||||
### 2.2 - Force de l'equipe
|
||||
```python
|
||||
def force_equipe(equipe):
|
||||
force_totale = 0
|
||||
for pokemon in equipe:
|
||||
pv = pokemon[2]
|
||||
attaque = pokemon[3]
|
||||
defense = pokemon[4]
|
||||
vitesse = pokemon[5]
|
||||
force_pokemon = pv + attaque + defense + vitesse
|
||||
force_totale = force_totale + force_pokemon
|
||||
return force_totale
|
||||
```
|
||||
|
||||
### 2.3 - Pokemon le plus fort
|
||||
```python
|
||||
def plus_fort(equipe):
|
||||
if len(equipe) == 0:
|
||||
return None
|
||||
|
||||
meilleur = equipe[0]
|
||||
meilleure_attaque = equipe[0][3] # indice 3 = attaque
|
||||
|
||||
for pokemon in equipe:
|
||||
if pokemon[3] > meilleure_attaque:
|
||||
meilleur = pokemon
|
||||
meilleure_attaque = pokemon[3]
|
||||
|
||||
return meilleur
|
||||
```
|
||||
|
||||
### 2.4 - Types couverts
|
||||
```python
|
||||
def types_couverts(equipe):
|
||||
types_liste = []
|
||||
for pokemon in equipe:
|
||||
types = pokemon[1]
|
||||
for t in types:
|
||||
if t not in types_liste:
|
||||
types_liste.append(t)
|
||||
return types_liste
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Exercice 3 (Bonus)
|
||||
|
||||
### 3.1 - Chaine d'evolution
|
||||
```python
|
||||
def chaine_evolution(nom, dex):
|
||||
chaine = [nom]
|
||||
|
||||
# Chercher le pokemon actuel
|
||||
pokemon_actuel = None
|
||||
for p in dex:
|
||||
if p[0] == nom:
|
||||
pokemon_actuel = p
|
||||
break
|
||||
|
||||
if pokemon_actuel == None:
|
||||
return chaine
|
||||
|
||||
# Suivre les evolutions
|
||||
evolution = pokemon_actuel[6]
|
||||
while evolution != None and evolution != "Multiple":
|
||||
chaine.append(evolution)
|
||||
# Chercher le pokemon suivant
|
||||
for p in dex:
|
||||
if p[0] == evolution:
|
||||
evolution = p[6]
|
||||
break
|
||||
|
||||
return chaine
|
||||
```
|
||||
|
||||
### 3.2 - Verifier efficacite
|
||||
```python
|
||||
def est_efficace(attaquant, defenseur, faiblesses):
|
||||
types_attaquant = attaquant[1]
|
||||
types_defenseur = defenseur[1]
|
||||
|
||||
# Pour chaque type de l'attaquant
|
||||
for type_att in types_attaquant:
|
||||
# Verifier si ce type est efficace
|
||||
if type_att in faiblesses:
|
||||
types_faibles = faiblesses[type_att]
|
||||
# Verifier si le defenseur a un type faible
|
||||
for type_def in types_defenseur:
|
||||
if type_def in types_faibles:
|
||||
return True
|
||||
|
||||
return False
|
||||
```
|
||||
|
||||
### 3.3 - Meilleur contre un adversaire
|
||||
```python
|
||||
def meilleur_contre(adversaire, equipe, faiblesses):
|
||||
# D'abord chercher un pokemon efficace
|
||||
for pokemon in equipe:
|
||||
if est_efficace(pokemon, adversaire, faiblesses):
|
||||
return pokemon
|
||||
|
||||
# Sinon renvoyer le plus fort en attaque
|
||||
return plus_fort(equipe)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Pieges a eviter
|
||||
|
||||
1. **Types en tuple** : meme un seul type est un tuple `("Feu",)` - notez la virgule !
|
||||
2. **Tuples immutables** : vous ne pouvez pas modifier `pokemon[2] = 50`
|
||||
3. **Faiblesses unidirectionnelles** : Feu bat Plante, mais Plante ne bat pas Feu
|
||||
4. **PV negatifs** : verifiez `pv > 0` et non `pv >= 0`
|
||||
5. **Acces par indice** : pokemon[0]=nom, pokemon[1]=types, pokemon[2]=pv, pokemon[3]=attaque, pokemon[4]=defense, pokemon[5]=vitesse, pokemon[6]=evolution
|
||||
@@ -1,268 +0,0 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"# TP Évaluation - Collection Manga\n",
|
||||
"\n",
|
||||
"**Durée : 1h30**\n",
|
||||
"\n",
|
||||
"**Nom :** \n",
|
||||
"\n",
|
||||
"**Prénom :**\n",
|
||||
"\n",
|
||||
"---\n",
|
||||
"\n",
|
||||
"Dans ce TP, vous allez gérer une collection de mangas.\n",
|
||||
"\n",
|
||||
"**Compétences évaluées :**\n",
|
||||
"- Listes de dictionnaires\n",
|
||||
"- Algorithmes de filtrage et tri\n",
|
||||
"- Manipulation de données"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Données initiales\n",
|
||||
"\n",
|
||||
"**Exécutez cette cellule avant de commencer.**"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Collection de mangas\n",
|
||||
"# Chaque manga est un dictionnaire\n",
|
||||
"mangas = [\n",
|
||||
" {\"titre\": \"One Piece\", \"auteur\": \"Eiichiro Oda\", \"genres\": [\"Aventure\", \"Action\"], \"tomes\": 107, \"termine\": False, \"note\": 9.2},\n",
|
||||
" {\"titre\": \"Naruto\", \"auteur\": \"Masashi Kishimoto\", \"genres\": [\"Action\", \"Aventure\"], \"tomes\": 72, \"termine\": True, \"note\": 8.5},\n",
|
||||
" {\"titre\": \"Death Note\", \"auteur\": \"Tsugumi Ohba\", \"genres\": [\"Thriller\", \"Psychologique\"], \"tomes\": 12, \"termine\": True, \"note\": 9.0},\n",
|
||||
" {\"titre\": \"Attack on Titan\", \"auteur\": \"Hajime Isayama\", \"genres\": [\"Action\", \"Drame\"], \"tomes\": 34, \"termine\": True, \"note\": 9.1},\n",
|
||||
" {\"titre\": \"My Hero Academia\", \"auteur\": \"Kohei Horikoshi\", \"genres\": [\"Action\", \"Super-heros\"], \"tomes\": 40, \"termine\": False, \"note\": 8.3},\n",
|
||||
" {\"titre\": \"Demon Slayer\", \"auteur\": \"Koyoharu Gotouge\", \"genres\": [\"Action\", \"Surnaturel\"], \"tomes\": 23, \"termine\": True, \"note\": 8.7},\n",
|
||||
" {\"titre\": \"Jujutsu Kaisen\", \"auteur\": \"Gege Akutami\", \"genres\": [\"Action\", \"Surnaturel\"], \"tomes\": 25, \"termine\": False, \"note\": 8.8},\n",
|
||||
" {\"titre\": \"Chainsaw Man\", \"auteur\": \"Tatsuki Fujimoto\", \"genres\": [\"Action\", \"Horreur\"], \"tomes\": 16, \"termine\": False, \"note\": 8.9},\n",
|
||||
" {\"titre\": \"Spy x Family\", \"auteur\": \"Tatsuya Endo\", \"genres\": [\"Action\", \"Comedie\"], \"tomes\": 12, \"termine\": False, \"note\": 8.6},\n",
|
||||
" {\"titre\": \"Dragon Ball\", \"auteur\": \"Akira Toriyama\", \"genres\": [\"Action\", \"Aventure\"], \"tomes\": 42, \"termine\": True, \"note\": 8.8},\n",
|
||||
" {\"titre\": \"Fullmetal Alchemist\", \"auteur\": \"Hiromu Arakawa\", \"genres\": [\"Action\", \"Aventure\", \"Fantasy\"], \"tomes\": 27, \"termine\": True, \"note\": 9.3},\n",
|
||||
" {\"titre\": \"Tokyo Ghoul\", \"auteur\": \"Sui Ishida\", \"genres\": [\"Action\", \"Horreur\"], \"tomes\": 14, \"termine\": True, \"note\": 8.4}\n",
|
||||
"]\n",
|
||||
"\n",
|
||||
"# Ma collection personnelle (tomes possedes par manga)\n",
|
||||
"ma_collection = {\n",
|
||||
" \"Death Note\": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12],\n",
|
||||
" \"One Piece\": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10],\n",
|
||||
" \"Demon Slayer\": [1, 2, 3, 4, 5],\n",
|
||||
" \"Spy x Family\": [1, 2, 3, 4]\n",
|
||||
"}\n",
|
||||
"\n",
|
||||
"# Liste de souhaits\n",
|
||||
"liste_souhaits = [\"Chainsaw Man\", \"Jujutsu Kaisen\", \"Fullmetal Alchemist\"]"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"---\n",
|
||||
"\n",
|
||||
"## Exercice 1 - Exploration du catalogue (25 min)\n",
|
||||
"\n",
|
||||
"### 1.1 Affichage d'un manga (4 pts)\n",
|
||||
"\n",
|
||||
"Écrivez une fonction `afficher_manga(manga)` qui affiche les informations d'un manga.\n",
|
||||
"\n",
|
||||
"Exemple :\n",
|
||||
"```\n",
|
||||
"Death Note - Tsugumi Ohba\n",
|
||||
"Genres : Thriller, Psychologique\n",
|
||||
"12 tomes (Termine) | Note : 9.0\n",
|
||||
"```"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": "def afficher_manga(manga):\n titre = manga[\"titre\"]\n auteur = manga[\"auteur\"]\n genres = manga[\"genres\"]\n tomes = manga[\"tomes\"]\n termine = manga[\"termine\"]\n note = manga[\"note\"]\n \n # Afficher : titre - auteur\n # Votre code ici\n pass\n \n # Afficher les genres séparés par des virgules\n # Votre code ici\n pass\n \n # Afficher le statut : \"Termine\" ou \"En cours\"\n # Votre code ici\n pass\n\n# Tests\nafficher_manga(mangas[2]) # Death Note\nprint()\nafficher_manga(mangas[0]) # One Piece"
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"### 1.2 Recherche par genre (4 pts)\n",
|
||||
"\n",
|
||||
"Écrivez une fonction `rechercher_par_genre(mangas, genre)` qui renvoie la liste des mangas contenant ce genre."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": "def rechercher_par_genre(mangas, genre):\n resultats = []\n \n for manga in mangas:\n # Votre code ici\n pass\n \n return resultats\n\n# Test\nprint(\"Mangas d'Horreur :\")\nfor m in rechercher_par_genre(mangas, \"Horreur\"):\n print(\" \", m[\"titre\"])"
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"### 1.3 Mangas terminés (4 pts)\n",
|
||||
"\n",
|
||||
"Écrivez une fonction `mangas_termines(mangas)` qui renvoie la liste des mangas terminés, triés par note décroissante."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": "def mangas_termines(mangas):\n termines = []\n \n for manga in mangas:\n # Votre code ici\n pass\n \n # Trier par note decroissante\n # Votre code ici\n pass\n \n return termines\n\n# Test\nprint(\"Mangas termines (par note) :\")\nfor m in mangas_termines(mangas):\n print(\" \", m[\"titre\"], \"-\", m[\"note\"])"
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"---\n",
|
||||
"\n",
|
||||
"## Exercice 2 - Gestion de collection (35 min)\n",
|
||||
"\n",
|
||||
"### 2.1 Avancement de lecture (6 pts)\n",
|
||||
"\n",
|
||||
"Écrivez une fonction `avancement_collection(ma_coll, mangas)` qui calcule l'avancement pour chaque manga possédé.\n",
|
||||
"\n",
|
||||
"Renvoie une liste de dictionnaires avec `titre`, `possede`, `total`, `pourcentage`, `complet` (booléen)."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": "def avancement_collection(ma_coll, mangas):\n avancement = []\n \n for titre, tomes_possedes in ma_coll.items():\n # Trouver le manga dans le catalogue\n total_tomes = 0\n for manga in mangas:\n # Votre code ici\n pass\n \n nb_possedes = len(tomes_possedes)\n \n # Calculer le pourcentage (arrondi)\n # Votre code ici\n pourcentage = 0\n \n # Determiner si la collection est complete\n # Votre code ici\n complet = False\n \n avancement.append({\n \"titre\": titre,\n \"possede\": nb_possedes,\n \"total\": total_tomes,\n \"pourcentage\": pourcentage,\n \"complet\": complet\n })\n \n return avancement\n\n# Test\nprint(\"Avancement de ma collection :\")\nfor item in avancement_collection(ma_collection, mangas):\n statut = \"Complet\" if item[\"complet\"] else str(item[\"pourcentage\"]) + \"%\"\n print(\" \", item[\"titre\"], \":\", item[\"possede\"], \"/\", item[\"total\"], \"(\", statut, \")\")"
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"### 2.2 Tomes manquants (5 pts)\n",
|
||||
"\n",
|
||||
"Écrivez une fonction `tomes_manquants(titre, ma_coll, mangas)` qui renvoie la liste des numéros de tomes manquants pour un manga donné."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": "def tomes_manquants(titre, ma_coll, mangas):\n # Trouver le nombre total de tomes\n total_tomes = 0\n for manga in mangas:\n # Votre code ici\n pass\n \n # Recuperer les tomes possedes\n if titre in ma_coll:\n possedes = ma_coll[titre]\n else:\n possedes = []\n \n # Trouver les manquants\n manquants = []\n for i in range(1, total_tomes + 1):\n # Votre code ici\n pass\n \n return manquants\n\n# Test\nmanq = tomes_manquants(\"One Piece\", ma_collection, mangas)\nprint(\"Tomes manquants de One Piece :\", len(manq), \"tomes\")\nprint(\"Premiers manquants :\", manq[:10])"
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"### 2.3 Valeur de la collection (5 pts)\n",
|
||||
"\n",
|
||||
"Écrivez une fonction `valeur_collection(ma_coll, prix_par_tome)` qui calcule la valeur totale de la collection.\n",
|
||||
"\n",
|
||||
"Renvoie un dictionnaire avec `nb_tomes` et `valeur_totale`."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": "def valeur_collection(ma_coll, prix_par_tome):\n nb_tomes = 0\n \n for titre, tomes in ma_coll.items():\n # Votre code ici\n pass\n \n # Calculer la valeur totale\n # Votre code ici\n valeur = 0\n \n return {\n \"nb_tomes\": nb_tomes,\n \"valeur_totale\": valeur\n }\n\n# Test (7 euros par tome)\nval = valeur_collection(ma_collection, 7)\nprint(\"Ma collection :\", val[\"nb_tomes\"], \"tomes\")\nprint(\"Valeur estimee :\", val[\"valeur_totale\"], \"euros\")"
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"### 2.4 Note moyenne des mangas possédés (5 pts)\n",
|
||||
"\n",
|
||||
"Écrivez une fonction `note_moyenne_collection(ma_coll, mangas)` qui calcule la note moyenne des mangas de la collection."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": "def note_moyenne_collection(ma_coll, mangas):\n total_notes = 0\n nb_mangas = 0\n \n for titre in ma_coll.keys():\n # Trouver le manga dans le catalogue\n for manga in mangas:\n # Votre code ici\n pass\n \n if nb_mangas == 0:\n return 0\n \n return round(total_notes / nb_mangas, 2)\n\n# Test\nprint(\"Note moyenne de ma collection :\", note_moyenne_collection(ma_collection, mangas))"
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"---\n",
|
||||
"\n",
|
||||
"## Exercice 3 - Bonus (20 min)\n",
|
||||
"\n",
|
||||
"### 3.1 Recommandation (5 pts)\n",
|
||||
"\n",
|
||||
"Écrivez une fonction `recommander(ma_coll, mangas)` qui recommande un manga non possédé basé sur les genres de la collection.\n",
|
||||
"\n",
|
||||
"Score = nombre de genres en commun + note du manga"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": "def recommander(ma_coll, mangas):\n # Collecter les genres de ma collection\n mes_genres = []\n for titre in ma_coll.keys():\n for manga in mangas:\n if manga[\"titre\"] == titre:\n for g in manga[\"genres\"]:\n if g not in mes_genres:\n mes_genres.append(g)\n \n # Chercher le meilleur manga non possede\n meilleur = None\n meilleur_score = 0\n \n for manga in mangas:\n if manga[\"titre\"] not in ma_coll:\n # Compter les genres en commun\n genres_communs = 0\n for g in manga[\"genres\"]:\n # Votre code ici\n pass\n \n score = genres_communs + manga[\"note\"]\n \n # Votre code ici : mettre a jour meilleur si score est superieur\n pass\n \n return meilleur\n\n# Test\nreco = recommander(ma_collection, mangas)\nif reco:\n print(\"Recommandation :\")\n afficher_manga(reco)"
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"### 3.2 Liste des auteurs (4 pts)\n",
|
||||
"\n",
|
||||
"Écrivez une fonction `auteurs_uniques(mangas)` qui renvoie la liste des auteurs (sans doublons), triée par ordre alphabétique."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": "def auteurs_uniques(mangas):\n auteurs = []\n \n for manga in mangas:\n # Votre code ici : ajouter l'auteur s'il n'est pas deja dans la liste\n pass\n \n auteurs.sort()\n return auteurs\n\n# Test\nprint(\"Auteurs :\", auteurs_uniques(mangas))"
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"### 3.3 Statistiques par genre (5 pts)\n",
|
||||
"\n",
|
||||
"Écrivez une fonction `stats_par_genre(mangas)` qui renvoie un dictionnaire avec pour chaque genre : le nombre de mangas et la note moyenne."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": "def stats_par_genre(mangas):\n # Collecter les donnees par genre\n donnees = {}\n \n for manga in mangas:\n for genre in manga[\"genres\"]:\n if genre not in donnees:\n donnees[genre] = {\"nb\": 0, \"total_notes\": 0}\n # Votre code ici : incrementer nb et ajouter la note\n pass\n \n # Calculer les moyennes\n stats = {}\n for genre, data in donnees.items():\n # Votre code ici : calculer la moyenne et remplir stats\n pass\n \n return stats\n\n# Test\nprint(\"Statistiques par genre :\")\nfor genre, data in stats_par_genre(mangas).items():\n print(\" \", genre, \":\", data[\"nombre\"], \"mangas, note moyenne\", data[\"note_moyenne\"])"
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"kernelspec": {
|
||||
"display_name": "Python 3",
|
||||
"language": "python",
|
||||
"name": "python3"
|
||||
},
|
||||
"language_info": {
|
||||
"name": "python",
|
||||
"version": "3.9.0"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 4
|
||||
}
|
||||
@@ -1,264 +0,0 @@
|
||||
# Aide - TP07 Manga
|
||||
|
||||
## Rappels utiles
|
||||
|
||||
### Structure des mangas (dictionnaires)
|
||||
```python
|
||||
# Chaque manga est un dictionnaire
|
||||
manga = mangas[0]
|
||||
print(manga["titre"]) # "One Piece"
|
||||
print(manga["auteur"]) # "Eiichiro Oda"
|
||||
print(manga["genres"]) # ["Aventure", "Action"]
|
||||
print(manga["tomes"]) # 107
|
||||
print(manga["termine"]) # False
|
||||
print(manga["note"]) # 9.2
|
||||
```
|
||||
|
||||
### Collection personnelle (dictionnaire)
|
||||
```python
|
||||
# ma_collection = {titre: [liste des tomes possedes]}
|
||||
ma_collection = {
|
||||
"Death Note": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12],
|
||||
"One Piece": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
|
||||
}
|
||||
|
||||
# Acceder aux tomes d'un manga
|
||||
tomes_possedes = ma_collection["Death Note"]
|
||||
print(len(tomes_possedes)) # 12
|
||||
```
|
||||
|
||||
### Parcourir la collection
|
||||
```python
|
||||
for titre, tomes_possedes in ma_collection.items():
|
||||
print(titre, ":", len(tomes_possedes), "tomes")
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Exercice 1
|
||||
|
||||
### 1.1 - Affichage d'un manga
|
||||
```python
|
||||
def afficher_manga(manga):
|
||||
titre = manga["titre"]
|
||||
auteur = manga["auteur"]
|
||||
genres = manga["genres"]
|
||||
tomes = manga["tomes"]
|
||||
termine = manga["termine"]
|
||||
note = manga["note"]
|
||||
|
||||
print(titre, "-", auteur)
|
||||
|
||||
# Afficher les genres
|
||||
genres_str = ", ".join(genres)
|
||||
print("Genres:", genres_str)
|
||||
|
||||
# Afficher le statut
|
||||
if termine:
|
||||
statut = "Termine"
|
||||
else:
|
||||
statut = "En cours"
|
||||
|
||||
print(tomes, "tomes (", statut, ") | Note:", note)
|
||||
```
|
||||
|
||||
### 1.2 - Recherche par genre
|
||||
```python
|
||||
def rechercher_par_genre(mangas, genre):
|
||||
resultats = []
|
||||
for manga in mangas:
|
||||
if genre in manga["genres"]:
|
||||
resultats.append(manga)
|
||||
return resultats
|
||||
```
|
||||
|
||||
### 1.3 - Mangas termines
|
||||
```python
|
||||
def mangas_termines(mangas):
|
||||
termines = []
|
||||
for manga in mangas:
|
||||
if manga["termine"] == True:
|
||||
termines.append(manga)
|
||||
|
||||
# Trier par note decroissante
|
||||
termines = sorted(termines, key=lambda m: m["note"], reverse=True)
|
||||
return termines
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Exercice 2
|
||||
|
||||
### 2.1 - Avancement de lecture
|
||||
```python
|
||||
def avancement_collection(ma_coll, mangas):
|
||||
avancement = []
|
||||
|
||||
for titre, tomes_possedes in ma_coll.items():
|
||||
# Trouver le manga dans le catalogue
|
||||
total_tomes = 0
|
||||
for manga in mangas:
|
||||
if manga["titre"] == titre:
|
||||
total_tomes = manga["tomes"]
|
||||
break
|
||||
|
||||
nb_possedes = len(tomes_possedes)
|
||||
|
||||
if total_tomes > 0:
|
||||
pourcentage = round(nb_possedes / total_tomes * 100)
|
||||
else:
|
||||
pourcentage = 0
|
||||
|
||||
complet = (nb_possedes == total_tomes)
|
||||
|
||||
avancement.append({
|
||||
"titre": titre,
|
||||
"possede": nb_possedes,
|
||||
"total": total_tomes,
|
||||
"pourcentage": pourcentage,
|
||||
"complet": complet
|
||||
})
|
||||
|
||||
return avancement
|
||||
```
|
||||
|
||||
### 2.2 - Tomes manquants
|
||||
```python
|
||||
def tomes_manquants(titre, ma_coll, mangas):
|
||||
# Trouver le nombre total de tomes
|
||||
total_tomes = 0
|
||||
for manga in mangas:
|
||||
if manga["titre"] == titre:
|
||||
total_tomes = manga["tomes"]
|
||||
break
|
||||
|
||||
# Recuperer les tomes possedes
|
||||
if titre in ma_coll:
|
||||
possedes = ma_coll[titre]
|
||||
else:
|
||||
possedes = []
|
||||
|
||||
# Trouver les manquants
|
||||
manquants = []
|
||||
for i in range(1, total_tomes + 1):
|
||||
if i not in possedes:
|
||||
manquants.append(i)
|
||||
|
||||
return manquants
|
||||
```
|
||||
|
||||
### 2.3 - Valeur de la collection
|
||||
```python
|
||||
def valeur_collection(ma_coll, prix_par_tome):
|
||||
nb_tomes = 0
|
||||
|
||||
for titre, tomes in ma_coll.items():
|
||||
nb_tomes = nb_tomes + len(tomes)
|
||||
|
||||
valeur = nb_tomes * prix_par_tome
|
||||
|
||||
return {
|
||||
"nb_tomes": nb_tomes,
|
||||
"valeur_totale": valeur
|
||||
}
|
||||
```
|
||||
|
||||
### 2.4 - Note moyenne des mangas possedes
|
||||
```python
|
||||
def note_moyenne_collection(ma_coll, mangas):
|
||||
total_notes = 0
|
||||
nb_mangas = 0
|
||||
|
||||
for titre in ma_coll.keys():
|
||||
# Trouver le manga dans le catalogue
|
||||
for manga in mangas:
|
||||
if manga["titre"] == titre:
|
||||
total_notes = total_notes + manga["note"]
|
||||
nb_mangas = nb_mangas + 1
|
||||
break
|
||||
|
||||
if nb_mangas == 0:
|
||||
return 0
|
||||
|
||||
return round(total_notes / nb_mangas, 2)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Exercice 3 (Bonus)
|
||||
|
||||
### 3.1 - Recommandation
|
||||
```python
|
||||
def recommander(ma_coll, mangas):
|
||||
# Collecter les genres de ma collection
|
||||
mes_genres = []
|
||||
for titre in ma_coll.keys():
|
||||
for manga in mangas:
|
||||
if manga["titre"] == titre:
|
||||
for g in manga["genres"]:
|
||||
if g not in mes_genres:
|
||||
mes_genres.append(g)
|
||||
|
||||
# Chercher le meilleur manga non possede
|
||||
meilleur = None
|
||||
meilleur_score = 0
|
||||
|
||||
for manga in mangas:
|
||||
if manga["titre"] not in ma_coll:
|
||||
# Compter les genres en commun
|
||||
genres_communs = 0
|
||||
for g in manga["genres"]:
|
||||
if g in mes_genres:
|
||||
genres_communs = genres_communs + 1
|
||||
|
||||
score = genres_communs + manga["note"]
|
||||
|
||||
if score > meilleur_score:
|
||||
meilleur = manga
|
||||
meilleur_score = score
|
||||
|
||||
return meilleur
|
||||
```
|
||||
|
||||
### 3.2 - Auteurs uniques
|
||||
```python
|
||||
def auteurs_uniques(mangas):
|
||||
auteurs = []
|
||||
for manga in mangas:
|
||||
auteur = manga["auteur"]
|
||||
if auteur not in auteurs:
|
||||
auteurs.append(auteur)
|
||||
auteurs.sort()
|
||||
return auteurs
|
||||
```
|
||||
|
||||
### 3.3 - Statistiques par genre
|
||||
```python
|
||||
def stats_par_genre(mangas):
|
||||
# Collecter les donnees par genre
|
||||
donnees = {}
|
||||
|
||||
for manga in mangas:
|
||||
for genre in manga["genres"]:
|
||||
if genre not in donnees:
|
||||
donnees[genre] = {"nb": 0, "total_notes": 0}
|
||||
donnees[genre]["nb"] = donnees[genre]["nb"] + 1
|
||||
donnees[genre]["total_notes"] = donnees[genre]["total_notes"] + manga["note"]
|
||||
|
||||
# Calculer les moyennes
|
||||
stats = {}
|
||||
for genre, data in donnees.items():
|
||||
moyenne = round(data["total_notes"] / data["nb"], 2)
|
||||
stats[genre] = {"nombre": data["nb"], "note_moyenne": moyenne}
|
||||
|
||||
return stats
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Pieges a eviter
|
||||
|
||||
1. **Genres en liste** : les genres sont une liste `["Action", "Aventure"]`, utilisez `in` pour verifier
|
||||
2. **Collection vs catalogue** : `ma_collection` contient les titres possedes, `mangas` contient les infos completes
|
||||
3. **Division par zero** : verifiez que le diviseur est > 0 avant de calculer une moyenne
|
||||
4. **Tomes manquants** : n'oubliez pas que les tomes sont numerotes de 1 a total_tomes
|
||||
@@ -1,518 +0,0 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"# TP Évaluation - Système de commande McDonald's\n",
|
||||
"\n",
|
||||
"**Durée : 1h30**\n",
|
||||
"\n",
|
||||
"**Nom :** \n",
|
||||
"\n",
|
||||
"**Prénom :**\n",
|
||||
"\n",
|
||||
"---\n",
|
||||
"\n",
|
||||
"Dans ce TP, vous allez créer un système de gestion de commandes pour un fast-food.\n",
|
||||
"\n",
|
||||
"**Compétences évaluées :**\n",
|
||||
"- Manipulation de dictionnaires imbriqués\n",
|
||||
"- Calculs sur des structures de données\n",
|
||||
"- Algorithmes de traitement de commandes"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Données initiales\n",
|
||||
"\n",
|
||||
"**Exécutez cette cellule avant de commencer.**"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Menu du restaurant\n",
|
||||
"menu = {\n",
|
||||
" \"burgers\": {\n",
|
||||
" \"Big Mac\": {\"prix\": 5.50, \"calories\": 540},\n",
|
||||
" \"McChicken\": {\"prix\": 4.90, \"calories\": 400},\n",
|
||||
" \"Royal Deluxe\": {\"prix\": 6.20, \"calories\": 580},\n",
|
||||
" \"Double Cheese\": {\"prix\": 4.50, \"calories\": 450},\n",
|
||||
" \"Filet-O-Fish\": {\"prix\": 4.80, \"calories\": 380},\n",
|
||||
" \"McFirst\": {\"prix\": 2.50, \"calories\": 260}\n",
|
||||
" },\n",
|
||||
" \"accompagnements\": {\n",
|
||||
" \"Frites (P)\": {\"prix\": 2.00, \"calories\": 230},\n",
|
||||
" \"Frites (M)\": {\"prix\": 2.50, \"calories\": 340},\n",
|
||||
" \"Frites (G)\": {\"prix\": 3.00, \"calories\": 450},\n",
|
||||
" \"Potatoes\": {\"prix\": 3.20, \"calories\": 290},\n",
|
||||
" \"Salade\": {\"prix\": 3.50, \"calories\": 80},\n",
|
||||
" \"Nuggets x6\": {\"prix\": 4.50, \"calories\": 260},\n",
|
||||
" \"Nuggets x9\": {\"prix\": 5.90, \"calories\": 390}\n",
|
||||
" },\n",
|
||||
" \"boissons\": {\n",
|
||||
" \"Coca-Cola (M)\": {\"prix\": 2.50, \"calories\": 140},\n",
|
||||
" \"Coca-Cola (G)\": {\"prix\": 3.00, \"calories\": 200},\n",
|
||||
" \"Sprite (M)\": {\"prix\": 2.50, \"calories\": 130},\n",
|
||||
" \"Eau\": {\"prix\": 1.50, \"calories\": 0},\n",
|
||||
" \"Cafe\": {\"prix\": 1.80, \"calories\": 5}\n",
|
||||
" },\n",
|
||||
" \"desserts\": {\n",
|
||||
" \"Sundae Caramel\": {\"prix\": 2.80, \"calories\": 340},\n",
|
||||
" \"Sundae Chocolat\": {\"prix\": 2.80, \"calories\": 350},\n",
|
||||
" \"McFlurry Oreo\": {\"prix\": 3.50, \"calories\": 380},\n",
|
||||
" \"Cookie\": {\"prix\": 1.50, \"calories\": 180}\n",
|
||||
" }\n",
|
||||
"}\n",
|
||||
"\n",
|
||||
"# Menus Best-Of (formules)\n",
|
||||
"menus_bestof = {\n",
|
||||
" \"Best-Of Big Mac\": {\"burger\": \"Big Mac\", \"frites\": \"Frites (M)\", \"boisson\": \"Coca-Cola (M)\", \"prix\": 8.90},\n",
|
||||
" \"Best-Of McChicken\": {\"burger\": \"McChicken\", \"frites\": \"Frites (M)\", \"boisson\": \"Coca-Cola (M)\", \"prix\": 8.50},\n",
|
||||
" \"Best-Of Royal\": {\"burger\": \"Royal Deluxe\", \"frites\": \"Frites (M)\", \"boisson\": \"Coca-Cola (M)\", \"prix\": 9.50}\n",
|
||||
"}\n",
|
||||
"\n",
|
||||
"# File de commandes en cours\n",
|
||||
"# Chaque commande : {\"id\": numero, \"items\": [(article, quantite), ...], \"heure\": \"HH:MM\"}\n",
|
||||
"commandes_en_cours = [\n",
|
||||
" {\"id\": 101, \"items\": [(\"Big Mac\", 2), (\"Frites (G)\", 2), (\"Coca-Cola (G)\", 2)], \"heure\": \"12:05\"},\n",
|
||||
" {\"id\": 102, \"items\": [(\"Best-Of McChicken\", 1), (\"McFlurry Oreo\", 1)], \"heure\": \"12:07\"},\n",
|
||||
" {\"id\": 103, \"items\": [(\"Nuggets x9\", 2), (\"Frites (M)\", 2), (\"Sprite (M)\", 2)], \"heure\": \"12:08\"},\n",
|
||||
" {\"id\": 104, \"items\": [(\"Best-Of Royal\", 1), (\"Salade\", 1), (\"Eau\", 1)], \"heure\": \"12:10\"},\n",
|
||||
" {\"id\": 105, \"items\": [(\"Double Cheese\", 3), (\"Frites (G)\", 3), (\"Sundae Chocolat\", 3)], \"heure\": \"12:12\"}\n",
|
||||
"]"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"---\n",
|
||||
"\n",
|
||||
"## Exercice 1 - Exploration du menu (25 min)\n",
|
||||
"\n",
|
||||
"### 1.1 Affichage d'une catégorie (4 pts)\n",
|
||||
"\n",
|
||||
"Écrivez une fonction `afficher_categorie(menu, categorie)` qui affiche les articles d'une catégorie.\n",
|
||||
"\n",
|
||||
"Exemple :\n",
|
||||
"```\n",
|
||||
"=== BURGERS ===\n",
|
||||
"Big Mac : 5.50 euros (540 cal)\n",
|
||||
"McChicken : 4.90 euros (400 cal)\n",
|
||||
"...\n",
|
||||
"```"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"def afficher_categorie(menu, categorie):\n",
|
||||
" if categorie not in menu:\n",
|
||||
" print(\"Categorie inconnue\")\n",
|
||||
" return\n",
|
||||
" \n",
|
||||
" print(\"===\", categorie.upper(), \"===\")\n",
|
||||
" \n",
|
||||
" articles = menu[categorie]\n",
|
||||
" for nom, infos in articles.items():\n",
|
||||
" # Votre code ici : afficher le nom, prix et calories\n",
|
||||
" pass\n",
|
||||
"\n",
|
||||
"# Test\n",
|
||||
"afficher_categorie(menu, \"burgers\")"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"### 1.2 Rechercher un article (4 pts)\n",
|
||||
"\n",
|
||||
"Écrivez une fonction `rechercher_article(menu, nom)` qui cherche un article par son nom.\n",
|
||||
"\n",
|
||||
"Renvoie un dictionnaire `{\"nom\": ..., \"categorie\": ..., \"prix\": ..., \"calories\": ...}` ou `None` si non trouvé."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"def rechercher_article(menu, nom):\n",
|
||||
" for categorie, articles in menu.items():\n",
|
||||
" if nom in articles:\n",
|
||||
" infos = articles[nom]\n",
|
||||
" # Votre code ici : renvoyer le dictionnaire avec nom, categorie, prix, calories\n",
|
||||
" pass\n",
|
||||
" return None\n",
|
||||
"\n",
|
||||
"# Tests\n",
|
||||
"article = rechercher_article(menu, \"Big Mac\")\n",
|
||||
"if article:\n",
|
||||
" print(article[\"nom\"], \"trouve dans\", article[\"categorie\"])\n",
|
||||
" print(\"Prix :\", article[\"prix\"], \"euros\")\n",
|
||||
"\n",
|
||||
"print()\n",
|
||||
"print(\"Pizza :\", rechercher_article(menu, \"Pizza\"))"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"### 1.3 Article le moins calorique (4 pts)\n",
|
||||
"\n",
|
||||
"Écrivez une fonction `moins_calorique(menu, categorie)` qui renvoie l'article le moins calorique d'une catégorie.\n",
|
||||
"\n",
|
||||
"Si `categorie` est `None`, chercher dans tout le menu.\n",
|
||||
"\n",
|
||||
"Renvoie un tuple `(nom, calories)`."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"def moins_calorique(menu, categorie):\n",
|
||||
" meilleur_nom = None\n",
|
||||
" meilleur_cal = 99999\n",
|
||||
" \n",
|
||||
" if categorie != None:\n",
|
||||
" # Chercher dans une seule categorie\n",
|
||||
" articles = menu[categorie]\n",
|
||||
" for nom, infos in articles.items():\n",
|
||||
" # Votre code ici\n",
|
||||
" pass\n",
|
||||
" else:\n",
|
||||
" # Chercher dans tout le menu\n",
|
||||
" for cat, articles in menu.items():\n",
|
||||
" for nom, infos in articles.items():\n",
|
||||
" # Votre code ici\n",
|
||||
" pass\n",
|
||||
" \n",
|
||||
" return (meilleur_nom, meilleur_cal)\n",
|
||||
"\n",
|
||||
"# Tests\n",
|
||||
"print(\"Moins calorique (burgers) :\", moins_calorique(menu, \"burgers\"))\n",
|
||||
"print(\"Moins calorique (tout) :\", moins_calorique(menu, None))"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"---\n",
|
||||
"\n",
|
||||
"## Exercice 2 - Gestion des commandes (35 min)\n",
|
||||
"\n",
|
||||
"### 2.1 Calculer le prix d'une commande (6 pts)\n",
|
||||
"\n",
|
||||
"Écrivez une fonction `calculer_prix(commande, menu, menus_bestof)` qui calcule le prix total d'une commande.\n",
|
||||
"\n",
|
||||
"Attention : les articles peuvent être des Best-Of ou des articles individuels.\n",
|
||||
"\n",
|
||||
"*Aide : utilisez `rechercher_article()` pour trouver le prix d'un article dans le menu.*"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"def calculer_prix(commande, menu, menus_bestof):\n",
|
||||
" total = 0\n",
|
||||
" \n",
|
||||
" for item in commande[\"items\"]:\n",
|
||||
" nom_article = item[0]\n",
|
||||
" quantite = item[1]\n",
|
||||
" \n",
|
||||
" # Verifier si c'est un Best-Of\n",
|
||||
" if nom_article in menus_bestof:\n",
|
||||
" # Votre code ici : ajouter le prix du Best-Of * quantite\n",
|
||||
" pass\n",
|
||||
" else:\n",
|
||||
" # Chercher dans le menu normal avec rechercher_article\n",
|
||||
" # Votre code ici\n",
|
||||
" pass\n",
|
||||
" \n",
|
||||
" return round(total, 2)\n",
|
||||
"\n",
|
||||
"# Test\n",
|
||||
"for cmd in commandes_en_cours:\n",
|
||||
" prix = calculer_prix(cmd, menu, menus_bestof)\n",
|
||||
" print(\"Commande\", cmd[\"id\"], \":\", prix, \"euros\")"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"### 2.2 Calculer les calories d'une commande (5 pts)\n",
|
||||
"\n",
|
||||
"Écrivez une fonction `calculer_calories(commande, menu, menus_bestof)` qui calcule le total des calories.\n",
|
||||
"\n",
|
||||
"Pour un Best-Of, additionner les calories du burger, des frites et de la boisson."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"def calculer_calories(commande, menu, menus_bestof):\n",
|
||||
" total_cal = 0\n",
|
||||
" \n",
|
||||
" for item in commande[\"items\"]:\n",
|
||||
" nom_article = item[0]\n",
|
||||
" quantite = item[1]\n",
|
||||
" \n",
|
||||
" # Verifier si c'est un Best-Of\n",
|
||||
" if nom_article in menus_bestof:\n",
|
||||
" bestof = menus_bestof[nom_article]\n",
|
||||
" # Votre code ici : additionner les calories du burger, frites et boisson\n",
|
||||
" pass\n",
|
||||
" else:\n",
|
||||
" # Chercher dans le menu normal\n",
|
||||
" # Votre code ici\n",
|
||||
" pass\n",
|
||||
" \n",
|
||||
" return total_cal\n",
|
||||
"\n",
|
||||
"# Test\n",
|
||||
"for cmd in commandes_en_cours:\n",
|
||||
" cal = calculer_calories(cmd, menu, menus_bestof)\n",
|
||||
" print(\"Commande\", cmd[\"id\"], \":\", cal, \"calories\")"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"### 2.3 Ticket de caisse (6 pts)\n",
|
||||
"\n",
|
||||
"Écrivez une fonction `generer_ticket(commande, menu, menus_bestof)` qui génère un ticket de caisse sous forme de chaîne de caractères."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"def generer_ticket(commande, menu, menus_bestof):\n",
|
||||
" lignes = []\n",
|
||||
" lignes.append(\"=\" * 30)\n",
|
||||
" lignes.append(\"COMMANDE #\" + str(commande[\"id\"]))\n",
|
||||
" lignes.append(\"Heure : \" + commande[\"heure\"])\n",
|
||||
" lignes.append(\"-\" * 30)\n",
|
||||
" \n",
|
||||
" for item in commande[\"items\"]:\n",
|
||||
" nom_article = item[0]\n",
|
||||
" quantite = item[1]\n",
|
||||
" \n",
|
||||
" # Trouver le prix de l'article\n",
|
||||
" # Votre code ici\n",
|
||||
" prix = 0\n",
|
||||
" \n",
|
||||
" sous_total = prix * quantite\n",
|
||||
" ligne = str(quantite) + \"x \" + nom_article + \" - \" + str(sous_total) + \" euros\"\n",
|
||||
" lignes.append(ligne)\n",
|
||||
" \n",
|
||||
" lignes.append(\"-\" * 30)\n",
|
||||
" total = calculer_prix(commande, menu, menus_bestof)\n",
|
||||
" lignes.append(\"TOTAL : \" + str(total) + \" euros\")\n",
|
||||
" lignes.append(\"=\" * 30)\n",
|
||||
" \n",
|
||||
" return \"\\n\".join(lignes)\n",
|
||||
"\n",
|
||||
"# Test\n",
|
||||
"print(generer_ticket(commandes_en_cours[0], menu, menus_bestof))"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"### 2.4 Chiffre d'affaires (5 pts)\n",
|
||||
"\n",
|
||||
"Écrivez une fonction `chiffre_affaires(commandes, menu, menus_bestof)` qui calcule le chiffre d'affaires total de toutes les commandes."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"def chiffre_affaires(commandes, menu, menus_bestof):\n",
|
||||
" total = 0\n",
|
||||
" \n",
|
||||
" for commande in commandes:\n",
|
||||
" # Votre code ici : utiliser calculer_prix\n",
|
||||
" pass\n",
|
||||
" \n",
|
||||
" return round(total, 2)\n",
|
||||
"\n",
|
||||
"# Test\n",
|
||||
"ca = chiffre_affaires(commandes_en_cours, menu, menus_bestof)\n",
|
||||
"print(\"Chiffre d'affaires :\", ca, \"euros\")\n",
|
||||
"print(\"Nombre de commandes :\", len(commandes_en_cours))\n",
|
||||
"print(\"Panier moyen :\", round(ca / len(commandes_en_cours), 2), \"euros\")"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"---\n",
|
||||
"\n",
|
||||
"## Exercice 3 - Bonus (20 min)\n",
|
||||
"\n",
|
||||
"### 3.1 Article le plus commandé (5 pts)\n",
|
||||
"\n",
|
||||
"Écrivez une fonction `article_plus_commande(commandes)` qui renvoie l'article le plus commandé (en nombre total).\n",
|
||||
"\n",
|
||||
"Renvoie un tuple `(nom_article, nombre_total)`."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"def article_plus_commande(commandes):\n",
|
||||
" compteur = {}\n",
|
||||
" \n",
|
||||
" for commande in commandes:\n",
|
||||
" for item in commande[\"items\"]:\n",
|
||||
" nom = item[0]\n",
|
||||
" quantite = item[1]\n",
|
||||
" # Votre code ici : incrementer le compteur\n",
|
||||
" pass\n",
|
||||
" \n",
|
||||
" # Trouver le maximum\n",
|
||||
" meilleur = None\n",
|
||||
" meilleur_nb = 0\n",
|
||||
" \n",
|
||||
" for article, nb in compteur.items():\n",
|
||||
" # Votre code ici\n",
|
||||
" pass\n",
|
||||
" \n",
|
||||
" return (meilleur, meilleur_nb)\n",
|
||||
"\n",
|
||||
"# Test\n",
|
||||
"art, nb = article_plus_commande(commandes_en_cours)\n",
|
||||
"print(\"Article le plus commande :\", art, \"(\", nb, \"fois)\")"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"### 3.2 Économie Best-Of (5 pts)\n",
|
||||
"\n",
|
||||
"Écrivez une fonction `economie_bestof(nom_bestof, menu, menus_bestof)` qui calcule l'économie réalisée en prenant un Best-Of par rapport aux articles séparés."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"def economie_bestof(nom_bestof, menu, menus_bestof):\n",
|
||||
" if nom_bestof not in menus_bestof:\n",
|
||||
" return 0\n",
|
||||
" \n",
|
||||
" bestof = menus_bestof[nom_bestof]\n",
|
||||
" prix_bestof = bestof[\"prix\"]\n",
|
||||
" \n",
|
||||
" # Calculer le prix des articles separes (burger + frites + boisson)\n",
|
||||
" # Votre code ici\n",
|
||||
" prix_separe = 0\n",
|
||||
" \n",
|
||||
" economie = prix_separe - prix_bestof\n",
|
||||
" \n",
|
||||
" return round(economie, 2)\n",
|
||||
"\n",
|
||||
"# Test\n",
|
||||
"for nom in menus_bestof.keys():\n",
|
||||
" eco = economie_bestof(nom, menu, menus_bestof)\n",
|
||||
" print(nom, \": economie de\", eco, \"euros\")"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"### 3.3 Statistiques par catégorie (4 pts)\n",
|
||||
"\n",
|
||||
"Écrivez une fonction `stats_menu(menu)` qui renvoie des statistiques pour chaque catégorie : nombre d'articles, prix moyen, calories moyennes."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"def stats_menu(menu):\n",
|
||||
" stats = {}\n",
|
||||
" \n",
|
||||
" for categorie, articles in menu.items():\n",
|
||||
" nb = len(articles)\n",
|
||||
" total_prix = 0\n",
|
||||
" total_cal = 0\n",
|
||||
" \n",
|
||||
" for nom, infos in articles.items():\n",
|
||||
" # Votre code ici : cumuler prix et calories\n",
|
||||
" pass\n",
|
||||
" \n",
|
||||
" stats[categorie] = {\n",
|
||||
" \"nb_articles\": nb,\n",
|
||||
" \"prix_moyen\": round(total_prix / nb, 2),\n",
|
||||
" \"calories_moyennes\": round(total_cal / nb)\n",
|
||||
" }\n",
|
||||
" \n",
|
||||
" return stats\n",
|
||||
"\n",
|
||||
"# Test\n",
|
||||
"print(\"Statistiques du menu :\")\n",
|
||||
"for cat, data in stats_menu(menu).items():\n",
|
||||
" print(\" \", cat, \":\")\n",
|
||||
" print(\" Articles :\", data[\"nb_articles\"])\n",
|
||||
" print(\" Prix moyen :\", data[\"prix_moyen\"], \"euros\")\n",
|
||||
" print(\" Calories moyennes :\", data[\"calories_moyennes\"])"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"kernelspec": {
|
||||
"display_name": "Python 3",
|
||||
"language": "python",
|
||||
"name": "python3"
|
||||
},
|
||||
"language_info": {
|
||||
"name": "python",
|
||||
"version": "3.9.0"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 4
|
||||
}
|
||||
@@ -1,282 +0,0 @@
|
||||
# Aide - TP08 McDonald's
|
||||
|
||||
## Rappels utiles
|
||||
|
||||
### Structure du menu (dictionnaire imbrique)
|
||||
```python
|
||||
# menu = {categorie: {article: {infos}}}
|
||||
menu = {
|
||||
"burgers": {
|
||||
"Big Mac": {"prix": 5.50, "calories": 540, "temps_prep": 3},
|
||||
"McChicken": {"prix": 4.90, "calories": 420, "temps_prep": 3}
|
||||
},
|
||||
"accompagnements": {...},
|
||||
"boissons": {...}
|
||||
}
|
||||
|
||||
# Acceder au prix du Big Mac
|
||||
prix = menu["burgers"]["Big Mac"]["prix"]
|
||||
|
||||
# Parcourir toutes les categories
|
||||
for categorie, articles in menu.items():
|
||||
for nom_article, infos in articles.items():
|
||||
print(nom_article, ":", infos["prix"], "euros")
|
||||
```
|
||||
|
||||
### Structure des commandes
|
||||
```python
|
||||
commande = {
|
||||
"id": 101,
|
||||
"items": [("Big Mac", 2), ("Frites (G)", 2)], # (article, quantite)
|
||||
"heure": "12:05"
|
||||
}
|
||||
|
||||
# Parcourir les items
|
||||
for article, quantite in commande["items"]:
|
||||
print(quantite, "x", article)
|
||||
```
|
||||
|
||||
### Trouver un article dans le menu
|
||||
```python
|
||||
def trouver_article(menu, nom):
|
||||
for categorie, articles in menu.items():
|
||||
if nom in articles:
|
||||
return articles[nom]
|
||||
return None
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Exercice 1
|
||||
|
||||
### 1.1 - Affichage du menu
|
||||
```python
|
||||
def afficher_menu(menu, categorie):
|
||||
if categorie in menu:
|
||||
print("===", categorie.upper(), "===")
|
||||
for nom, infos in menu[categorie].items():
|
||||
print(" ", nom, ":", infos["prix"], "euros (", infos["calories"], "cal)")
|
||||
```
|
||||
|
||||
### 1.2 - Recherche d'articles
|
||||
```python
|
||||
def rechercher_article(menu, nom_recherche):
|
||||
resultats = []
|
||||
nom_lower = nom_recherche.lower()
|
||||
|
||||
for categorie, articles in menu.items():
|
||||
for nom_article, infos in articles.items():
|
||||
if nom_lower in nom_article.lower():
|
||||
resultats.append({
|
||||
"nom": nom_article,
|
||||
"categorie": categorie,
|
||||
"prix": infos["prix"],
|
||||
"calories": infos["calories"]
|
||||
})
|
||||
|
||||
return resultats
|
||||
```
|
||||
|
||||
### 1.3 - Statistiques du menu
|
||||
```python
|
||||
def stats_menu(menu):
|
||||
tous_articles = []
|
||||
|
||||
for categorie, articles in menu.items():
|
||||
for nom, infos in articles.items():
|
||||
tous_articles.append({"nom": nom, "infos": infos})
|
||||
|
||||
# Prix moyen
|
||||
total_prix = 0
|
||||
for article in tous_articles:
|
||||
total_prix = total_prix + article["infos"]["prix"]
|
||||
prix_moyen = total_prix / len(tous_articles)
|
||||
|
||||
# Article le moins calorique
|
||||
min_cal = tous_articles[0]
|
||||
for article in tous_articles:
|
||||
if article["infos"]["calories"] < min_cal["infos"]["calories"]:
|
||||
min_cal = article
|
||||
|
||||
return {
|
||||
"prix_moyen": round(prix_moyen, 2),
|
||||
"article_moins_calorique": min_cal["nom"]
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Exercice 2
|
||||
|
||||
### 2.1 - Calculer le prix
|
||||
```python
|
||||
def calculer_prix(commande, menu, menus_bestof):
|
||||
total = 0
|
||||
|
||||
for article, qte in commande["items"]:
|
||||
# Verifier si c'est un Best-Of
|
||||
if article in menus_bestof:
|
||||
total = total + menus_bestof[article]["prix"] * qte
|
||||
else:
|
||||
# Chercher dans le menu normal
|
||||
for categorie, articles in menu.items():
|
||||
if article in articles:
|
||||
total = total + articles[article]["prix"] * qte
|
||||
break
|
||||
|
||||
return total
|
||||
```
|
||||
|
||||
### 2.2 - Temps de preparation
|
||||
```python
|
||||
def temps_preparation(commande, menu, menus_bestof):
|
||||
temps_par_categorie = {}
|
||||
|
||||
for article, qte in commande["items"]:
|
||||
if article in menus_bestof:
|
||||
# Best-Of = burger + frites + boisson
|
||||
# Ajouter le temps du burger (le plus long)
|
||||
temps_par_categorie["burgers"] = max(
|
||||
temps_par_categorie.get("burgers", 0), 3
|
||||
)
|
||||
else:
|
||||
# Trouver la categorie et le temps
|
||||
for categorie, articles in menu.items():
|
||||
if article in articles:
|
||||
temps = articles[article]["temps_prep"]
|
||||
# Garder le max par categorie (preparation parallele)
|
||||
temps_par_categorie[categorie] = max(
|
||||
temps_par_categorie.get(categorie, 0), temps
|
||||
)
|
||||
break
|
||||
|
||||
# Additionner les temps des differentes categories
|
||||
total = 0
|
||||
for temps in temps_par_categorie.values():
|
||||
total = total + temps
|
||||
return total
|
||||
```
|
||||
|
||||
### 2.3 - Calories totales
|
||||
```python
|
||||
def calories_commande(commande, menu, menus_bestof):
|
||||
total_calories = 0
|
||||
|
||||
for article, qte in commande["items"]:
|
||||
if article in menus_bestof:
|
||||
total_calories = total_calories + menus_bestof[article]["calories"] * qte
|
||||
else:
|
||||
for categorie, articles in menu.items():
|
||||
if article in articles:
|
||||
total_calories = total_calories + articles[article]["calories"] * qte
|
||||
break
|
||||
|
||||
return total_calories
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Exercice 3 (Bonus)
|
||||
|
||||
### 3.1 - Ticket de caisse
|
||||
```python
|
||||
def generer_ticket(commande, menu, menus_bestof):
|
||||
lignes = []
|
||||
lignes.append("=" * 30)
|
||||
lignes.append("COMMANDE #" + str(commande["id"]))
|
||||
lignes.append("Heure: " + commande["heure"])
|
||||
lignes.append("-" * 30)
|
||||
|
||||
total = 0
|
||||
for article, qte in commande["items"]:
|
||||
# Trouver le prix
|
||||
prix = 0
|
||||
if article in menus_bestof:
|
||||
prix = menus_bestof[article]["prix"]
|
||||
else:
|
||||
for cat, articles in menu.items():
|
||||
if article in articles:
|
||||
prix = articles[article]["prix"]
|
||||
break
|
||||
|
||||
sous_total = prix * qte
|
||||
total = total + sous_total
|
||||
lignes.append(str(qte) + "x " + article + " : " + str(sous_total) + " euros")
|
||||
|
||||
lignes.append("-" * 30)
|
||||
lignes.append("TOTAL: " + str(total) + " euros")
|
||||
lignes.append("=" * 30)
|
||||
|
||||
return "\n".join(lignes)
|
||||
```
|
||||
|
||||
### 3.2 - Repas optimal
|
||||
```python
|
||||
def repas_optimal(menu, budget, calories_max):
|
||||
meilleur_repas = None
|
||||
meilleur_score = -1
|
||||
|
||||
for burger_nom, burger in menu["burgers"].items():
|
||||
for accomp_nom, accomp in menu["accompagnements"].items():
|
||||
for boisson_nom, boisson in menu["boissons"].items():
|
||||
prix = burger["prix"] + accomp["prix"] + boisson["prix"]
|
||||
calories = burger["calories"] + accomp["calories"] + boisson["calories"]
|
||||
|
||||
if prix <= budget and calories <= calories_max:
|
||||
# Score = satisfaction / prix
|
||||
satisfaction = 100 - calories / 10
|
||||
score = satisfaction / prix
|
||||
|
||||
if score > meilleur_score:
|
||||
meilleur_score = score
|
||||
meilleur_repas = {
|
||||
"burger": burger_nom,
|
||||
"accompagnement": accomp_nom,
|
||||
"boisson": boisson_nom,
|
||||
"prix_total": prix,
|
||||
"calories_total": calories
|
||||
}
|
||||
|
||||
return meilleur_repas
|
||||
```
|
||||
|
||||
### 3.3 - Analyse de la file
|
||||
```python
|
||||
def analyser_file(commandes, menu, menus_bestof):
|
||||
chiffre_affaires = 0
|
||||
|
||||
# Compter les articles
|
||||
compteur_articles = {}
|
||||
|
||||
for cmd in commandes:
|
||||
chiffre_affaires = chiffre_affaires + calculer_prix(cmd, menu, menus_bestof)
|
||||
|
||||
for article, qte in cmd["items"]:
|
||||
if article not in compteur_articles:
|
||||
compteur_articles[article] = 0
|
||||
compteur_articles[article] = compteur_articles[article] + qte
|
||||
|
||||
# Trouver l'article le plus commande
|
||||
article_star = None
|
||||
max_qte = 0
|
||||
for article, qte in compteur_articles.items():
|
||||
if qte > max_qte:
|
||||
article_star = article
|
||||
max_qte = qte
|
||||
|
||||
return {
|
||||
"nb_commandes": len(commandes),
|
||||
"chiffre_affaires": chiffre_affaires,
|
||||
"article_plus_commande": article_star
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Pieges a eviter
|
||||
|
||||
1. **Best-Of vs articles individuels** : verifiez d'abord si l'article est un Best-Of avant de chercher dans le menu
|
||||
2. **Temps de preparation** : meme categorie = parallele (max), categories differentes = sequentiel (somme)
|
||||
3. **Prix avec decimales** : utilisez round() pour arrondir
|
||||
4. **Quantites** : n'oubliez pas de multiplier par la quantite !
|
||||
5. **Articles avec tailles** : "Frites (M)" et "Frites (G)" sont des articles differents
|
||||
@@ -1,559 +0,0 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"# TP Évaluation - Statistiques Fortnite\n",
|
||||
"\n",
|
||||
"**Durée : 1h30**\n",
|
||||
"\n",
|
||||
"**Nom :** \n",
|
||||
"\n",
|
||||
"**Prénom :**\n",
|
||||
"\n",
|
||||
"---\n",
|
||||
"\n",
|
||||
"Dans ce TP, vous allez analyser des statistiques de joueurs Fortnite.\n",
|
||||
"\n",
|
||||
"**Compétences évaluées :**\n",
|
||||
"- Dictionnaires imbriqués\n",
|
||||
"- Algorithmes de calcul statistique\n",
|
||||
"- Filtrage et tri de données"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Données initiales\n",
|
||||
"\n",
|
||||
"**Exécutez cette cellule avant de commencer.**"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Statistiques des joueurs\n",
|
||||
"joueurs = {\n",
|
||||
" \"NinjaMaster\": {\n",
|
||||
" \"niveau\": 250,\n",
|
||||
" \"vbucks\": 3500,\n",
|
||||
" \"stats\": {\n",
|
||||
" \"solo\": {\"parties\": 450, \"victoires\": 89, \"kills\": 2340},\n",
|
||||
" \"duo\": {\"parties\": 320, \"victoires\": 65, \"kills\": 1890},\n",
|
||||
" \"squad\": {\"parties\": 280, \"victoires\": 72, \"kills\": 1650}\n",
|
||||
" },\n",
|
||||
" \"inventaire\": [\"Pioche Spectrale\", \"Planeur Dragon\", \"Skin Raven\"]\n",
|
||||
" },\n",
|
||||
" \"BuilderPro\": {\n",
|
||||
" \"niveau\": 180,\n",
|
||||
" \"vbucks\": 1200,\n",
|
||||
" \"stats\": {\n",
|
||||
" \"solo\": {\"parties\": 280, \"victoires\": 42, \"kills\": 1120},\n",
|
||||
" \"duo\": {\"parties\": 450, \"victoires\": 98, \"kills\": 2450},\n",
|
||||
" \"squad\": {\"parties\": 380, \"victoires\": 110, \"kills\": 2100}\n",
|
||||
" },\n",
|
||||
" \"inventaire\": [\"Pioche Arc-en-ciel\", \"Skin Drift\"]\n",
|
||||
" },\n",
|
||||
" \"SniperElite\": {\n",
|
||||
" \"niveau\": 320,\n",
|
||||
" \"vbucks\": 8900,\n",
|
||||
" \"stats\": {\n",
|
||||
" \"solo\": {\"parties\": 680, \"victoires\": 156, \"kills\": 4200},\n",
|
||||
" \"duo\": {\"parties\": 220, \"victoires\": 45, \"kills\": 980},\n",
|
||||
" \"squad\": {\"parties\": 150, \"victoires\": 28, \"kills\": 620}\n",
|
||||
" },\n",
|
||||
" \"inventaire\": [\"Pioche Galaxy\", \"Planeur Meteore\", \"Skin Black Knight\", \"Skin Omega\"]\n",
|
||||
" },\n",
|
||||
" \"CasualGamer\": {\n",
|
||||
" \"niveau\": 85,\n",
|
||||
" \"vbucks\": 500,\n",
|
||||
" \"stats\": {\n",
|
||||
" \"solo\": {\"parties\": 120, \"victoires\": 8, \"kills\": 180},\n",
|
||||
" \"duo\": {\"parties\": 200, \"victoires\": 22, \"kills\": 420},\n",
|
||||
" \"squad\": {\"parties\": 350, \"victoires\": 45, \"kills\": 680}\n",
|
||||
" },\n",
|
||||
" \"inventaire\": [\"Skin Default\", \"Pioche Standard\"]\n",
|
||||
" },\n",
|
||||
" \"StreamerKing\": {\n",
|
||||
" \"niveau\": 450,\n",
|
||||
" \"vbucks\": 25000,\n",
|
||||
" \"stats\": {\n",
|
||||
" \"solo\": {\"parties\": 1200, \"victoires\": 312, \"kills\": 8900},\n",
|
||||
" \"duo\": {\"parties\": 800, \"victoires\": 245, \"kills\": 5600},\n",
|
||||
" \"squad\": {\"parties\": 600, \"victoires\": 198, \"kills\": 4200}\n",
|
||||
" },\n",
|
||||
" \"inventaire\": [\"Pioche Galaxy\", \"Skin Skull Trooper\", \"Skin Ghoul Trooper\", \"Planeur Dragon\", \"Skin Renegade Raider\"]\n",
|
||||
" }\n",
|
||||
"}\n",
|
||||
"\n",
|
||||
"# Boutique du jour\n",
|
||||
"boutique = [\n",
|
||||
" {\"nom\": \"Skin Crystal\", \"type\": \"skin\", \"rarete\": \"rare\", \"prix\": 1200},\n",
|
||||
" {\"nom\": \"Skin Aura\", \"type\": \"skin\", \"rarete\": \"uncommon\", \"prix\": 800},\n",
|
||||
" {\"nom\": \"Skin Raptor\", \"type\": \"skin\", \"rarete\": \"legendary\", \"prix\": 2000},\n",
|
||||
" {\"nom\": \"Pioche Laser\", \"type\": \"pioche\", \"rarete\": \"rare\", \"prix\": 800},\n",
|
||||
" {\"nom\": \"Pioche Feu\", \"type\": \"pioche\", \"rarete\": \"uncommon\", \"prix\": 500},\n",
|
||||
" {\"nom\": \"Planeur Etoile\", \"type\": \"planeur\", \"rarete\": \"epic\", \"prix\": 1200},\n",
|
||||
" {\"nom\": \"Emote Dance\", \"type\": \"emote\", \"rarete\": \"rare\", \"prix\": 500}\n",
|
||||
"]\n",
|
||||
"\n",
|
||||
"# Historique des parties recentes\n",
|
||||
"parties_recentes = [\n",
|
||||
" {\"joueur\": \"NinjaMaster\", \"mode\": \"solo\", \"placement\": 1, \"kills\": 8},\n",
|
||||
" {\"joueur\": \"NinjaMaster\", \"mode\": \"solo\", \"placement\": 15, \"kills\": 3},\n",
|
||||
" {\"joueur\": \"BuilderPro\", \"mode\": \"duo\", \"placement\": 1, \"kills\": 6},\n",
|
||||
" {\"joueur\": \"SniperElite\", \"mode\": \"solo\", \"placement\": 1, \"kills\": 12},\n",
|
||||
" {\"joueur\": \"SniperElite\", \"mode\": \"solo\", \"placement\": 3, \"kills\": 7},\n",
|
||||
" {\"joueur\": \"CasualGamer\", \"mode\": \"squad\", \"placement\": 8, \"kills\": 2},\n",
|
||||
" {\"joueur\": \"StreamerKing\", \"mode\": \"solo\", \"placement\": 1, \"kills\": 15},\n",
|
||||
" {\"joueur\": \"StreamerKing\", \"mode\": \"duo\", \"placement\": 1, \"kills\": 9},\n",
|
||||
" {\"joueur\": \"BuilderPro\", \"mode\": \"squad\", \"placement\": 2, \"kills\": 5}\n",
|
||||
"]"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"---\n",
|
||||
"\n",
|
||||
"## Exercice 1 - Analyse des profils (25 min)\n",
|
||||
"\n",
|
||||
"### 1.1 Affichage de profil (4 pts)\n",
|
||||
"\n",
|
||||
"Écrivez une fonction `afficher_profil(pseudo, joueurs)` qui affiche le profil d'un joueur.\n",
|
||||
"\n",
|
||||
"Exemple :\n",
|
||||
"```\n",
|
||||
"=== NinjaMaster ===\n",
|
||||
"Niveau : 250 | V-Bucks : 3500\n",
|
||||
"Inventaire : 3 items\n",
|
||||
"```"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"def afficher_profil(pseudo, joueurs):\n",
|
||||
" if pseudo not in joueurs:\n",
|
||||
" print(\"Joueur non trouve\")\n",
|
||||
" return\n",
|
||||
" \n",
|
||||
" profil = joueurs[pseudo]\n",
|
||||
" \n",
|
||||
" # Votre code ici : afficher le pseudo, niveau, vbucks et nb d'items\n",
|
||||
" pass\n",
|
||||
"\n",
|
||||
"# Test\n",
|
||||
"afficher_profil(\"NinjaMaster\", joueurs)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"### 1.2 Statistiques globales (4 pts)\n",
|
||||
"\n",
|
||||
"Écrivez une fonction `stats_globales(pseudo, joueurs)` qui calcule pour un joueur :\n",
|
||||
"- `parties_totales` : somme de toutes les parties\n",
|
||||
"- `victoires_totales` : somme de toutes les victoires\n",
|
||||
"- `kills_totaux` : somme de tous les kills\n",
|
||||
"- `winrate` : pourcentage de victoires (arrondi à 2 décimales)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"def stats_globales(pseudo, joueurs):\n",
|
||||
" profil = joueurs[pseudo]\n",
|
||||
" stats = profil[\"stats\"]\n",
|
||||
" \n",
|
||||
" parties_totales = 0\n",
|
||||
" victoires_totales = 0\n",
|
||||
" kills_totaux = 0\n",
|
||||
" \n",
|
||||
" for mode, data in stats.items():\n",
|
||||
" # Votre code ici : cumuler parties, victoires et kills\n",
|
||||
" pass\n",
|
||||
" \n",
|
||||
" # Calculer le winrate\n",
|
||||
" # Votre code ici\n",
|
||||
" winrate = 0\n",
|
||||
" \n",
|
||||
" return {\n",
|
||||
" \"parties_totales\": parties_totales,\n",
|
||||
" \"victoires_totales\": victoires_totales,\n",
|
||||
" \"kills_totaux\": kills_totaux,\n",
|
||||
" \"winrate\": winrate\n",
|
||||
" }\n",
|
||||
"\n",
|
||||
"# Test\n",
|
||||
"stats = stats_globales(\"SniperElite\", joueurs)\n",
|
||||
"print(\"Stats de SniperElite :\")\n",
|
||||
"print(\" Parties :\", stats[\"parties_totales\"])\n",
|
||||
"print(\" Victoires :\", stats[\"victoires_totales\"])\n",
|
||||
"print(\" Kills :\", stats[\"kills_totaux\"])\n",
|
||||
"print(\" Winrate :\", stats[\"winrate\"], \"%\")"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"### 1.3 Mode préféré (4 pts)\n",
|
||||
"\n",
|
||||
"Écrivez une fonction `mode_prefere(pseudo, joueurs)` qui renvoie le mode de jeu (solo, duo, squad) où le joueur a joué le plus de parties."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"def mode_prefere(pseudo, joueurs):\n",
|
||||
" profil = joueurs[pseudo]\n",
|
||||
" stats = profil[\"stats\"]\n",
|
||||
" \n",
|
||||
" meilleur_mode = None\n",
|
||||
" max_parties = 0\n",
|
||||
" \n",
|
||||
" for mode, data in stats.items():\n",
|
||||
" # Votre code ici\n",
|
||||
" pass\n",
|
||||
" \n",
|
||||
" return meilleur_mode\n",
|
||||
"\n",
|
||||
"# Test\n",
|
||||
"for pseudo in joueurs:\n",
|
||||
" print(pseudo, \"prefere le mode\", mode_prefere(pseudo, joueurs))"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"---\n",
|
||||
"\n",
|
||||
"## Exercice 2 - Classements et boutique (35 min)\n",
|
||||
"\n",
|
||||
"### 2.1 Classement par critère (6 pts)\n",
|
||||
"\n",
|
||||
"Écrivez une fonction `classement(joueurs, critere)` qui renvoie la liste des pseudos triés selon le critère.\n",
|
||||
"\n",
|
||||
"Critères possibles : `\"niveau\"`, `\"victoires\"`, `\"kills\"`, `\"winrate\"`\n",
|
||||
"\n",
|
||||
"*Aide : créez d'abord une liste de tuples (pseudo, valeur), triez-la, puis extrayez les pseudos.*"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"def classement(joueurs, critere):\n",
|
||||
" # Creer une liste de tuples (pseudo, valeur)\n",
|
||||
" liste = []\n",
|
||||
" \n",
|
||||
" for pseudo in joueurs:\n",
|
||||
" if critere == \"niveau\":\n",
|
||||
" valeur = joueurs[pseudo][\"niveau\"]\n",
|
||||
" elif critere == \"victoires\":\n",
|
||||
" stats = stats_globales(pseudo, joueurs)\n",
|
||||
" valeur = stats[\"victoires_totales\"]\n",
|
||||
" elif critere == \"kills\":\n",
|
||||
" stats = stats_globales(pseudo, joueurs)\n",
|
||||
" valeur = stats[\"kills_totaux\"]\n",
|
||||
" elif critere == \"winrate\":\n",
|
||||
" stats = stats_globales(pseudo, joueurs)\n",
|
||||
" valeur = stats[\"winrate\"]\n",
|
||||
" else:\n",
|
||||
" valeur = 0\n",
|
||||
" \n",
|
||||
" liste.append((pseudo, valeur))\n",
|
||||
" \n",
|
||||
" # Trier par valeur decroissante\n",
|
||||
" # Votre code ici\n",
|
||||
" pass\n",
|
||||
" \n",
|
||||
" # Extraire les pseudos\n",
|
||||
" resultat = []\n",
|
||||
" for item in liste:\n",
|
||||
" # Votre code ici\n",
|
||||
" pass\n",
|
||||
" \n",
|
||||
" return resultat\n",
|
||||
"\n",
|
||||
"# Tests\n",
|
||||
"print(\"Par niveau :\", classement(joueurs, \"niveau\"))\n",
|
||||
"print(\"Par victoires :\", classement(joueurs, \"victoires\"))\n",
|
||||
"print(\"Par winrate :\", classement(joueurs, \"winrate\"))"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"### 2.2 Articles achetables (5 pts)\n",
|
||||
"\n",
|
||||
"Écrivez une fonction `articles_achetables(pseudo, joueurs, boutique)` qui renvoie la liste des articles que le joueur peut acheter avec ses V-Bucks.\n",
|
||||
"\n",
|
||||
"Exclure les articles déjà possédés dans l'inventaire."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"def articles_achetables(pseudo, joueurs, boutique):\n",
|
||||
" profil = joueurs[pseudo]\n",
|
||||
" vbucks = profil[\"vbucks\"]\n",
|
||||
" inventaire = profil[\"inventaire\"]\n",
|
||||
" \n",
|
||||
" achetables = []\n",
|
||||
" \n",
|
||||
" for article in boutique:\n",
|
||||
" # Verifier le prix et si pas deja possede\n",
|
||||
" # Votre code ici\n",
|
||||
" pass\n",
|
||||
" \n",
|
||||
" return achetables\n",
|
||||
"\n",
|
||||
"# Test\n",
|
||||
"print(\"Articles achetables pour BuilderPro :\")\n",
|
||||
"for art in articles_achetables(\"BuilderPro\", joueurs, boutique):\n",
|
||||
" print(\" \", art[\"nom\"], \"-\", art[\"prix\"], \"V-Bucks\")"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"### 2.3 Comparaison de joueurs (6 pts)\n",
|
||||
"\n",
|
||||
"Écrivez une fonction `comparer_joueurs(pseudo1, pseudo2, joueurs)` qui compare deux joueurs.\n",
|
||||
"\n",
|
||||
"Renvoie un dictionnaire indiquant pour chaque critère (niveau, victoires, kills, winrate) quel joueur est meilleur."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"def comparer_joueurs(pseudo1, pseudo2, joueurs):\n",
|
||||
" stats1 = stats_globales(pseudo1, joueurs)\n",
|
||||
" stats2 = stats_globales(pseudo2, joueurs)\n",
|
||||
" \n",
|
||||
" comparaison = {}\n",
|
||||
" \n",
|
||||
" # Comparer le niveau\n",
|
||||
" # Votre code ici\n",
|
||||
" pass\n",
|
||||
" \n",
|
||||
" # Comparer les victoires\n",
|
||||
" # Votre code ici\n",
|
||||
" pass\n",
|
||||
" \n",
|
||||
" # Comparer les kills\n",
|
||||
" # Votre code ici\n",
|
||||
" pass\n",
|
||||
" \n",
|
||||
" # Comparer le winrate\n",
|
||||
" # Votre code ici\n",
|
||||
" pass\n",
|
||||
" \n",
|
||||
" return comparaison\n",
|
||||
"\n",
|
||||
"# Test\n",
|
||||
"comp = comparer_joueurs(\"NinjaMaster\", \"SniperElite\", joueurs)\n",
|
||||
"print(\"Comparaison NinjaMaster vs SniperElite :\")\n",
|
||||
"for critere, gagnant in comp.items():\n",
|
||||
" print(\" \", critere, \":\", gagnant)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"### 2.4 Joueur le plus riche (5 pts)\n",
|
||||
"\n",
|
||||
"Écrivez une fonction `plus_riche(joueurs)` qui renvoie le pseudo du joueur ayant le plus de V-Bucks."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"def plus_riche(joueurs):\n",
|
||||
" meilleur = None\n",
|
||||
" max_vbucks = 0\n",
|
||||
" \n",
|
||||
" for pseudo, profil in joueurs.items():\n",
|
||||
" # Votre code ici\n",
|
||||
" pass\n",
|
||||
" \n",
|
||||
" return meilleur\n",
|
||||
"\n",
|
||||
"# Test\n",
|
||||
"riche = plus_riche(joueurs)\n",
|
||||
"print(\"Joueur le plus riche :\", riche)\n",
|
||||
"if riche:\n",
|
||||
" print(\"V-Bucks :\", joueurs[riche][\"vbucks\"])"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"---\n",
|
||||
"\n",
|
||||
"## Exercice 3 - Bonus (20 min)\n",
|
||||
"\n",
|
||||
"### 3.1 Performances récentes (5 pts)\n",
|
||||
"\n",
|
||||
"Écrivez une fonction `performances_recentes(pseudo, parties)` qui analyse les parties récentes d'un joueur.\n",
|
||||
"\n",
|
||||
"Renvoie : `nb_parties`, `victoires`, `kills_moyen` (arrondi à 1 décimale)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"def performances_recentes(pseudo, parties):\n",
|
||||
" nb_parties = 0\n",
|
||||
" victoires = 0\n",
|
||||
" total_kills = 0\n",
|
||||
" \n",
|
||||
" for partie in parties:\n",
|
||||
" if partie[\"joueur\"] == pseudo:\n",
|
||||
" # Votre code ici\n",
|
||||
" pass\n",
|
||||
" \n",
|
||||
" if nb_parties > 0:\n",
|
||||
" kills_moyen = round(total_kills / nb_parties, 1)\n",
|
||||
" else:\n",
|
||||
" kills_moyen = 0\n",
|
||||
" \n",
|
||||
" return {\n",
|
||||
" \"nb_parties\": nb_parties,\n",
|
||||
" \"victoires\": victoires,\n",
|
||||
" \"kills_moyen\": kills_moyen\n",
|
||||
" }\n",
|
||||
"\n",
|
||||
"# Test\n",
|
||||
"for pseudo in [\"NinjaMaster\", \"SniperElite\", \"StreamerKing\"]:\n",
|
||||
" perf = performances_recentes(pseudo, parties_recentes)\n",
|
||||
" print(pseudo, \":\", perf[\"victoires\"], \"/\", perf[\"nb_parties\"], \"victoires, \", perf[\"kills_moyen\"], \"kills/partie\")"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"### 3.2 K/D Ratio (4 pts)\n",
|
||||
"\n",
|
||||
"Écrivez une fonction `kd_ratio(pseudo, joueurs)` qui calcule le ratio kills/deaths.\n",
|
||||
"\n",
|
||||
"Deaths = parties - victoires (on meurt une fois par partie perdue)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"def kd_ratio(pseudo, joueurs):\n",
|
||||
" stats = stats_globales(pseudo, joueurs)\n",
|
||||
" \n",
|
||||
" kills = stats[\"kills_totaux\"]\n",
|
||||
" deaths = stats[\"parties_totales\"] - stats[\"victoires_totales\"]\n",
|
||||
" \n",
|
||||
" # Votre code ici : calculer le ratio (attention division par zero)\n",
|
||||
" ratio = 0\n",
|
||||
" \n",
|
||||
" return ratio\n",
|
||||
"\n",
|
||||
"# Test\n",
|
||||
"print(\"K/D Ratio :\")\n",
|
||||
"for pseudo in joueurs:\n",
|
||||
" print(\" \", pseudo, \":\", kd_ratio(pseudo, joueurs))"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"### 3.3 Items les plus possédés (5 pts)\n",
|
||||
"\n",
|
||||
"Écrivez une fonction `items_populaires(joueurs)` qui compte combien de joueurs possèdent chaque item et renvoie la liste triée par popularité décroissante.\n",
|
||||
"\n",
|
||||
"Renvoie une liste de tuples `(nom_item, nb_joueurs)`."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"def items_populaires(joueurs):\n",
|
||||
" compteur = {}\n",
|
||||
" \n",
|
||||
" for pseudo, profil in joueurs.items():\n",
|
||||
" for item in profil[\"inventaire\"]:\n",
|
||||
" # Votre code ici : incrementer le compteur\n",
|
||||
" pass\n",
|
||||
" \n",
|
||||
" # Convertir en liste de tuples et trier\n",
|
||||
" liste = []\n",
|
||||
" for item, nb in compteur.items():\n",
|
||||
" liste.append((item, nb))\n",
|
||||
" \n",
|
||||
" # Votre code ici : trier par nb decroissant\n",
|
||||
" pass\n",
|
||||
" \n",
|
||||
" return liste\n",
|
||||
"\n",
|
||||
"# Test\n",
|
||||
"print(\"Items les plus possedes :\")\n",
|
||||
"for item, nb in items_populaires(joueurs):\n",
|
||||
" print(\" \", item, \":\", nb, \"joueur(s)\")"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"kernelspec": {
|
||||
"display_name": "Python 3",
|
||||
"language": "python",
|
||||
"name": "python3"
|
||||
},
|
||||
"language_info": {
|
||||
"name": "python",
|
||||
"version": "3.9.0"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 4
|
||||
}
|
||||
@@ -1,339 +0,0 @@
|
||||
# Aide - TP09 Fortnite
|
||||
|
||||
## Rappels utiles
|
||||
|
||||
### Structure des joueurs (dictionnaire imbrique)
|
||||
```python
|
||||
joueurs = {
|
||||
"NinjaMaster": {
|
||||
"niveau": 250,
|
||||
"vbucks": 3500,
|
||||
"stats": {
|
||||
"solo": {"parties": 450, "victoires": 89, "kills": 2340, "top10": 180},
|
||||
"duo": {"parties": 320, "victoires": 65, "kills": 1890, "top5": 110},
|
||||
"squad": {"parties": 280, "victoires": 72, "kills": 1650, "top3": 95}
|
||||
},
|
||||
"inventaire": ["Pioche Spectrale", "Planeur Dragon"]
|
||||
}
|
||||
}
|
||||
|
||||
# Acceder aux stats solo d'un joueur
|
||||
solo = joueurs["NinjaMaster"]["stats"]["solo"]
|
||||
victoires_solo = solo["victoires"]
|
||||
|
||||
# Parcourir tous les joueurs
|
||||
for pseudo, profil in joueurs.items():
|
||||
print(pseudo, ": niveau", profil["niveau"])
|
||||
```
|
||||
|
||||
### Structure de la boutique
|
||||
```python
|
||||
boutique = {
|
||||
"skins": [
|
||||
{"nom": "Skin Crystal", "rarete": "rare", "prix": 1200},
|
||||
{"nom": "Skin Phoenix", "rarete": "epique", "prix": 1500}
|
||||
],
|
||||
"pioches": [...],
|
||||
"planeurs": [...]
|
||||
}
|
||||
|
||||
# Parcourir toutes les categories
|
||||
for categorie, articles in boutique.items():
|
||||
for article in articles:
|
||||
print(article["nom"], ":", article["prix"], "V-Bucks")
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Exercice 1
|
||||
|
||||
### 1.1 - Affichage de profil
|
||||
```python
|
||||
def afficher_profil(pseudo, joueurs):
|
||||
if pseudo not in joueurs:
|
||||
print("Joueur non trouve")
|
||||
return
|
||||
|
||||
profil = joueurs[pseudo]
|
||||
print("===", pseudo, "===")
|
||||
print("Niveau:", profil["niveau"])
|
||||
print("V-Bucks:", profil["vbucks"])
|
||||
print()
|
||||
print("Statistiques:")
|
||||
for mode, stats in profil["stats"].items():
|
||||
print(" ", mode, ":", stats["victoires"], "victoires /", stats["parties"], "parties")
|
||||
```
|
||||
|
||||
### 1.2 - Statistiques globales
|
||||
```python
|
||||
def stats_globales(pseudo, joueurs):
|
||||
profil = joueurs[pseudo]
|
||||
stats = profil["stats"]
|
||||
|
||||
# Calculer les totaux
|
||||
parties = 0
|
||||
victoires = 0
|
||||
kills = 0
|
||||
|
||||
for mode, s in stats.items():
|
||||
parties = parties + s["parties"]
|
||||
victoires = victoires + s["victoires"]
|
||||
kills = kills + s["kills"]
|
||||
|
||||
# Winrate
|
||||
if parties > 0:
|
||||
winrate = round(victoires * 100 / parties, 2)
|
||||
else:
|
||||
winrate = 0
|
||||
|
||||
# KD = kills / morts, morts = parties - victoires
|
||||
morts = parties - victoires
|
||||
if morts > 0:
|
||||
kd = round(kills / morts, 2)
|
||||
else:
|
||||
kd = kills
|
||||
|
||||
# Mode prefere = celui avec le plus de parties
|
||||
mode_prefere = None
|
||||
max_parties = 0
|
||||
for mode, s in stats.items():
|
||||
if s["parties"] > max_parties:
|
||||
mode_prefere = mode
|
||||
max_parties = s["parties"]
|
||||
|
||||
return {
|
||||
"parties_totales": parties,
|
||||
"victoires_totales": victoires,
|
||||
"kills_totaux": kills,
|
||||
"winrate": winrate,
|
||||
"kd_ratio": kd,
|
||||
"mode_prefere": mode_prefere
|
||||
}
|
||||
```
|
||||
|
||||
### 1.3 - Classement des joueurs
|
||||
```python
|
||||
def classement(joueurs, critere):
|
||||
liste_joueurs = []
|
||||
|
||||
if critere == "niveau":
|
||||
for pseudo, profil in joueurs.items():
|
||||
liste_joueurs.append((pseudo, profil["niveau"]))
|
||||
liste_joueurs = sorted(liste_joueurs, key=lambda x: x[1], reverse=True)
|
||||
|
||||
elif critere == "victoires":
|
||||
for pseudo, profil in joueurs.items():
|
||||
total_victoires = 0
|
||||
for mode, s in profil["stats"].items():
|
||||
total_victoires = total_victoires + s["victoires"]
|
||||
liste_joueurs.append((pseudo, total_victoires))
|
||||
liste_joueurs = sorted(liste_joueurs, key=lambda x: x[1], reverse=True)
|
||||
|
||||
# Renvoyer juste les pseudos
|
||||
pseudos = []
|
||||
for pseudo, valeur in liste_joueurs:
|
||||
pseudos.append(pseudo)
|
||||
return pseudos
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Exercice 2
|
||||
|
||||
### 2.1 - Articles achetables
|
||||
```python
|
||||
def articles_achetables(pseudo, joueurs, boutique):
|
||||
budget = joueurs[pseudo]["vbucks"]
|
||||
inventaire = joueurs[pseudo]["inventaire"]
|
||||
|
||||
achetables = []
|
||||
for categorie, articles in boutique.items():
|
||||
for article in articles:
|
||||
if article["prix"] <= budget and article["nom"] not in inventaire:
|
||||
achetables.append(article)
|
||||
|
||||
return achetables
|
||||
```
|
||||
|
||||
### 2.2 - Panier optimise
|
||||
```python
|
||||
def panier_optimal(pseudo, joueurs, boutique, priorites):
|
||||
budget = joueurs[pseudo]["vbucks"]
|
||||
inventaire = joueurs[pseudo]["inventaire"]
|
||||
panier = []
|
||||
|
||||
for categorie in priorites:
|
||||
if categorie not in boutique:
|
||||
continue
|
||||
|
||||
# Trier par prix croissant pour maximiser le nombre d'achats
|
||||
articles = sorted(boutique[categorie], key=lambda a: a["prix"])
|
||||
|
||||
for article in articles:
|
||||
if article["nom"] not in inventaire and article["prix"] <= budget:
|
||||
panier.append(article)
|
||||
budget = budget - article["prix"]
|
||||
|
||||
return panier, budget
|
||||
```
|
||||
|
||||
### 2.3 - Analyse des inventaires
|
||||
```python
|
||||
def analyser_inventaires(joueurs):
|
||||
# Compter les occurrences de chaque item
|
||||
compteur = {}
|
||||
for pseudo, profil in joueurs.items():
|
||||
for item in profil["inventaire"]:
|
||||
if item not in compteur:
|
||||
compteur[item] = 0
|
||||
compteur[item] = compteur[item] + 1
|
||||
|
||||
# Items communs (possedes par plusieurs joueurs)
|
||||
items_communs = []
|
||||
for item, count in compteur.items():
|
||||
if count >= 2:
|
||||
items_communs.append(item)
|
||||
|
||||
# Items rares (possedes par un seul joueur)
|
||||
items_rares = []
|
||||
for item, count in compteur.items():
|
||||
if count == 1:
|
||||
items_rares.append(item)
|
||||
|
||||
# Collectionneur (le plus d'items)
|
||||
collectionneur = None
|
||||
max_items = 0
|
||||
for pseudo, profil in joueurs.items():
|
||||
if len(profil["inventaire"]) > max_items:
|
||||
collectionneur = pseudo
|
||||
max_items = len(profil["inventaire"])
|
||||
|
||||
return {
|
||||
"items_communs": items_communs,
|
||||
"items_rares": items_rares,
|
||||
"joueur_collectionneur": collectionneur
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Exercice 3 (Bonus)
|
||||
|
||||
### 3.1 - Performances recentes
|
||||
```python
|
||||
def performances_recentes(pseudo, parties):
|
||||
# Filtrer les parties du joueur
|
||||
mes_parties = []
|
||||
for p in parties:
|
||||
if p["joueur"] == pseudo:
|
||||
mes_parties.append(p)
|
||||
|
||||
if len(mes_parties) == 0:
|
||||
return None
|
||||
|
||||
# Calculer les statistiques
|
||||
victoires = 0
|
||||
total_kills = 0
|
||||
total_degats = 0
|
||||
total_duree = 0
|
||||
|
||||
for p in mes_parties:
|
||||
if p["placement"] == 1:
|
||||
victoires = victoires + 1
|
||||
total_kills = total_kills + p["kills"]
|
||||
total_degats = total_degats + p["degats"]
|
||||
total_duree = total_duree + p["duree"]
|
||||
|
||||
kills_moyen = round(total_kills / len(mes_parties), 1)
|
||||
degats_moyens = round(total_degats / len(mes_parties))
|
||||
duree_moyenne = round(total_duree / len(mes_parties))
|
||||
|
||||
# Meilleure partie
|
||||
meilleure = mes_parties[0]
|
||||
for p in mes_parties:
|
||||
if p["kills"] > meilleure["kills"]:
|
||||
meilleure = p
|
||||
|
||||
return {
|
||||
"nb_parties": len(mes_parties),
|
||||
"victoires": victoires,
|
||||
"kills_moyen": kills_moyen,
|
||||
"degats_moyens": degats_moyens,
|
||||
"duree_moyenne": duree_moyenne,
|
||||
"meilleure_partie": meilleure
|
||||
}
|
||||
```
|
||||
|
||||
### 3.2 - Comparaison de joueurs
|
||||
```python
|
||||
def comparer_joueurs(pseudo1, pseudo2, joueurs):
|
||||
stats1 = stats_globales(pseudo1, joueurs)
|
||||
stats2 = stats_globales(pseudo2, joueurs)
|
||||
|
||||
comparaison = {}
|
||||
|
||||
# Comparer les stats
|
||||
if stats1["kills_totaux"] > stats2["kills_totaux"]:
|
||||
comparaison["kills"] = pseudo1
|
||||
else:
|
||||
comparaison["kills"] = pseudo2
|
||||
|
||||
if stats1["winrate"] > stats2["winrate"]:
|
||||
comparaison["winrate"] = pseudo1
|
||||
else:
|
||||
comparaison["winrate"] = pseudo2
|
||||
|
||||
if stats1["kd_ratio"] > stats2["kd_ratio"]:
|
||||
comparaison["kd"] = pseudo1
|
||||
else:
|
||||
comparaison["kd"] = pseudo2
|
||||
|
||||
return comparaison
|
||||
```
|
||||
|
||||
### 3.3 - Prediction de rang
|
||||
```python
|
||||
def calculer_rang(pseudo, joueurs):
|
||||
stats = stats_globales(pseudo, joueurs)
|
||||
profil = joueurs[pseudo]
|
||||
|
||||
# Winrate solo
|
||||
solo = profil["stats"]["solo"]
|
||||
if solo["parties"] > 0:
|
||||
winrate_solo = solo["victoires"] * 100 / solo["parties"]
|
||||
else:
|
||||
winrate_solo = 0
|
||||
|
||||
# Calcul des points
|
||||
points = 0
|
||||
points = points + winrate_solo * 3
|
||||
points = points + stats["kd_ratio"] * 50
|
||||
points = points + stats["victoires_totales"] * 0.1
|
||||
points = points + profil["niveau"] * 0.05
|
||||
|
||||
# Attribution du rang
|
||||
if points >= 100:
|
||||
rang = "Champion"
|
||||
elif points >= 70:
|
||||
rang = "Diamond"
|
||||
elif points >= 50:
|
||||
rang = "Platinum"
|
||||
elif points >= 30:
|
||||
rang = "Gold"
|
||||
elif points >= 15:
|
||||
rang = "Silver"
|
||||
else:
|
||||
rang = "Bronze"
|
||||
|
||||
return rang, round(points)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Pieges a eviter
|
||||
|
||||
1. **KD ratio** : attention a la division par zero ! `morts = parties - victoires` peut etre 0
|
||||
2. **Stats par mode** : solo a "top10", duo a "top5", squad a "top3"
|
||||
3. **Inventaire = liste de strings** : utilisez `in` pour verifier si un item est possede
|
||||
4. **V-Bucks** : ne pas oublier de soustraire apres chaque achat
|
||||
5. **Parties recentes** : filtrer d'abord par joueur avant de calculer les stats
|
||||
@@ -1,541 +0,0 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"# TP Évaluation - Planification de Voyage\n",
|
||||
"\n",
|
||||
"**Durée : 1h30**\n",
|
||||
"\n",
|
||||
"**Nom :** \n",
|
||||
"\n",
|
||||
"**Prénom :**\n",
|
||||
"\n",
|
||||
"---\n",
|
||||
"\n",
|
||||
"Dans ce TP de synthèse, vous allez créer un système de planification de voyage.\n",
|
||||
"\n",
|
||||
"**Compétences évaluées :**\n",
|
||||
"- Listes de tuples et dictionnaires\n",
|
||||
"- Filtrage et tri de données\n",
|
||||
"- Algorithmes de recherche"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Données initiales\n",
|
||||
"\n",
|
||||
"**Exécutez cette cellule avant de commencer.**"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Base de donnees des villes\n",
|
||||
"# Chaque ville : (nom, pays, langue, monnaie, decalage_horaire)\n",
|
||||
"villes = [\n",
|
||||
" (\"Paris\", \"France\", \"Francais\", \"EUR\", 0),\n",
|
||||
" (\"Londres\", \"Royaume-Uni\", \"Anglais\", \"GBP\", 0),\n",
|
||||
" (\"New York\", \"Etats-Unis\", \"Anglais\", \"USD\", -6),\n",
|
||||
" (\"Tokyo\", \"Japon\", \"Japonais\", \"JPY\", 8),\n",
|
||||
" (\"Barcelone\", \"Espagne\", \"Espagnol\", \"EUR\", 0),\n",
|
||||
" (\"Rome\", \"Italie\", \"Italien\", \"EUR\", 0),\n",
|
||||
" (\"Amsterdam\", \"Pays-Bas\", \"Neerlandais\", \"EUR\", 0),\n",
|
||||
" (\"Berlin\", \"Allemagne\", \"Allemand\", \"EUR\", 0),\n",
|
||||
" (\"Dubai\", \"Emirats Arabes Unis\", \"Arabe\", \"AED\", 3),\n",
|
||||
" (\"Sydney\", \"Australie\", \"Anglais\", \"AUD\", 9)\n",
|
||||
"]\n",
|
||||
"\n",
|
||||
"# Base de donnees des hotels\n",
|
||||
"# Chaque hotel est un dictionnaire\n",
|
||||
"hotels = [\n",
|
||||
" {\"nom\": \"Le Marais Boutique\", \"ville\": \"Paris\", \"etoiles\": 3, \"prix_nuit\": 120, \"note\": 8.5},\n",
|
||||
" {\"nom\": \"Paris Luxury Palace\", \"ville\": \"Paris\", \"etoiles\": 5, \"prix_nuit\": 450, \"note\": 9.2},\n",
|
||||
" {\"nom\": \"Eiffel Budget\", \"ville\": \"Paris\", \"etoiles\": 2, \"prix_nuit\": 65, \"note\": 7.1},\n",
|
||||
" {\"nom\": \"London Central\", \"ville\": \"Londres\", \"etoiles\": 4, \"prix_nuit\": 180, \"note\": 8.8},\n",
|
||||
" {\"nom\": \"Westminster Inn\", \"ville\": \"Londres\", \"etoiles\": 3, \"prix_nuit\": 95, \"note\": 7.9},\n",
|
||||
" {\"nom\": \"Manhattan View\", \"ville\": \"New York\", \"etoiles\": 4, \"prix_nuit\": 220, \"note\": 8.6},\n",
|
||||
" {\"nom\": \"Times Square Budget\", \"ville\": \"New York\", \"etoiles\": 2, \"prix_nuit\": 89, \"note\": 6.8},\n",
|
||||
" {\"nom\": \"Tokyo Garden\", \"ville\": \"Tokyo\", \"etoiles\": 4, \"prix_nuit\": 150, \"note\": 9.0},\n",
|
||||
" {\"nom\": \"Shibuya Capsule\", \"ville\": \"Tokyo\", \"etoiles\": 1, \"prix_nuit\": 35, \"note\": 7.5},\n",
|
||||
" {\"nom\": \"Barcelona Beach\", \"ville\": \"Barcelone\", \"etoiles\": 4, \"prix_nuit\": 140, \"note\": 8.7},\n",
|
||||
" {\"nom\": \"Roma Antica\", \"ville\": \"Rome\", \"etoiles\": 3, \"prix_nuit\": 110, \"note\": 8.3},\n",
|
||||
" {\"nom\": \"Canal House\", \"ville\": \"Amsterdam\", \"etoiles\": 3, \"prix_nuit\": 130, \"note\": 8.4},\n",
|
||||
" {\"nom\": \"Berlin Modern\", \"ville\": \"Berlin\", \"etoiles\": 3, \"prix_nuit\": 85, \"note\": 8.1},\n",
|
||||
" {\"nom\": \"Burj Luxury\", \"ville\": \"Dubai\", \"etoiles\": 5, \"prix_nuit\": 380, \"note\": 9.4},\n",
|
||||
" {\"nom\": \"Sydney Harbour\", \"ville\": \"Sydney\", \"etoiles\": 4, \"prix_nuit\": 200, \"note\": 8.9}\n",
|
||||
"]\n",
|
||||
"\n",
|
||||
"# Base de donnees des vols (depuis Paris)\n",
|
||||
"# Chaque vol : (compagnie, depart, arrivee, prix, escales)\n",
|
||||
"vols = [\n",
|
||||
" (\"Air France\", \"Paris\", \"Londres\", 120, 0),\n",
|
||||
" (\"EasyJet\", \"Paris\", \"Londres\", 65, 0),\n",
|
||||
" (\"Air France\", \"Paris\", \"New York\", 480, 0),\n",
|
||||
" (\"Delta\", \"Paris\", \"New York\", 420, 0),\n",
|
||||
" (\"United\", \"Paris\", \"New York\", 350, 1),\n",
|
||||
" (\"JAL\", \"Paris\", \"Tokyo\", 750, 0),\n",
|
||||
" (\"Air France\", \"Paris\", \"Tokyo\", 680, 0),\n",
|
||||
" (\"ANA\", \"Paris\", \"Tokyo\", 620, 1),\n",
|
||||
" (\"Vueling\", \"Paris\", \"Barcelone\", 85, 0),\n",
|
||||
" (\"Air France\", \"Paris\", \"Barcelone\", 130, 0),\n",
|
||||
" (\"Alitalia\", \"Paris\", \"Rome\", 110, 0),\n",
|
||||
" (\"EasyJet\", \"Paris\", \"Rome\", 75, 0),\n",
|
||||
" (\"KLM\", \"Paris\", \"Amsterdam\", 95, 0),\n",
|
||||
" (\"Lufthansa\", \"Paris\", \"Berlin\", 110, 0),\n",
|
||||
" (\"Emirates\", \"Paris\", \"Dubai\", 450, 0),\n",
|
||||
" (\"Qantas\", \"Paris\", \"Sydney\", 980, 1),\n",
|
||||
" (\"Emirates\", \"Paris\", \"Sydney\", 1100, 1)\n",
|
||||
"]\n",
|
||||
"\n",
|
||||
"# Activites par ville\n",
|
||||
"activites = {\n",
|
||||
" \"Paris\": [\n",
|
||||
" {\"nom\": \"Tour Eiffel\", \"prix\": 26, \"duree\": 2, \"type\": \"monument\"},\n",
|
||||
" {\"nom\": \"Louvre\", \"prix\": 17, \"duree\": 4, \"type\": \"musee\"},\n",
|
||||
" {\"nom\": \"Croisiere Seine\", \"prix\": 15, \"duree\": 1, \"type\": \"excursion\"}\n",
|
||||
" ],\n",
|
||||
" \"Londres\": [\n",
|
||||
" {\"nom\": \"British Museum\", \"prix\": 0, \"duree\": 3, \"type\": \"musee\"},\n",
|
||||
" {\"nom\": \"London Eye\", \"prix\": 32, \"duree\": 1, \"type\": \"attraction\"},\n",
|
||||
" {\"nom\": \"Tower of London\", \"prix\": 28, \"duree\": 2, \"type\": \"monument\"}\n",
|
||||
" ],\n",
|
||||
" \"New York\": [\n",
|
||||
" {\"nom\": \"Statue of Liberty\", \"prix\": 24, \"duree\": 4, \"type\": \"monument\"},\n",
|
||||
" {\"nom\": \"Empire State Building\", \"prix\": 44, \"duree\": 2, \"type\": \"monument\"},\n",
|
||||
" {\"nom\": \"Broadway Show\", \"prix\": 150, \"duree\": 3, \"type\": \"spectacle\"}\n",
|
||||
" ],\n",
|
||||
" \"Tokyo\": [\n",
|
||||
" {\"nom\": \"Temple Senso-ji\", \"prix\": 0, \"duree\": 2, \"type\": \"monument\"},\n",
|
||||
" {\"nom\": \"Tokyo Skytree\", \"prix\": 20, \"duree\": 2, \"type\": \"attraction\"},\n",
|
||||
" {\"nom\": \"Robot Restaurant\", \"prix\": 80, \"duree\": 2, \"type\": \"spectacle\"}\n",
|
||||
" ],\n",
|
||||
" \"Barcelone\": [\n",
|
||||
" {\"nom\": \"Sagrada Familia\", \"prix\": 26, \"duree\": 2, \"type\": \"monument\"},\n",
|
||||
" {\"nom\": \"Parc Guell\", \"prix\": 10, \"duree\": 2, \"type\": \"parc\"},\n",
|
||||
" {\"nom\": \"Camp Nou\", \"prix\": 28, \"duree\": 2, \"type\": \"sport\"}\n",
|
||||
" ],\n",
|
||||
" \"Rome\": [\n",
|
||||
" {\"nom\": \"Colisee\", \"prix\": 16, \"duree\": 2, \"type\": \"monument\"},\n",
|
||||
" {\"nom\": \"Vatican\", \"prix\": 20, \"duree\": 4, \"type\": \"monument\"},\n",
|
||||
" {\"nom\": \"Fontaine de Trevi\", \"prix\": 0, \"duree\": 1, \"type\": \"monument\"}\n",
|
||||
" ]\n",
|
||||
"}"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"---\n",
|
||||
"\n",
|
||||
"## Exercice 1 - Exploration des données (25 min)\n",
|
||||
"\n",
|
||||
"### 1.1 Affichage d'une ville (4 pts)\n",
|
||||
"\n",
|
||||
"Écrivez une fonction `afficher_ville(ville)` qui affiche les informations d'une ville.\n",
|
||||
"\n",
|
||||
"Exemple :\n",
|
||||
"```\n",
|
||||
"Tokyo (Japon)\n",
|
||||
"Langue : Japonais | Monnaie : JPY\n",
|
||||
"Decalage horaire : +8h\n",
|
||||
"```\n",
|
||||
"\n",
|
||||
"*Rappel : ville[0] = nom, ville[1] = pays, ville[2] = langue, ville[3] = monnaie, ville[4] = decalage*"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"def afficher_ville(ville):\n",
|
||||
" nom = ville[0]\n",
|
||||
" pays = ville[1]\n",
|
||||
" langue = ville[2]\n",
|
||||
" monnaie = ville[3]\n",
|
||||
" decalage = ville[4]\n",
|
||||
" \n",
|
||||
" # Votre code ici : afficher les informations\n",
|
||||
" pass\n",
|
||||
"\n",
|
||||
"# Test\n",
|
||||
"afficher_ville(villes[3]) # Tokyo"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"### 1.2 Rechercher une ville (4 pts)\n",
|
||||
"\n",
|
||||
"Écrivez une fonction `rechercher_ville(nom, villes)` qui renvoie le tuple de la ville correspondante, ou `None` si non trouvée."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"def rechercher_ville(nom, villes):\n",
|
||||
" for ville in villes:\n",
|
||||
" # Votre code ici\n",
|
||||
" pass\n",
|
||||
" return None\n",
|
||||
"\n",
|
||||
"# Test\n",
|
||||
"v = rechercher_ville(\"Rome\", villes)\n",
|
||||
"if v:\n",
|
||||
" afficher_ville(v)\n",
|
||||
"print()\n",
|
||||
"print(\"Madrid :\", rechercher_ville(\"Madrid\", villes))"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"### 1.3 Villes par monnaie (4 pts)\n",
|
||||
"\n",
|
||||
"Écrivez une fonction `villes_par_monnaie(villes, monnaie)` qui renvoie la liste des noms de villes utilisant cette monnaie."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"def villes_par_monnaie(villes, monnaie):\n",
|
||||
" resultats = []\n",
|
||||
" \n",
|
||||
" for ville in villes:\n",
|
||||
" # Votre code ici\n",
|
||||
" pass\n",
|
||||
" \n",
|
||||
" return resultats\n",
|
||||
"\n",
|
||||
"# Test\n",
|
||||
"print(\"Villes en zone Euro :\", villes_par_monnaie(villes, \"EUR\"))"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"---\n",
|
||||
"\n",
|
||||
"## Exercice 2 - Recherche d'hôtels et vols (35 min)\n",
|
||||
"\n",
|
||||
"### 2.1 Hôtels dans une ville (5 pts)\n",
|
||||
"\n",
|
||||
"Écrivez une fonction `hotels_ville(ville, hotels)` qui renvoie la liste des hôtels d'une ville, triés par note décroissante."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"def hotels_ville(ville, hotels):\n",
|
||||
" resultats = []\n",
|
||||
" \n",
|
||||
" for hotel in hotels:\n",
|
||||
" # Votre code ici\n",
|
||||
" pass\n",
|
||||
" \n",
|
||||
" # Trier par note decroissante\n",
|
||||
" # Votre code ici\n",
|
||||
" pass\n",
|
||||
" \n",
|
||||
" return resultats\n",
|
||||
"\n",
|
||||
"# Test\n",
|
||||
"print(\"Hotels a Paris :\")\n",
|
||||
"for h in hotels_ville(\"Paris\", hotels):\n",
|
||||
" print(\" \", h[\"nom\"], \"-\", h[\"etoiles\"], \"etoiles -\", h[\"prix_nuit\"], \"euros/nuit - Note:\", h[\"note\"])"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"### 2.2 Vols vers une destination (5 pts)\n",
|
||||
"\n",
|
||||
"Écrivez une fonction `vols_vers(destination, vols)` qui renvoie la liste des vols vers cette destination, triés par prix croissant.\n",
|
||||
"\n",
|
||||
"*Rappel : vol[2] = arrivee, vol[3] = prix*"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"def vols_vers(destination, vols):\n",
|
||||
" resultats = []\n",
|
||||
" \n",
|
||||
" for vol in vols:\n",
|
||||
" # Votre code ici\n",
|
||||
" pass\n",
|
||||
" \n",
|
||||
" # Trier par prix croissant\n",
|
||||
" # Votre code ici\n",
|
||||
" pass\n",
|
||||
" \n",
|
||||
" return resultats\n",
|
||||
"\n",
|
||||
"# Test\n",
|
||||
"print(\"Vols vers Tokyo :\")\n",
|
||||
"for v in vols_vers(\"Tokyo\", vols):\n",
|
||||
" escales = \"direct\" if v[4] == 0 else str(v[4]) + \" escale(s)\"\n",
|
||||
" print(\" \", v[0], \":\", v[3], \"euros (\", escales, \")\")"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"### 2.3 Vol le moins cher (5 pts)\n",
|
||||
"\n",
|
||||
"Écrivez une fonction `vol_moins_cher(destination, vols, direct_seulement)` qui renvoie le vol le moins cher vers une destination.\n",
|
||||
"\n",
|
||||
"Si `direct_seulement` est `True`, ne considérer que les vols sans escale."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"def vol_moins_cher(destination, vols, direct_seulement):\n",
|
||||
" meilleur = None\n",
|
||||
" meilleur_prix = 999999\n",
|
||||
" \n",
|
||||
" for vol in vols:\n",
|
||||
" if vol[2] == destination:\n",
|
||||
" # Verifier si on veut que des vols directs\n",
|
||||
" if direct_seulement and vol[4] > 0:\n",
|
||||
" continue\n",
|
||||
" \n",
|
||||
" # Votre code ici : garder le vol le moins cher\n",
|
||||
" pass\n",
|
||||
" \n",
|
||||
" return meilleur\n",
|
||||
"\n",
|
||||
"# Tests\n",
|
||||
"vol = vol_moins_cher(\"New York\", vols, True)\n",
|
||||
"if vol:\n",
|
||||
" print(\"Vol direct le moins cher vers New York :\", vol[0], \"-\", vol[3], \"euros\")\n",
|
||||
"\n",
|
||||
"vol = vol_moins_cher(\"New York\", vols, False)\n",
|
||||
"if vol:\n",
|
||||
" print(\"Vol le moins cher vers New York (avec escales) :\", vol[0], \"-\", vol[3], \"euros\")"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"### 2.4 Budget hotel (6 pts)\n",
|
||||
"\n",
|
||||
"Écrivez une fonction `hotels_budget(ville, hotels, budget_max, etoiles_min)` qui renvoie les hôtels correspondant aux critères, triés par prix croissant."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"def hotels_budget(ville, hotels, budget_max, etoiles_min):\n",
|
||||
" resultats = []\n",
|
||||
" \n",
|
||||
" for hotel in hotels:\n",
|
||||
" # Verifier ville, budget et etoiles\n",
|
||||
" # Votre code ici\n",
|
||||
" pass\n",
|
||||
" \n",
|
||||
" # Trier par prix croissant\n",
|
||||
" # Votre code ici\n",
|
||||
" pass\n",
|
||||
" \n",
|
||||
" return resultats\n",
|
||||
"\n",
|
||||
"# Test\n",
|
||||
"print(\"Hotels a Paris, max 150 euros, min 3 etoiles :\")\n",
|
||||
"for h in hotels_budget(\"Paris\", hotels, 150, 3):\n",
|
||||
" print(\" \", h[\"nom\"], \"-\", h[\"prix_nuit\"], \"euros/nuit\")"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"---\n",
|
||||
"\n",
|
||||
"## Exercice 3 - Bonus (20 min)\n",
|
||||
"\n",
|
||||
"### 3.1 Calculer le budget voyage (5 pts)\n",
|
||||
"\n",
|
||||
"Écrivez une fonction `calculer_budget(destination, nuits, vol, hotel, activites_choisies, activites)` qui calcule le budget total.\n",
|
||||
"\n",
|
||||
"Budget = prix vol + (prix hotel × nuits) + somme des activités"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"def calculer_budget(destination, nuits, vol, hotel, activites_choisies, activites):\n",
|
||||
" budget = {}\n",
|
||||
" \n",
|
||||
" # Vol\n",
|
||||
" budget[\"vol\"] = vol[3]\n",
|
||||
" \n",
|
||||
" # Hotel\n",
|
||||
" budget[\"hotel\"] = hotel[\"prix_nuit\"] * nuits\n",
|
||||
" \n",
|
||||
" # Activites\n",
|
||||
" budget[\"activites\"] = 0\n",
|
||||
" if destination in activites:\n",
|
||||
" for act in activites[destination]:\n",
|
||||
" # Votre code ici : ajouter le prix si l'activite est choisie\n",
|
||||
" pass\n",
|
||||
" \n",
|
||||
" budget[\"total\"] = budget[\"vol\"] + budget[\"hotel\"] + budget[\"activites\"]\n",
|
||||
" \n",
|
||||
" return budget\n",
|
||||
"\n",
|
||||
"# Test\n",
|
||||
"vol_choisi = vols[6] # Air France Paris-Tokyo\n",
|
||||
"hotel_choisi = hotels[7] # Tokyo Garden\n",
|
||||
"acts = [\"Temple Senso-ji\", \"Tokyo Skytree\"]\n",
|
||||
"\n",
|
||||
"budget = calculer_budget(\"Tokyo\", 5, vol_choisi, hotel_choisi, acts, activites)\n",
|
||||
"print(\"Budget voyage Tokyo :\")\n",
|
||||
"for poste, montant in budget.items():\n",
|
||||
" print(\" \", poste, \":\", montant, \"euros\")"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"### 3.2 Activités gratuites (4 pts)\n",
|
||||
"\n",
|
||||
"Écrivez une fonction `activites_gratuites(activites)` qui renvoie la liste de toutes les activités gratuites (prix = 0).\n",
|
||||
"\n",
|
||||
"Renvoie une liste de dictionnaires `{\"ville\": ..., \"activite\": ...}`."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"def activites_gratuites(activites):\n",
|
||||
" gratuites = []\n",
|
||||
" \n",
|
||||
" for ville, liste_acts in activites.items():\n",
|
||||
" for act in liste_acts:\n",
|
||||
" # Votre code ici\n",
|
||||
" pass\n",
|
||||
" \n",
|
||||
" return gratuites\n",
|
||||
"\n",
|
||||
"# Test\n",
|
||||
"print(\"Activites gratuites :\")\n",
|
||||
"for a in activites_gratuites(activites):\n",
|
||||
" print(\" \", a[\"ville\"], \":\", a[\"activite\"])"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"### 3.3 Destination la moins chère (5 pts)\n",
|
||||
"\n",
|
||||
"Écrivez une fonction `destination_moins_chere(vols, hotels, nuits)` qui trouve la destination la moins chère (vol + hotel × nuits).\n",
|
||||
"\n",
|
||||
"Pour chaque destination, prendre le vol le moins cher et l'hotel le moins cher."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"def destination_moins_chere(vols, hotels, nuits):\n",
|
||||
" # Trouver toutes les destinations\n",
|
||||
" destinations = []\n",
|
||||
" for vol in vols:\n",
|
||||
" if vol[2] not in destinations:\n",
|
||||
" destinations.append(vol[2])\n",
|
||||
" \n",
|
||||
" meilleure = None\n",
|
||||
" meilleur_prix = 999999\n",
|
||||
" \n",
|
||||
" for dest in destinations:\n",
|
||||
" # Trouver le vol le moins cher\n",
|
||||
" vol = vol_moins_cher(dest, vols, False)\n",
|
||||
" if vol == None:\n",
|
||||
" continue\n",
|
||||
" \n",
|
||||
" # Trouver l'hotel le moins cher\n",
|
||||
" hotels_dest = hotels_ville(dest, hotels)\n",
|
||||
" if len(hotels_dest) == 0:\n",
|
||||
" continue\n",
|
||||
" \n",
|
||||
" hotel_min = hotels_dest[0]\n",
|
||||
" for h in hotels_dest:\n",
|
||||
" if h[\"prix_nuit\"] < hotel_min[\"prix_nuit\"]:\n",
|
||||
" hotel_min = h\n",
|
||||
" \n",
|
||||
" # Calculer le prix total\n",
|
||||
" # Votre code ici : mettre a jour meilleure si prix_total est inferieur\n",
|
||||
" prix_total = 0\n",
|
||||
" \n",
|
||||
" return meilleure\n",
|
||||
"\n",
|
||||
"# Test\n",
|
||||
"dest = destination_moins_chere(vols, hotels, 3)\n",
|
||||
"if dest:\n",
|
||||
" print(\"Destination la moins chere pour 3 nuits :\")\n",
|
||||
" print(\" Destination :\", dest[\"destination\"])\n",
|
||||
" print(\" Vol :\", dest[\"vol\"], \"-\", dest[\"prix_vol\"], \"euros\")\n",
|
||||
" print(\" Hotel :\", dest[\"hotel\"], \"-\", dest[\"prix_hotel\"], \"euros/nuit\")\n",
|
||||
" print(\" Total :\", dest[\"total\"], \"euros\")"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"kernelspec": {
|
||||
"display_name": "Python 3",
|
||||
"language": "python",
|
||||
"name": "python3"
|
||||
},
|
||||
"language_info": {
|
||||
"name": "python",
|
||||
"version": "3.9.0"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 4
|
||||
}
|
||||
@@ -1,336 +0,0 @@
|
||||
# Aide - TP10 Planification de Voyage
|
||||
|
||||
## Rappels utiles
|
||||
|
||||
### Structure des villes (tuples)
|
||||
```python
|
||||
# Ville = (nom, pays, langue, monnaie, decalage_horaire)
|
||||
ville = villes[0]
|
||||
nom = ville[0] # "Paris"
|
||||
pays = ville[1] # "France"
|
||||
langue = ville[2] # "Francais"
|
||||
monnaie = ville[3] # "EUR"
|
||||
decalage = ville[4] # 0
|
||||
|
||||
# Parcourir les villes
|
||||
for ville in villes:
|
||||
print(ville[0], "-", ville[1])
|
||||
```
|
||||
|
||||
### Structure des hotels (dictionnaires)
|
||||
```python
|
||||
hotels = {
|
||||
"Paris": [
|
||||
{"nom": "Hotel Lumiere", "etoiles": 4, "prix_nuit": 150, "services": ["wifi", "spa"], "note": 8.5},
|
||||
{"nom": "Petit Paris", "etoiles": 2, "prix_nuit": 65, "services": ["wifi"], "note": 7.2}
|
||||
],
|
||||
"Londres": [...]
|
||||
}
|
||||
|
||||
# Acceder aux hotels de Paris
|
||||
hotels_paris = hotels["Paris"]
|
||||
for h in hotels_paris:
|
||||
print(h["nom"], "-", h["prix_nuit"], "euros/nuit")
|
||||
```
|
||||
|
||||
### Structure des vols (tuples)
|
||||
```python
|
||||
# Vol = (compagnie, depart, arrivee, heure_depart, heure_arrivee, prix, escales)
|
||||
vol = vols[0]
|
||||
compagnie = vol[0] # "Air France"
|
||||
depart = vol[1] # "Paris"
|
||||
arrivee = vol[2] # "Londres"
|
||||
heure_dep = vol[3] # "08:00"
|
||||
heure_arr = vol[4] # "09:15"
|
||||
prix = vol[5] # 120
|
||||
escales = vol[6] # 0
|
||||
```
|
||||
|
||||
### Structure des activites (dictionnaires)
|
||||
```python
|
||||
activites = {
|
||||
"Paris": [
|
||||
{"nom": "Tour Eiffel", "duree": 3, "prix": 25, "type": "monument"},
|
||||
{"nom": "Louvre", "duree": 4, "prix": 17, "type": "musee"}
|
||||
]
|
||||
}
|
||||
|
||||
# Acceder aux activites d'une ville
|
||||
acts_paris = activites.get("Paris", []) # [] si la ville n'existe pas
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Exercice 1
|
||||
|
||||
### 1.1 - Fiche destination
|
||||
```python
|
||||
def fiche_destination(nom_ville, villes, hotels, vols):
|
||||
# Trouver la ville
|
||||
ville = None
|
||||
for v in villes:
|
||||
if v[0] == nom_ville:
|
||||
ville = v
|
||||
break
|
||||
|
||||
if ville == None:
|
||||
return "Ville non trouvee"
|
||||
|
||||
print("===", ville[0], "-", ville[1], "===")
|
||||
print("Langue:", ville[2])
|
||||
print("Monnaie:", ville[3])
|
||||
print("Decalage horaire:", ville[4], "h")
|
||||
|
||||
# Compter les hotels
|
||||
if nom_ville in hotels:
|
||||
nb_hotels = len(hotels[nom_ville])
|
||||
else:
|
||||
nb_hotels = 0
|
||||
print("Hotels disponibles:", nb_hotels)
|
||||
|
||||
# Compter les vols
|
||||
nb_vols = 0
|
||||
for vol in vols:
|
||||
if vol[2] == nom_ville: # arrivee
|
||||
nb_vols = nb_vols + 1
|
||||
print("Vols disponibles:", nb_vols)
|
||||
```
|
||||
|
||||
### 1.2 - Recherche de destinations
|
||||
```python
|
||||
def rechercher_destinations(villes, monnaie, decalage_max):
|
||||
resultats = []
|
||||
|
||||
for ville in villes:
|
||||
# Verifier la monnaie
|
||||
if monnaie is not None and ville[3] != monnaie:
|
||||
continue
|
||||
|
||||
# Verifier le decalage horaire
|
||||
if decalage_max is not None and abs(ville[4]) > decalage_max:
|
||||
continue
|
||||
|
||||
resultats.append(ville)
|
||||
|
||||
return resultats
|
||||
```
|
||||
|
||||
### 1.3 - Statistiques
|
||||
```python
|
||||
def stats_base(villes, hotels, vols):
|
||||
# Prix moyen des hotels
|
||||
total_prix_hotels = 0
|
||||
nb_hotels = 0
|
||||
for ville, liste_hotels in hotels.items():
|
||||
for h in liste_hotels:
|
||||
total_prix_hotels = total_prix_hotels + h["prix_nuit"]
|
||||
nb_hotels = nb_hotels + 1
|
||||
|
||||
if nb_hotels > 0:
|
||||
prix_hotel_moyen = total_prix_hotels / nb_hotels
|
||||
else:
|
||||
prix_hotel_moyen = 0
|
||||
|
||||
# Prix moyen des vols
|
||||
total_prix_vols = 0
|
||||
for vol in vols:
|
||||
total_prix_vols = total_prix_vols + vol[5]
|
||||
|
||||
if len(vols) > 0:
|
||||
prix_vol_moyen = total_prix_vols / len(vols)
|
||||
else:
|
||||
prix_vol_moyen = 0
|
||||
|
||||
return {
|
||||
"nb_destinations": len(villes),
|
||||
"nb_hotels": nb_hotels,
|
||||
"nb_vols": len(vols),
|
||||
"prix_hotel_moyen": round(prix_hotel_moyen, 2),
|
||||
"prix_vol_moyen": round(prix_vol_moyen, 2)
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Exercice 2
|
||||
|
||||
### 2.1 - Trouver les meilleurs vols
|
||||
```python
|
||||
def trouver_vols(vols, destination, critere):
|
||||
# Filtrer les vols vers la destination
|
||||
vols_dest = []
|
||||
for v in vols:
|
||||
if v[2] == destination:
|
||||
vols_dest.append(v)
|
||||
|
||||
if critere == "prix":
|
||||
vols_dest = sorted(vols_dest, key=lambda v: v[5])
|
||||
|
||||
elif critere == "direct":
|
||||
# Direct d'abord (escales = 0), puis par prix
|
||||
vols_dest = sorted(vols_dest, key=lambda v: (v[6], v[5]))
|
||||
|
||||
return vols_dest
|
||||
```
|
||||
|
||||
### 2.2 - Trouver l'hotel ideal
|
||||
```python
|
||||
def trouver_hotel(hotels, ville, budget_nuit, services_requis, etoiles_min):
|
||||
if ville not in hotels:
|
||||
return []
|
||||
|
||||
resultats = []
|
||||
for h in hotels[ville]:
|
||||
# Verifier le budget
|
||||
if budget_nuit is not None and h["prix_nuit"] > budget_nuit:
|
||||
continue
|
||||
|
||||
# Verifier les etoiles
|
||||
if etoiles_min is not None and h["etoiles"] < etoiles_min:
|
||||
continue
|
||||
|
||||
# Verifier les services
|
||||
if services_requis is not None:
|
||||
a_tous_services = True
|
||||
for service in services_requis:
|
||||
if service not in h["services"]:
|
||||
a_tous_services = False
|
||||
break
|
||||
if not a_tous_services:
|
||||
continue
|
||||
|
||||
resultats.append(h)
|
||||
|
||||
# Trier par note decroissante
|
||||
resultats = sorted(resultats, key=lambda h: h["note"], reverse=True)
|
||||
return resultats
|
||||
```
|
||||
|
||||
### 2.3 - Planifier les activites
|
||||
```python
|
||||
def planifier_activites(ville, activites, jours, budget_max):
|
||||
if ville not in activites:
|
||||
return {"planning": [], "budget_utilise": 0}
|
||||
|
||||
acts_ville = activites[ville]
|
||||
|
||||
# Trier par note ou popularite (ici par prix croissant comme exemple)
|
||||
acts_triees = sorted(acts_ville, key=lambda a: a["prix"])
|
||||
|
||||
planning = []
|
||||
budget_utilise = 0
|
||||
|
||||
for act in acts_triees:
|
||||
if budget_utilise + act["prix"] <= budget_max:
|
||||
planning.append(act)
|
||||
budget_utilise = budget_utilise + act["prix"]
|
||||
|
||||
return {
|
||||
"planning": planning,
|
||||
"budget_utilise": budget_utilise
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Exercice 3 (Bonus)
|
||||
|
||||
### 3.1 - Calculer le budget total
|
||||
```python
|
||||
def calculer_budget(vol, hotel, nuits, activites_choisies, activites, ville):
|
||||
budget = {
|
||||
"vol": vol[5],
|
||||
"hotel": hotel["prix_nuit"] * nuits,
|
||||
"activites": 0
|
||||
}
|
||||
|
||||
if ville in activites:
|
||||
for act in activites[ville]:
|
||||
if act["nom"] in activites_choisies:
|
||||
budget["activites"] = budget["activites"] + act["prix"]
|
||||
|
||||
budget["total"] = budget["vol"] + budget["hotel"] + budget["activites"]
|
||||
return budget
|
||||
```
|
||||
|
||||
### 3.2 - Voyage optimal
|
||||
```python
|
||||
def voyage_optimal(destination, budget_max, nuits, villes, hotels, vols):
|
||||
# Trouver les vols
|
||||
vols_dest = []
|
||||
for v in vols:
|
||||
if v[2] == destination:
|
||||
vols_dest.append(v)
|
||||
|
||||
if len(vols_dest) == 0:
|
||||
return None
|
||||
|
||||
# Trouver les hotels
|
||||
if destination not in hotels:
|
||||
return None
|
||||
hotels_dest = hotels[destination]
|
||||
|
||||
# Trier par prix
|
||||
vols_dest = sorted(vols_dest, key=lambda v: v[5])
|
||||
hotels_dest = sorted(hotels_dest, key=lambda h: h["prix_nuit"])
|
||||
|
||||
# Essayer les combinaisons
|
||||
for vol in vols_dest:
|
||||
for hotel in hotels_dest:
|
||||
cout_base = vol[5] + hotel["prix_nuit"] * nuits
|
||||
|
||||
if cout_base <= budget_max:
|
||||
return {
|
||||
"destination": destination,
|
||||
"vol": vol,
|
||||
"hotel": hotel,
|
||||
"budget_total": cout_base
|
||||
}
|
||||
|
||||
return None
|
||||
```
|
||||
|
||||
### 3.3 - Comparateur de destinations
|
||||
```python
|
||||
def comparer_destinations(destinations, budget, nuits, villes, hotels, vols, activites):
|
||||
comparaison = []
|
||||
|
||||
for dest in destinations:
|
||||
voyage = voyage_optimal(dest, budget, nuits, villes, hotels, vols)
|
||||
|
||||
if voyage != None:
|
||||
# Compter les activites possibles
|
||||
budget_restant = budget - voyage["budget_total"]
|
||||
nb_acts = 0
|
||||
if dest in activites:
|
||||
for act in activites[dest]:
|
||||
if act["prix"] <= budget_restant:
|
||||
nb_acts = nb_acts + 1
|
||||
|
||||
# Score = note hotel + nb activites possibles
|
||||
score = voyage["hotel"]["note"] + nb_acts * 0.5
|
||||
|
||||
comparaison.append({
|
||||
"ville": dest,
|
||||
"budget": voyage["budget_total"],
|
||||
"note_hotel": voyage["hotel"]["note"],
|
||||
"nb_activites": nb_acts,
|
||||
"score": score
|
||||
})
|
||||
|
||||
# Trier par score decroissant
|
||||
comparaison = sorted(comparaison, key=lambda x: x["score"], reverse=True)
|
||||
return comparaison
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Pieges a eviter
|
||||
|
||||
1. **Tuples immutables** : impossible de modifier `vol[5] = 100`
|
||||
2. **Services = liste** : utilisez `in` pour verifier si un service est disponible
|
||||
3. **Escales** : 0 = vol direct, > 0 = avec escale(s)
|
||||
4. **Decalage horaire** : peut etre negatif (New York = -6)
|
||||
5. **Activites par ville** : utilisez `.get(ville, [])` pour eviter KeyError si ville sans activites
|
||||
6. **Budget** : vol + (hotel x nuits) + activites
|
||||
7. **Acces par indice pour les tuples** : ville[0]=nom, ville[1]=pays, vol[5]=prix, etc.
|
||||
Reference in New Issue
Block a user