{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "6bd1091d",
   "metadata": {},
   "source": [
    "# Feuille d'exercices 3\n",
    "\n",
    "\n",
    "\n",
    "\n",
    "```{admonition} Objectifs\n",
    "* Compléments sur les listes\n",
    "* Ensembles et dictionnaires\n",
    "* Mot-clefs **`all`** et **`any`**\n",
    "```\n",
    "\n",
    "\n",
    "\n",
    "\n",
    "## Exercice 1 : listes par compréhension\n",
    "\n",
    "\n",
    "\n",
    "\n",
    "**Question 1 :** En utilisant une déclaration de liste **par compréhension**, écrire la liste des puissances de $2$ comprises entre $2^1$ et $2^{20}$."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "0d2339f2",
   "metadata": {},
   "outputs": [],
   "source": [
    "[ 2**i for i in range(1, 21) ]"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "2dc2dc26",
   "metadata": {},
   "source": [
    "**Question 2 :** En utilisant une déclaration de liste **par compréhension**, donner la liste des caractères de la chaîne \"Université Paris 8 Vincennes Saint-Denis\" qui ne sont pas des espaces."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "e8b8d07d",
   "metadata": {},
   "outputs": [],
   "source": [
    "chaine = \"Université Paris 8 Vincennes Saint-Denis\"\n",
    "L = [ c for c in chaine if c != \" \" ]\n",
    "print(L)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c2e1f0c4",
   "metadata": {},
   "source": [
    "**Question 3 :** En utilisant une déclaration de liste par compréhension, donner **le nombre** d'entiers compris entre $1000$ et $2000$, qui sont à la fois divisibles par $2$ et $7$."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "b2801a1a",
   "metadata": {},
   "outputs": [],
   "source": [
    "L = [ i for i in range(1000, 2001) if (i % 2 == 0 and i % 7 == 0) ]\n",
    "print(len(L))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "42b2180a",
   "metadata": {},
   "source": [
    "**Question 4 :** En utilisant une déclaration de liste **par compréhension**, écrire une fonction `diviseurs(n)` qui retourne la liste des diviseurs d'un entier `n`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "99fb5986",
   "metadata": {},
   "outputs": [],
   "source": [
    "def diviseurs(n):\n",
    "    return [i for i in range(1, n+1) if n % i == 0]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "6541f517",
   "metadata": {},
   "outputs": [],
   "source": [
    "D6 = diviseurs(6)\n",
    "print(\" Les diviseurs de 6 sont :\", D6)\n",
    "\n",
    "D48 = diviseurs(48)\n",
    "print(\" Les diviseurs de 48 sont :\", D48)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "396d6017",
   "metadata": {},
   "source": [
    "## Exercice 2 : mots-clefs **`any`** et **`all`**\n",
    "\n",
    "\n",
    "\n",
    "\n",
    "\n",
    "Un **palindrome** est un mot ou une phrase qui se lit identiquement dans les deux sens. Par exemple, les mots \"radar\", \"kayak\" ou \"naan\" sont des palindromes.\n",
    "\n",
    "**Question 1 :** En utilisant le mot clef **`all`**, écrire une fonction `est_palindrome(mot)` qui teste si la chaîne de caractère mot est (ou non) un palindrome. Pour cela, on pourra utiliser le mot-clef **`all`**."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "1f390fb8",
   "metadata": {},
   "outputs": [],
   "source": [
    "def est_palindrome(mot):\n",
    "    n = len(mot)\n",
    "    return all(mot[i] == mot[n-1-i] for i in range(n//2))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "4ea2a6ad",
   "metadata": {},
   "outputs": [],
   "source": [
    "print(est_palindrome(\"radar\"))\n",
    "print(est_palindrome(\"palindrome\"))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "449042f8",
   "metadata": {},
   "source": [
    "**Question 2 :** En utilisant le mot clef **`any`**, écrire une fonction `contient_palindrome(L)` qui prend en entrée une **liste** de chaînes de caractères `L`, et qui teste si **au moins une** de ces chaînes est un palindrome."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "67425bf9",
   "metadata": {},
   "outputs": [],
   "source": [
    "def contient_palindrome(L):\n",
    "    return any( est_palindrome(x) for x in L)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "e0ec3b19",
   "metadata": {},
   "outputs": [],
   "source": [
    "print(contient_palindrome([\"université\", \"paris\", \"8\"]))\n",
    "print(contient_palindrome([\"saint\", \"denis\"]))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "53784736",
   "metadata": {},
   "source": [
    "## Exercice 3 : ensembles\n",
    "\n",
    "\n",
    "\n",
    "**Question 1 :** Écrire une fonction `caracteres(texte)` qui prend en entrée une chaîne de caractères `texte`, et qui retourne **l'ensemble** des caractères de la chaîne."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "13f93140",
   "metadata": {},
   "outputs": [],
   "source": [
    "def caracteres(texte):\n",
    "    return { c for c in texte }"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "ef00eda4",
   "metadata": {},
   "outputs": [],
   "source": [
    "print(caracteres(\"texte\"))\n",
    "print(caracteres(\"aaaaaaaaaaaaaaaa\"))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "9904d2dc",
   "metadata": {},
   "source": [
    "## Exercice 4 : dictionnaires\n",
    "\n",
    "\n",
    "\n",
    "**Question 1 :** Écrire une fonction `compte_caracteres(texte)` qui prend en entrée une chaîne de caractères `texte`, et qui retourne le dictionnaire ayant :\n",
    "* pour clés les caractères de la chaîne `texte`\n",
    "* pour valeur correspondant au caractère `c`, le nombre de fois que `c` apparaît dans `texte`.\n",
    "\n",
    "Par exemple, pour la chaîne \"calcul\", on obtient le dictionnaire `{ 'c': 2, 'a': 1, 'l': 2, 'u': 1}`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "ce7f83cd",
   "metadata": {},
   "outputs": [],
   "source": [
    "def compte_caracteres(texte):\n",
    "    D = {}\n",
    "    for c in texte:\n",
    "        if c in D:\n",
    "            D[c] += 1\n",
    "        else:\n",
    "            D[c] = 1\n",
    "    return D"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "bd570774",
   "metadata": {},
   "outputs": [],
   "source": [
    "print(compte_caracteres(\"calcul\"))\n",
    "print(compte_caracteres(\"aaaaaaaaaaaaaaaa\"))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "8a7f4bf2",
   "metadata": {},
   "source": [
    "## Exercice 5 : somme de puissances\n",
    "\n",
    "\n",
    "**Question 1 :** Créer une fonction ``liste_puissances(n, p)`` qui prend en entrée deux paramètres paramètres `n` et `p`, et qui retourne la liste des entiers de la forme $x^p$, pour $x$ compris entre $1$ et $n$.  Par exemple, pour $n = 4$ et $p = 3$, on obtient la liste ``[1, 8, 27, 64]``. Votre fonction devra utiliser une déclaration de liste **par compréhension**."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "9e58bebb",
   "metadata": {},
   "outputs": [],
   "source": [
    "def liste_puissances(n, p):\n",
    "    return [ i**p for i in range(1, n+1) ]\n",
    "    \n",
    "liste_puissances(4, 3)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e9b18b6d",
   "metadata": {},
   "source": [
    "**Question 2 :** Créer une fonction **récursive** `somme_liste(L)` qui retourne la somme des éléments d'une liste `L`. Si la liste `L` est vide, la fonction doit retourner $0$."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "1305801b",
   "metadata": {},
   "outputs": [],
   "source": [
    "def somme_liste(L):\n",
    "    if L == []:\n",
    "        return 0\n",
    "    x = L.pop()\n",
    "    return x + somme_liste(L)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "adce88ea",
   "metadata": {},
   "source": [
    "**Question 3 :** À l'aide du mot-clef **`all`** et des questions précédentes, vérifier que l'identité\n",
    "\n",
    "$$\n",
    "    \\sum_{i=1}^n i^3 = \\left(\\sum_{i=1}^n i \\right)^2\n",
    "$$\n",
    "\n",
    "est satisfaite pour les entiers $n$ compris entre $1$ et $100$."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "856b7d6a",
   "metadata": {},
   "outputs": [],
   "source": [
    "all(somme_liste(liste_puissances(n, 3)) == somme_liste(liste_puissances(n, 1))**2 for n in range(1, 101))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a43b56d1",
   "metadata": {},
   "source": [
    "## Exercice 6 : corriger des erreurs\n",
    "\n",
    "\n",
    "\n",
    "**Question 1 :** Dans la cellule suivante, une fonction a été écrite dnas le but d'inverser l'ordre des lettres d'un mot. Cette fonction contient **plusieurs erreurs**. Exécutez la cellule, puis observez ce qui est affiché. Essayez ensuite de corriger les erreurs pour obtenir le bon résultat."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "6ed9fe01",
   "metadata": {},
   "outputs": [],
   "source": [
    "def ma_fonction(mot)\n",
    "    renverse = \"\"\n",
    "    n = len(mot)\n",
    "    for i in range(1, n):\n",
    "        renverse = mot(i) + renverse\n",
    "    return renverse\n",
    "\n",
    "ma_fonction(\"calcul\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ba30f4d2",
   "metadata": {},
   "source": [
    "Il y a trois erreurs :\n",
    "1. à la ligne 1, il manque un `:` à la déclaration de la fonction\n",
    "1. à la ligne 5, la syntaxe pour accéder à un caractère doit être avec des crochets (`mot[i]`)\n",
    "1. enfin, le résultat est erroné car à la ligne 4, on ne parcourt pas le premier caractère du mot (pour `i = 0`)."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "09a9080c",
   "metadata": {},
   "outputs": [],
   "source": [
    "def ma_fonction_corrigee(mot):\n",
    "    renverse = \"\"\n",
    "    n = len(mot)\n",
    "    for i in range(0, n):\n",
    "        renverse = mot[i] + renverse\n",
    "    return renverse\n",
    "\n",
    "ma_fonction_corrigee(\"calcul\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "1a169934",
   "metadata": {},
   "source": [
    "## Exercice 7 : doublon dans les listes\n",
    "\n",
    "**Question 1 :** Écrire une fonction `doublon(L)` qui prend en entrée une liste `L`, et qui teste si la liste `L` contient au moins deux fois le même élément.\n",
    "\n",
    "\n",
    "\n",
    "Une première version :"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "164e1e59",
   "metadata": {},
   "outputs": [],
   "source": [
    "def doublon(L):\n",
    "    n = len(L)\n",
    "    for i in range(n):\n",
    "        for j in range(n):\n",
    "            if i != j and L[i] == L[j]:\n",
    "                return True\n",
    "    return False\n",
    "\n",
    "print(doublon([1, 2, 5, 3, 0, 2]))\n",
    "print(doublon([1, \"a\", 5, 3, 0, 2]))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "55e24348",
   "metadata": {},
   "source": [
    "Voici maintenant une version un peu plus efficace :"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "7c6f9dc4",
   "metadata": {},
   "outputs": [],
   "source": [
    "def doublon(L):\n",
    "    n = len(L)\n",
    "    for i in range(n):\n",
    "        for j in range(i):\n",
    "            if L[i] == L[j]:\n",
    "                return True\n",
    "    return False\n",
    "\n",
    "print(doublon([1, 2, 5, 3, 0, 2]))\n",
    "print(doublon([1, \"a\", 5, 3, 0, 2]))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "de827241",
   "metadata": {},
   "source": [
    "**Question 2 :** Si ce n'est pas déjà fait, reprendre la question 1, en utilisant le mot-clef **`any`**, ainsi qu'une syntaxe **par compréhension**."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "c610035f",
   "metadata": {},
   "outputs": [],
   "source": [
    "def doublon(L):\n",
    "    n = len(L)\n",
    "    return any( L[i] == L[j] for i in range(n) for j in range(i) )\n",
    "\n",
    "print(doublon([1, 2, 5, 3, 0, 2]))\n",
    "print(doublon([1, \"a\", 5, 3, 0, 2]))"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "python",
   "language": "python",
   "name": "python"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
