{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "f39da861",
   "metadata": {},
   "source": [
    "# ICS - Série 5\n",
    "\n",
    "08.10.25\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "bb279251",
   "metadata": {},
   "source": [
    "# Exercice 1 : qu'affiche ce code\n",
    "\n",
    "Essayez de prédire la sortie de programmes ci-dessous. N'hésitez pas à changer les valeurs et tester différents paramètres ! "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "7de5de46",
   "metadata": {},
   "outputs": [],
   "source": [
    "print(\"pas de surprise\")\n",
    "L1 = [1, 2]\n",
    "L2 = [3, 4]\n",
    "L = L1 + L2\n",
    "L1.append(5)\n",
    "print(L1, L2)\n",
    "print(L)\n",
    "\n",
    "print(\"***********************\")\n",
    "print(\"!!ATTENTION!!\")\n",
    "t1 = ([1], [2])\n",
    "t2 = ([3], [4])\n",
    "t = t1 + t2\n",
    "t1[1].append(5)\n",
    "print(t1, t2)\n",
    "print(t)\n",
    "# essayez aussi avec deux listes de listes L1 et L2 au lieu des tuples t1 et t2"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "7580062d",
   "metadata": {},
   "outputs": [],
   "source": [
    "print(\"pas de surprise\")\n",
    "L = [1]\n",
    "L1 = L * 2\n",
    "print(L1)\n",
    "L.pop()\n",
    "print(L, L1)\n",
    "\n",
    "print(\"***********************\")\n",
    "print(\"!!ATTENTION!!\")\n",
    "L = [[1]] #essayez aussi avec un tuple t = ([1],)\n",
    "L1 = L * 2\n",
    "print(L1)\n",
    "L[0].pop()\n",
    "print(L1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "fc7b0779",
   "metadata": {},
   "outputs": [],
   "source": [
    "print(\"pas de surprise\")\n",
    "L = [10, 20, 30]\n",
    "L1 = L.copy()\n",
    "print(L, L1)\n",
    "L1[1] = 50\n",
    "L.append(40)\n",
    "print(L, L1)\n",
    "\n",
    "print(\"***********************\")\n",
    "print(\"!!ATTENTION!!\")\n",
    "\n",
    "L = [[10], [20], [30]]\n",
    "L1 = L.copy()\n",
    "print(L, L1)\n",
    "L1[1] = 50\n",
    "L[0].append(40)\n",
    "print(L, L1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "525ddd99",
   "metadata": {},
   "outputs": [],
   "source": [
    "L = [x for x in range(11)]\n",
    "print(L)\n",
    "L1 = [x for x in range(11) if x % 3 == 0]\n",
    "print(L1)\n",
    "L2 = [x for x in L1 if x % 2 == 0]\n",
    "print(L2)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "bbedc73a",
   "metadata": {},
   "outputs": [],
   "source": [
    "L = [y/2 for y in range(4)]\n",
    "print(L)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "9916e421",
   "metadata": {},
   "outputs": [],
   "source": [
    "print([x*2 for x in \"hello\"])\n",
    "print()\n",
    "print([x + y for x in \"hello\" for y in \"!\"])\n",
    "print()\n",
    "print([x for x in \"hello\" if x > \"g\"])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "d1ec9a8d",
   "metadata": {},
   "outputs": [],
   "source": [
    "d1 = {i:[] for i in range(10, 25, 4)}\n",
    "d1[14].append(3)\n",
    "\n",
    "print(d1)\n",
    "\n",
    "# attention à la mutabilité!\n",
    "L = []\n",
    "d2 = {i:L for i in range(10, 25, 4)}\n",
    "d2[14].append(3)\n",
    "\n",
    "print(d2)\n",
    "\n",
    "\n",
    "print(id(d1[10]) == id(d1[14]))\n",
    "print(id(d2[10]) == id(d2[14]))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "ab657709",
   "metadata": {},
   "outputs": [],
   "source": [
    "d = {10:\"a\", 20:\"b\", 30:\"c\"}\n",
    "for i in range(20, 50, 10):\n",
    "    d[i] = \"d\"\n",
    "print(d)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "fe6c24aa",
   "metadata": {},
   "outputs": [],
   "source": [
    "d = {\"nom\": \"Hercule Poirot\", \"section\": \"CMS\", \"notes\":[4, 4.5, 3.5]}\n",
    "\n",
    "d[\"notes\"].extend([5, 5.5, 4.5])\n",
    "print(d[\"notes\"])\n",
    "print(d.get(\"notes\"))\n",
    "\n",
    "print(\"\\n************************\")\n",
    "\n",
    "d1 = {\"nom\": \"S. Dubuis\", \"section\": \"CMS\", \"notes\":[6, 6, 6, 6]}\n",
    "print(d1.get(\"adresse\"))\n",
    "s = 0\n",
    "for x in d1[\"notes\"]:\n",
    "    s += x\n",
    "print(s/len(d1[\"notes\"]))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "eb8b8669",
   "metadata": {},
   "outputs": [],
   "source": [
    "d = {\"x\": 23, \"y\": 23, \"z\": 54}\n",
    "\n",
    "for c in d:\n",
    "    print(c, d[c])\n",
    "    \n",
    "print(\"************************************************\")\n",
    "for c in d.keys():\n",
    "    print(c, d[c])\n",
    "    \n",
    "print(\"************************************************\")\n",
    "for v in d.values():\n",
    "    print(v)\n",
    "    \n",
    "print(\"************************************************\")\n",
    "for c, v in d.items():\n",
    "    print(c, v)\n",
    "    \n",
    "print(\"************************************************\")\n",
    "for v in d.values():\n",
    "    for c in d:\n",
    "        if d[c] == v:\n",
    "            print(c, v)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "5c0f4f4d",
   "metadata": {},
   "outputs": [],
   "source": [
    "d1 = {x**2:x for x in range(-1, -10, -2)}\n",
    "print(d1)\n",
    "\n",
    "t = (1, 3, 5, 7)\n",
    "d2 = {t[i]:t[i] for i in range(len(t))}\n",
    "print(d2)\n",
    "\n",
    "d3 = {t[i]:t[i+1] for i in range(len(t)-1)}\n",
    "print(d3)\n",
    "\n",
    "L = [10, 23, 14, 22, 19, 26]\n",
    "d4 = {i:2*i for i in L if i % 2 == 0}\n",
    "print(d4)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "b5f4715e",
   "metadata": {},
   "outputs": [],
   "source": [
    "d = {}\n",
    "for x in \"hi\":\n",
    "    for y in \"ha\":\n",
    "        print(\"on insère\", x, \":\", y)\n",
    "        d[x] = y\n",
    "        \n",
    "print(d)\n",
    "\n",
    "d2 = {x:y for x in \"hi\" for y in \"ha\"}\n",
    "print(d2)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "6641a15f",
   "metadata": {},
   "source": [
    "## Exercice 2: compréhensions de listes \n",
    "\n",
    "Voici quelques fonctions que vous avez implémentées à la série 4 à l'aide de boucles `for` et de la méthode `append`. Cette fois, implémentez-les avec des compréhensions de listes.\n",
    "\n",
    "**(a)** Ecrivez une fonction qui prend en entrée un entier `n` positif et qui retourne la liste contenant les nombres `1, 2, ... n`.\n",
    "\n",
    "**(b)** Ecrivez une fonction qui prend en entrée une liste `L` de nombres et retourne une liste `L1` contenant uniquement les éléments pairs de `L`.\n",
    "\n",
    "**(c)** Ecrivez une fonction `list_intersection` qui prend en entrée deux listes `L1` et `L2` et retourne une liste `L` contenant l'intersection de `L1` et `L2`, c'est-à-dire les éléments présents dans les deux listes. Par exemple, l'appel `list_intersection([1, 3, 5], [2, 3])` doit retourner la liste `[3]`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "2b120ef4",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "id": "79dcbd83",
   "metadata": {},
   "source": [
    "# Exercice 3: opérations de dictionnaire\n",
    "\n",
    "Effectuez la suite d'instructions suivantes (en affichant le dictionnaire chaque fois que vous le jugez nécessaire):\n",
    "\n",
    "- Créez un dictionnaire vide `d`.\n",
    "- Insérez dans `d` les paires `(clé, valeur)` suivantes: `(\"arbre\":0)`, `(\"pomme\":1)`, `(\"avion\":2)`, `(\"lune\":3)`, `(\"mer\":4)`, `(\"oiseau\":5)`.\n",
    "- Remplacez la valeur associée à la clé `\"pomme\"` par `10` et la valeur associée à la clé `\"avion\"` par `20`.\n",
    "- Affichez toutes les valeurs du dictionnaire.\n",
    "- Supprimez du dictionnaire l'entrée dont la clé vaut `\"pomme\"`.\n",
    "- Créez un dictionnaire `d1` qui contient les entrées de `d` dont la clé commence par `\"a\"` (d'une manière qui marcherait aussi si le dictionnaire contenait des milliers d'entrées dont les clés sont toutes des chaînes de caractères)\n",
    "- Affichez toutes les clés de `d` associées à une valeur paire (d'une manière qui marcherait aussi si le dictionnaire contenait des milliers d'entrées dont les valeurs sont toutes des entiers)."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "4d7062a9",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "id": "93af5ad4",
   "metadata": {},
   "source": [
    "# Exercice 4\n",
    "\n",
    "**(a)** Ecrivez une fonction qui prend en entrée un dictionnaire `d` dont les valeurs sont numériques, et retourne la clé associée à la valeur maximale (si plusieurs clés sont associées à la valeur maximale, vous pouvez retourner n'importe laquelle de ces clés). Si le dictionnaire est vide, votre fonction doit retourner `None`. \n",
    "Ecrivez deux versions de la fonction:\n",
    "1. en utilisant la fonction `max()`\n",
    "2. sans utiliser la fonction `max()` (*Indice*: il sera utile d'initialiser une certaine variable à `float(\"-inf\")`, qui se comporte comme $-\\infty$ (en particulier, elle est plus petite que toute autre valeur numérique)).\n",
    "\n",
    "**(b)** Ecrivez une fonction qui prend en entrée un dictionnaire `d` dont les valeurs sont numériques, et retourne la somme des valeurs du dictionnaire. Si le dictionnaire est vide, votre fonction doit retourner `0`.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "ac523dc6",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "id": "f0ecec88",
   "metadata": {},
   "source": [
    "# Exercice 5\n",
    "\n",
    "**(a)** Ecrivez une fonction `dict_inverse` qui prend en entrée un dictionnaire `d` et retourne le dictionnaire dont les clés sont les **valeurs** de `d` et les valeurs associées sont les **clés** de `d`. Vous pouvez supposer que les valeurs du dictionnaire `d` sont uniques et immutables.\n",
    "\n",
    "Par exemple, l'appel `dict_inverse({1:\"a\", 2:\"b\"})` doit retourner le dictionnaire `{\"a\":1, \"b\":2})`.\n",
    "\n",
    "Donnez \n",
    "1. Une version de la fonction qui utilise une boucle\n",
    "2. Une version qui utilise la compréhension de dictionnaire."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "0d180692",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "id": "32eb92d1",
   "metadata": {},
   "source": [
    "**(b)** Ecrivez une fonction `dict_inverse_list` qui prend en entrée un dictionnaire `d` dont les valeurs ne sont pas nécessairement uniques (mais toujours immutables), et retourne le dictionnaire dont les clés sont les valeurs de `d`, et les valeurs associées sont les **listes** des clés de `d` correspondantes.\n",
    "\n",
    "Par exemple, l'appel `dict_inverse({1:\"a\", 2:\"b\", 3:\"a\", 4:\"c\"})` doit retourner le dictionnaire `{\"a\":[1, 3], \"b\":[2], \"c\":[4]})`.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "7b2ec713",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "id": "dc1358bc",
   "metadata": {},
   "source": [
    "# Exercice 6\n",
    "\n",
    "**(a)** Ecrivez une fonction `dict_occurrences` qui prend en entrée une liste `L` d'objets immutables, et retourne le dictionnaire dont les clés sont les éléments de `L`, et la valeur associée à chaque clé `x` est le nombre de fois où `x` apparaît dans `L`.\n",
    "\n",
    "Par exemple, `dict_occurrences([\"a\", \"b\", \"a\", \"c\", \"a\", \"b\"])` doit retourner le dictionnaire `{\"a\":3, \"b\":2, \"c\":1}`.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "e4f0a88a",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "id": "0f11dfc0",
   "metadata": {},
   "source": [
    "**(b)** Ecrivez une fonction qui \n",
    "- prend en entrée des paramètres entiers `n` et `m`\n",
    "- Génère une liste `L` de `n` nombres aléatoires entre `1` et `m` \n",
    "- passe `L` à `dict_occurrences` et récupère le dictionnaire `d` retourné\n",
    "- retourne le nombre d'éléments de `d` qui ont une valeur plus grande que `1`.\n",
    "\n",
    "Testez votre code pour plusieurs choix des paramètres `n` et `m` (par exemple, `n = 1000` et `m = 10000`; `n = 10000` et `m = 1000`, `n = m = 1000`...) Pour chaque choix de `n` et `m`, lancez le code plusieurs fois et observez les résultats."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "2577f17e",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "id": "d297f4f4",
   "metadata": {},
   "source": [
    "# Exercice 7 \n",
    "\n",
    "On se propose d'écrire une fonction qui calcule la moyenne des âges des étudiants de la classe, mais on ne sait pas à l'avance combien d'étudiants il y a (mais il y en aura au moins un.e). Ecrivez une fonction `moyenne_age` qui prend en entrée un argument obligatoire, suivi d'un nombre variable d'arguments (tous numériques) et qui retourne la moyenne des nombres entrés. Par exemple `moyenne_age(20, 19, 19, 21)` doit retourner `19.75`.\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "046f58cf",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "id": "1bc1e818",
   "metadata": {},
   "source": [
    "# Exercice facultatif : Enigme mathématique\n",
    "\n",
    "On considère `N` jetons numérotés, blancs d'un côté et noirs de l'autre. Ils ont initialement tous leur face blanche visible. \n",
    "\n",
    "Pour chaque jeton, on retourne successivement tous les multiples de ce jeton:\n",
    "- pour le jeton `1`, nous allons retourner les jetons d'indices `1, 2, 3, ..., N`\n",
    "- pour le jeton `2` nous allons retourner les jetons d'indices `2, 4, 6, ...`\n",
    "- pour le jeton `3` nous retournerons les jetons d'indices `3, 6, 9, ...`\n",
    "- ... et ainsi de suite jusqu'au jeton `N` que nous retournons tout seul.\n",
    "\n",
    "Ecrivez une fonction `jetons_mystere` qui prend le nombre `N` en entrée, simule le processus de retournement des jetons et retourne la liste contenant les indices des jetons qui seront noirs à la fin.\n",
    "\n",
    "Que remarquez-vous? Pouvez-vous expliquer ce résultat?\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "930efda1",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.10.4"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
