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
|
# Vidéos
|
||||||
*.webm
|
*.webm
|
||||||
AMELIORATIONS.md
|
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