{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Exercices du livre - Chapitre 5 - solutions\n",
    "\n",
    "---\n",
    "\n",
    "<table class=\"appbclp1\">\n",
    "<tr> <td style=\"font-weight: bold!;\">auteurs :</td><td style=\"text-align: left!;\">Laurent Pointal &lt;<a href=\"mailtp:laurent.pointal@limsi.fr\">laurent.pointal@limsi.fr</a>&gt; &amp; Bob Cordeau &lt;<a href=\"pycours@kordeo.eu\">pycours@kordeo.eu</a>&gt; </td> </tr>\n",
    "<tr> <td style=\"font-weight: bold!;\">licence :</td><td style=\"text-align: left!;\">Creative Commons Attribution-ShareAlike 4.0 International Public License (CC BY-SA 4.0) </td> </tr>\n",
    "<tr> <td style=\"font-weight: bold!;\">source :</td><td style=\"text-align: left!;\"><a href=\"https://github.com/lpointal/appbclp\">https://github.com/lpointal/appbclp</a></td> </tr>\n",
    "<tr> <td style=\"font-weight: bold!;\">description :</td><td style=\"text-align: left!;\">Les programmes dans ce Notebook Jupyter servent de support au livre <span style=\"font-style: italic!;\">« Python 3 - Apprendre à  programmer dans l'écosystème Python»</span>, édition Dunod, dans lequel les différentes sections sont expliquées </td> </tr>\n",
    "<tr> <td style=\"font-weight: bold!;\">url :</td><td style=\"text-align: left!;\"><a href=\"https://www.dunod.com/sciences-techniques/python-3\">https://www.dunod.com/EAN/9782100809141</a></td> </tr>\n",
    "</table>\n",
    "\n",
    "---"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Exercice 1"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Exercice 1\n",
    "\n",
    "def genere_sous_listes(liste):\n",
    "    sous_listes = [[]]\n",
    "\n",
    "    for lng in range(1, len(liste) + 1):\n",
    "        for i in range(0, len(liste) - lng + 1):\n",
    "            sous_listes.append(liste[i:i+lng])\n",
    "\n",
    "    return sous_listes\n",
    "\n",
    "# Auto-test ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n",
    "if __name__ == '__main__':\n",
    "    print(\"\\n\", genere_sous_listes([1, 2, 3]))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Exercice 2"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Exercice 2\n",
    "\n",
    "def fact(n):\n",
    "    r = 1\n",
    "    for i in range(1, n+1):\n",
    "        r *= i\n",
    "    return r\n",
    "\n",
    "# Programme principal =========================================================\n",
    "n = int(input(\"Nombre d'itérations : \"))\n",
    "exp = 0.0\n",
    "for i in range(n):\n",
    "    exp = exp + 1.0/fact(i)\n",
    "\n",
    "print(f\"Approximation de 'e' en {n} itérations : {exp:.3f}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Exercice 3"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Exercice 3\n",
    "\n",
    "def verif_passwd(passwd):\n",
    "    \"\"\"Vérifie un mot de passe.\"\"\"\n",
    "\n",
    "    cap, bdc, nbr = False, False, False\n",
    "    for ch in passwd:\n",
    "        if 'A' <= ch <= 'Z': cap = True  # au moins une majuscule\n",
    "        if 'a' <= ch <= 'z': bdc = True  # au moins une minuscule\n",
    "        if '0' <= ch <= '9': nbr = True  # au moins un chiffre\n",
    "\n",
    "    return len(passwd) >= 8 and cap and bdc and nbr"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Exercice 4"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Exercice 4\n",
    "\n",
    "CODE = {'A':'.-','B':'-...','C':'-.-.','D':'-..','E':'.','F':'..-.','G':'--.',\n",
    "    'H':'....','I':'..','J':'.---','K':'-.-','L':'.-..','M':'--','N':'-.',\n",
    "    'O':'---','P':'.--.','Q':'--.-','R':'.-.','S':'...','T':'-','U':'..-',\n",
    "    'V':'...-','W':'.--','X':'-..-','Y':'-.--','Z':'--..',\n",
    "    '0':'-----','1':'.----','2':'..---','3':'...--','4':'....-',\n",
    "    '5':'.....','6':'-....','7':'--...','8':'---..','9':'----.',\n",
    "    ' ':' '\n",
    "}\n",
    "\n",
    "# Définition de fonction ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n",
    "def morse(msg):\n",
    "    \"\"\"Reçoit un message en clair et retourne le message en morse.\"\"\"\n",
    "    code = \"\"\n",
    "    for ch in msg:\n",
    "        ch = ch.upper()\n",
    "        code += CODE[ch] + ' '\n",
    "\n",
    "    return code[:-1]  # enlève le blanc final\n",
    "\n",
    "# Programme principal ==========================================================\n",
    "message = \"SOS\"\n",
    "print(f'\\nUn exemple. Le codage de \"{message}\" est : \"{morse(message)}\"')\n",
    "\n",
    "message = input(\"\\nVotre message (ligne vide pour terminer) : \")\n",
    "while message:\n",
    "    print(f'Le codage de \"{message}\" est : \"{morse(message)}\"')\n",
    "    message = input(\"\\nVotre message (ligne vide pour terminer) : \")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Exercice 5"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Exercice 5\n",
    "\n",
    "import math as m\n",
    "from collections import namedtuple\n",
    "\n",
    "# Définition de fonction ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n",
    "def coeff_dir(nuage):\n",
    "    \"\"\"\n",
    "        Retourne m le coefficient directeur d'un nuage de points\n",
    "        selon la méthode des moindres carrés.\n",
    "    \"\"\"\n",
    "    n = len(nuage)\n",
    "\n",
    "    # On décompose la formule donnée sous la forme plus simple :\n",
    "    # m = (a - b1*b2) / (c - (b1**2 / n))\n",
    "    a, b1, b2, c = 0.0, 0.0, 0.0, 0.0\n",
    "    for p in nuage:\n",
    "        a += p.x * p.y\n",
    "        b1 += p.x\n",
    "        b2 += p.y\n",
    "        c += (p.x ** 2)\n",
    "\n",
    "    return (a - (b1 * b2) / n) / (c - (b1**2 / n))\n",
    "\n",
    "\n",
    "def coeff_cst(nuage, m):\n",
    "    \"\"\"\n",
    "        Retourne b le coefficient constant d'un nuage de points de coefficient directeur m.\n",
    "    \"\"\"\n",
    "\n",
    "    # b est donné par : b = y_m - m*x_m\n",
    "    # où x_m et y_m sont les valeurs moyennes des abscisses et des ordonnées\n",
    "    x_m, y_m = 0.0, 0.0\n",
    "    for p in nuage:\n",
    "        x_m += p.x\n",
    "        y_m += p.y\n",
    "\n",
    "    n = len(nuage)\n",
    "    x_m /= n\n",
    "    y_m /= n\n",
    "\n",
    "    return y_m - m * x_m\n",
    "\n",
    "\n",
    "# Programme principal ==========================================================\n",
    "Point = namedtuple('Point', ['x', 'y'])  # définition du type Point\n",
    "nuage = []                               # initialisation du nuage de points\n",
    "\n",
    "print(\"\\nEntrez une abscisse et une ordonnées séparées par un espace :\")\n",
    "ligne = input(\"\\tx y (ligne vide pour terminer) : \")\n",
    "while ligne:\n",
    "    saisie = ligne.split()\n",
    "    p = Point(float(saisie[0]), float(saisie[1]))\n",
    "    nuage.append(p)\n",
    "    ligne = input(\"\\tx y (ligne vide pour terminer) : \")\n",
    "\n",
    "if nuage:\n",
    "    m = coeff_dir(nuage)\n",
    "    b = coeff_cst(nuage, m)\n",
    "    print(f\"\\nDroite des moindres carrés : y = {m:.2g}x + {b:.2g}\")\n",
    "else:\n",
    "    print(\"\\nNuage vide !\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Exercice 6"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Exercice 6 (module)\n",
    "\n",
    "# Import ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n",
    "from math import gcd\n",
    "\n",
    "# Définition de fonction ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n",
    "def maj(couple, liste):\n",
    "    \"\"\"\n",
    "        Met à jour la liste des rationnels.\n",
    "    \"\"\"\n",
    "    pgcd = gcd(couple[0], couple[1])\n",
    "    t = (couple[0]//pgcd, couple[1]//pgcd)\n",
    "    if t not in liste:\n",
    "        liste.append(couple)\n",
    "\n",
    "\n",
    "def ajout_ordre_suivant(liste):\n",
    "    \"\"\"\n",
    "        Enrichit la liste de l'ordre suivant (par effet de bord).\n",
    "    \"\"\"\n",
    "    ordre = liste[-1][0] + liste[-1][1]\n",
    "    [maj((num, ordre+1-num), liste) for num in range(1, ordre + 1)]\n",
    "\n",
    "\n",
    "# Auto-test ====================================================================\n",
    "if __name__ == '__main__':\n",
    "    liste = [(0, 1)]\n",
    "    #------------------\n",
    "    maj((1, 1), liste)\n",
    "    print(liste)\n",
    "    maj((2, 2), liste)\n",
    "    print(liste)\n",
    "    #------------------\n",
    "    ajout_ordre_suivant(liste)\n",
    "    print(liste)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Exercice 6 (programme principal)\n",
    "\n",
    "from math import gcd\n",
    "from ratio_m import maj, ajout_ordre_suivant\n",
    "\n",
    "# Programme principal ==========================================================\n",
    "liste = [(0, 1)]     # initialisation de la liste\n",
    "choix = 1\n",
    "while choix != 0:\n",
    "    choix = int(input(\"\\nQuit                (0)\\n\"\n",
    "                      \"Valeur du quantième rationnel (1)\\n\"\n",
    "                      \"Rang d'un rationnel           (2)\\n\"\n",
    "                      \"\\t\\tVotre choix : \"))\n",
    "    \n",
    "    if choix == 1:   # Quel est le quantième rationnel ?\n",
    "        n = int(input(\"\\nNuméro dans la liste des rationnel : \"))\n",
    "        while len(liste) < n:\n",
    "            ajout_ordre_suivant(liste)\n",
    "        print(f\"Le {n}è rationnel est {liste[n-1][0]}/{liste[n-1][1]}\")\n",
    "            \n",
    "    if choix == 2:   # Quel est le rang d'un rationnel donné ?\n",
    "        num = int(input(\"\\nNumérateur   : \"))\n",
    "        den = int(input(\"Dénominateur : \"))\n",
    "        pgcd = gcd(num, den)\n",
    "        ratio = (num//pgcd, den//pgcd)\n",
    "\n",
    "        while ratio not in liste:\n",
    "            ajout_ordre_suivant(liste)\n",
    "\n",
    "        print(f\"Le rationnel {ratio[0]}/{ratio[1]} est au\"\n",
    "              f\" {liste.index(ratio) + 1}è rang\")\n",
    "\n",
    "print(\"\\nSalut !\")"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "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.7.6"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
