{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "3edc69a3",
   "metadata": {},
   "source": [
    "# Séance 4\n",
    "\n",
    "\n",
    "```{admonition} Objectifs\n",
    "* Fonctions natives python\n",
    "* Bibliothèques python : math, random, matplotlib\n",
    "```\n",
    "\n",
    "\n",
    "## Quelques fonctions natives de python\n",
    "\n",
    "\n",
    "Python pré-intègre un certain nombre de fonctions (*built-in functions*). Nous en avons déjà vu certaines : `print()`, `len()`, `range()` par exemple. Nous allons en découvrir quelques autres ; pour une liste plus complète, voir ici : [https://www.w3schools.com/python/python_ref_functions.asp](https://www.w3schools.com/python/python_ref_functions.asp)\n",
    "\n",
    "\n",
    "La fonction **valeur absolue** est notée `abs()` :"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "4700033f",
   "metadata": {},
   "outputs": [],
   "source": [
    "x = -1\n",
    "print(abs(x))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f613291c",
   "metadata": {},
   "source": [
    "La fonction de calcul **d'arrondi** est `round()` :"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "df1fb7be",
   "metadata": {},
   "outputs": [],
   "source": [
    "x = 1.4\n",
    "print(round(x))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "76b34f30",
   "metadata": {},
   "source": [
    "On peut obtenir le **minimum** et le **maximum** de plusieurs valeurs, ou même d'une liste, avec les fonctions `min()` et `max()` :"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "0f677bed",
   "metadata": {},
   "outputs": [],
   "source": [
    "print(min(1, 2))\n",
    "print(max(-3, 0, 0, -1))\n",
    "\n",
    "L = [ -3, 7, 2, 0, -9, 7, 1 ]\n",
    "print(\"le minimum de L est :\", min(L))\n",
    "print(\"le maximum de L est :\", max(L))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "3b40f821",
   "metadata": {},
   "source": [
    "On peut **trier** une liste avec la fonction `sorted()`. Cette fonction **ne modifie pas** la liste passée en paramètre ; elle **retourne** une version triée de cette liste."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "ef78fb35",
   "metadata": {},
   "outputs": [],
   "source": [
    "L = [ -3, 7, 2, 0, -9, 7, 1 ]\n",
    "M = sorted(L)\n",
    "print(L)\n",
    "print(M)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a15f4170",
   "metadata": {},
   "source": [
    "## Bibliothèque `math`\n",
    "\n",
    "\n",
    "En python, on peut **importer** d'autres fonctions et d'autres objets qui ont été écrits dans des **bibliothèques**. Par exemple, la bibliothèque `math` contient de nombreuses fonctions et constantes mathématiques. \n",
    "\n",
    "Pour importer cette bibliothèque, on utilise la syntaxe suivante :"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "bf0d528e",
   "metadata": {},
   "outputs": [],
   "source": [
    "import math"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "51baec4e",
   "metadata": {},
   "source": [
    "Puis, pour utiliser un objet de cette bibiothèque (par exemple la constante `pi`) on va utiliser la syntaxe `math.<objet>` :"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "90657ad2",
   "metadata": {},
   "outputs": [],
   "source": [
    "math.pi"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "81dbce6f",
   "metadata": {},
   "source": [
    "**Remarque :** il n'est pas utile de faire l'import à chaque cellule. Une fois la fonction importée dans python/jupyter, elle est à votre disposition.\n",
    "\n",
    "Passons maintenant en revue quelques fonctions et objets de la bibliothèque `math`.\n",
    "\n",
    "### Fonctions classiques\n",
    "\n",
    "La fonction **racine carrée** s'écrit `sqrt()` :"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "5710de6d",
   "metadata": {},
   "outputs": [],
   "source": [
    "print(math.sqrt(9))\n",
    "print(math.sqrt(2))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "bfb08ec0",
   "metadata": {},
   "source": [
    "Observons que, même si la racine carrée de $9$ est entière, la valeur de retour de `sqrt()` n'est pas un entier, mais un nombre \"approché\" (appelé aussi *flottant*).\n",
    "\n",
    "\n",
    "Les fonctions **exponentielle** et **logarithme népérien** sont `exp()` et `log()`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "17991f91",
   "metadata": {},
   "outputs": [],
   "source": [
    "print(math.exp(2))\n",
    "print(math.log(2))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "3c7f8234",
   "metadata": {},
   "source": [
    "Le nombre $e$ est également accessible :"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "8453a1e8",
   "metadata": {},
   "outputs": [],
   "source": [
    "print(math.e)\n",
    "print(math.e == math.exp(1))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d8d3906c",
   "metadata": {},
   "source": [
    "Les fonctions **partie entière inférieure** et **partie entière supérieure** sont `floor()` et `ceil()` :"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "d68266de",
   "metadata": {},
   "outputs": [],
   "source": [
    "x = 1.4\n",
    "print(math.floor(x), math.ceil(x))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "1fac07ee",
   "metadata": {},
   "source": [
    "### Trigonométrie\n",
    "\n",
    "La bibliothèque `math` contient aussi des objets et fonctions trigonométriques. Les fonctions **cosinus**, **sinus** et **tangente** sont `cos()`, `sin` et `tan` et leur argument doit être exprimé en radians."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "15adb047",
   "metadata": {},
   "outputs": [],
   "source": [
    "theta = math.pi/3\n",
    "print(math.cos(theta))\n",
    "print(math.sin(theta))\n",
    "print(math.tan(theta))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "1cb0cd84",
   "metadata": {},
   "source": [
    "Leurs fonctions réciproques sont `acos()`, `asin()` et `atan()`. Enfin, les fonctions hyperboliques sont `cosh()`, `sinh()`, `tanh()`, et leurs réciproques `acosh()`, `asinh()`, `atanh()`.\n",
    "\n",
    "\n",
    "\n",
    "### Arithmétique\n",
    "\n",
    "\n",
    "\n",
    "Le **pgcd** et le **ppcm** d'une séquence d'entiers peuvent être calculés via les fonctions `gcd` et `lcm`. Elles peuvent prendre $2$ arguments ou davatange."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "788490b4",
   "metadata": {},
   "outputs": [],
   "source": [
    "print(math.gcd(21, 49))\n",
    "print(math.gcd(21, 49, 76))\n",
    "\n",
    "print(math.lcm(21, 49))\n",
    "print(math.lcm(21, 49) * math.gcd(21, 49) == 21 * 49)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "af8d3ff2",
   "metadata": {},
   "source": [
    "Observons que ces fonctions retournent des **entiers**, et non des flottants.\n",
    "\n",
    "\n",
    "La **factorielle** et le **coefficient binomial** peuvent être obtenus via les fonctions `factorial` et `comb`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "19683728",
   "metadata": {},
   "outputs": [],
   "source": [
    "print(math.factorial(6))\n",
    "print(math.comb(5, 2))\n",
    "print(math.comb(10, 7) == math.factorial(10) // (math.factorial(7) * math.factorial(3)))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "3bac7798",
   "metadata": {},
   "source": [
    "```{warning}\n",
    "**Remarque pour les utilisateur·ices des machines de l'université.** Les fonctions `lcm`, `factorial` ou `comb` ne sont disponibles qu'à partir de la version 3.8 de python (datant de 2019), qui sont accessible en salle de cours, mais **pas au bocal**.\n",
    "```\n",
    "\n",
    "\n",
    "\n",
    "**Tableau récapitulatif (bibliothèque `math`)**\n",
    "\n",
    "| Fonction ou objet mathématique | Syntaxe python |\n",
    "| :---: | :---: |\n",
    "| racine carrée $\\sqrt{x}$ | `math.sqrt(x)` |\n",
    "| exponentielle $e^x$ | `math.exp(x)` |\n",
    "| logarithme népérien $\\ln(x)$ | `math.log(x)` |\n",
    "| cosinus $\\cos(a)$ | `math.cos(a)` |\n",
    "| sinus $\\sin(a)$ | `math.sin(a)` |\n",
    "| tangente $\\tan(a)$ | `math.tan(a)` |\n",
    "| partie entière (inférieure)  $\\lfloor x \\rfloor$ | `math.floor(x)` |\n",
    "| partie entière supérieure $\\lceil x \\rceil$ | `math.ceil(x)` |\n",
    "| pgcd de deux entiers $n$ et $m$ | `math.gcd(n, m)` |\n",
    "| ppcm de deux entiers $n$ et $m$ | `math.lcm(n, m)` |\n",
    "| factorielle $n!$ | `math.factorial(n)` |\n",
    "| coefficient binomial $\\binom{n}{k}$ | `math.comb(n, k)` |\n",
    "| nombre $\\pi$ | `math.pi` |\n",
    "| nombre $e$ | `math.e` |\n",
    "\n",
    "\n",
    "\n",
    "\n",
    "\n",
    "\n",
    "## Bibliothèque `random`\n",
    "\n",
    "En informatique, il est souvent utile de savoir **tirer aléatoirement** des valeurs, dans un certain ensemble et selon une certaine distribution. Par exemple, pour tirer un entier dans un intervalle $[a, b]$ selon la distribution uniforme, on peut utiliser la fonction `randint` de la bibliothèque `random`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "e03e356a",
   "metadata": {},
   "outputs": [],
   "source": [
    "import random\n",
    "\n",
    "n = random.randint(0, 1000)\n",
    "print(n)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "fb8cee10",
   "metadata": {},
   "source": [
    "Par exemple, pour engendrer une liste de $10$ entiers aléatoires entre $-2$ et $2$ :"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "0eada680",
   "metadata": {},
   "outputs": [],
   "source": [
    "L = [ random.randint(-2, 2) for i in range(10) ]\n",
    "print(L)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "015e9e05",
   "metadata": {},
   "source": [
    "Pour tirer un élément aléatoire dans une liste `L`, on peut tirer aléatoirement un indice $i$ de la liste (avec `randint`), puis accéder à `L[i]`. Une **autre manière** est d'utiliser la fonction appropriée `choice` :"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "e1eb6b42",
   "metadata": {},
   "outputs": [],
   "source": [
    "jours = [ \"lundi\", \"mardi\", \"mercredi\", \"jeudi\", \"vendredi\", \"samedi\", \"dimanche\" ]\n",
    "i = random.randint(0, len(jours)-1)\n",
    "print(jours[i])\n",
    "j = random.choice(jours)\n",
    "print(j)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "11376800",
   "metadata": {},
   "source": [
    "**Tableau récapitulatif (bibliothèque `random`)**\n",
    "\n",
    "| Fonction | Syntaxe python |\n",
    "| :---: | :---: |\n",
    "| tirage aléatoire uniforme d'un entier dans $[a, b]$ | `random.randint(a, b)` |\n",
    "| tirage aléatoire d'un élément d'une liste `L` | `random.choice(L)` |\n",
    "\n",
    "\n",
    "\n",
    "\n",
    "## Bibliothèque `matplotlib`\n",
    "\n",
    "\n",
    "Python permet aussi de **tracer des graphiques** grâce à sa biblitothèque `matplotlib`. Cette bibliothèque contient de nombreux **modules** (regroupement de fonctions et d'objets à l'intérieur d'une bibliothèque), notamment le module `pyplot` qui nous sera utile.\n",
    "\n",
    "```{note}\n",
    "Nous verrons que Sagemath simplifie grandement la manière de tracer des fonctions et d'afficher graphiquement des objets. Néanmoins, si vous utilisez plus tard python **sans** Sagemath, il vous sera utile de connaître la bibliothèque `matplotlib`.\n",
    "```\n",
    "\n",
    "Il est d'usage d'importer le module `pyplot` avec la syntaxe suivante :"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "0382fad6",
   "metadata": {},
   "outputs": [],
   "source": [
    "import matplotlib.pyplot as plt"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "437ab286",
   "metadata": {},
   "source": [
    "Cette instruction crée un alias `plt` vers le module `pyplot`, qui nous donne accès à différentes fonctions de création et de manipulation de graphiques. Voyons des exemples simples d'utilisation ; pour plus de détails et d'exemples, suivre le lien https://matplotlib.org/stable/index.html . Également, un autre tutoriel plus complet : https://matplotlib.org/stable/tutorials/pyplot.html#sphx-glr-tutorials-pyplot-py\n",
    "\n",
    "\n",
    "\n",
    "````{warning}\n",
    "**Remarque pour les utilisateur·ices des machines de l'université.** Il est possible qu'une mise à jour récente de la bibliothèque `numpy` sur les machines de l'université provoque des erreurs d'exécution, notamment lors de l'import de la bibliothèque `matplotlib`. Pour régler ce problème, vous devez faire un \"downgrade\" (une \"anti\"-mise à jour) de cette bibliothèque. La procédure est la suivante : entrez dans le terminal la commande\n",
    "```\n",
    "pip install numpy==1.22.0\n",
    "```\n",
    "Cette procédure va donc **désinstaller** la version de numpy actuellement installée sur vos machines, et la remplacer par une plus ancienne. Pour **ré-installer** la plus récente, si besoin par exemple dans un autre cours, faites :\n",
    "```\n",
    "pip install numpy==2.0.0\n",
    "```\n",
    "````\n",
    "\n",
    "### Les fonctions ``plot`` et ``show`` de ``matplotlib.pyplot``\n",
    "\n",
    "Les fonctions `plot` et `show` permettent de **construire** et **d'afficher** des données relatives à des points dans le plan. Plus précisément, si `X = [x1, x2, ..., xn]` et `Y = [y1, y2, ..., yn]` sont les listes des abscisses et des ordonnées des points à tracer, alors on peut exécuter l'instruction\n",
    "```\n",
    "plt.plot(X, Y)\n",
    "```\n",
    "pour **placer** ces points sur un graphique. Ensuite, pour **afficher** le graphique on utilise la fonction ``show`` :\n",
    "```\n",
    "plt.show()\n",
    "```\n",
    "\n",
    "Voici un exemple avec des données de températures annuelles en France entre 2011 et 2021 :"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "f0f1fdc5",
   "metadata": {},
   "outputs": [],
   "source": [
    "import matplotlib.pyplot as plt\n",
    "\n",
    "annees = [i for i in range(2011, 2022) ]\n",
    "temperatures = [13.6, 12.8, 12.4, 13.8, 13.6, 13.1, 13.4, 13.9, 13.7, 14.1, 12.9]\n",
    "\n",
    "plt.plot(annees, temperatures)\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "5cd3eb53",
   "metadata": {},
   "source": [
    "### Style \n",
    "\n",
    "Si le **style** d'affichage ne nous convient pas, on peut le changer avec certaines instructions. Quelques exemples.\n",
    "\n",
    "\n",
    "**Style des points.** Pour changer le style des points à afficher, on peut utiliser le paramètre optionnel `marker`. Par exemple, pour avoir des points sous forme de petits cercles, on écrit :"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "f4fd57f3",
   "metadata": {},
   "outputs": [],
   "source": [
    "plt.plot(annees, temperatures, marker='o')\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "eb2d4e85",
   "metadata": {},
   "source": [
    "**Couleur.** La couleur peut être choisie avec le paramètre optionnel `color`. Par exemple, pour obtenir un tracé rouge avec des points symbolisés par des petites croix, on écrira :"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "822ffa38",
   "metadata": {},
   "outputs": [],
   "source": [
    "plt.plot(annees, temperatures, marker='+', color='red')\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e31d6f77",
   "metadata": {},
   "source": [
    "**Épaisseur.** Pour modifier l'épaisseur du trait, on utilise le paramètre `linewidth` :"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "556f4f30",
   "metadata": {},
   "outputs": [],
   "source": [
    "plt.plot(annees, temperatures, linewidth=5)\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "2a21f1a6",
   "metadata": {},
   "source": [
    "**Style de trait.** Pour modifier le style du trait, c'est le paramètre `linestyle`. Par exemple pour avoir des tirets :"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "7cd6cee4",
   "metadata": {},
   "outputs": [],
   "source": [
    "plt.plot(annees, temperatures, linestyle='dashed')\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "57c71bc2",
   "metadata": {},
   "source": [
    "Pour n'afficher **que des points** (sans les relier avec une ligne), on donne la chaîne vide `''` comme valeur à l'argument `linestyle` :"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "3e784529",
   "metadata": {},
   "outputs": [],
   "source": [
    "plt.plot(annees, temperatures, marker='+', linestyle='')\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b3fb0a4c",
   "metadata": {},
   "source": [
    "Enfin, pour revenir à un style de trait **continu** :"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "6765522a",
   "metadata": {},
   "outputs": [],
   "source": [
    "plt.plot(annees, temperatures, linestyle='-')\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "85b7e1c5",
   "metadata": {},
   "source": [
    "Allez voir https://matplotlib.org/3.5.3/api/_as_gen/matplotlib.pyplot.plot.html pour davantage de détails.\n",
    "\n",
    "\n",
    "\n",
    "### Superposition\n",
    "\n",
    "On peut également **superposer** des graphiques. Pour cela, l'idée est d'appeler successivement `plot` avec différentes données, **puis** de demander l'affichage avec `show`. Par exemple, si l'on souhaite afficher les températures annuelles à Paris et à Marseille sur un même graphique :"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "855294c5",
   "metadata": {},
   "outputs": [],
   "source": [
    "annees = [i for i in range(2010, 2022) ]\n",
    "temperatures_paris = [11.8, 13.7, 12.7, 12.1, 13.6, 13.4, 12.9, 13.4, 13.8, 13.6, 14.3, 12.8]\n",
    "temperatures_marseille = [14.8, 16.2, 15.8, 15.2, 16.8, 16.3, 16.4, 16.2, 17, 16.4, 16.5, 15.9]\n",
    "\n",
    "plt.plot(annees, temperatures_paris, color='blue')\n",
    "plt.plot(annees, temperatures_marseille, color='red')\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "48b1582e",
   "metadata": {},
   "source": [
    "Remarquons que si nous avions appelé la fonction `show` entre les deux appels à `plot`, nous aurions eu deux graphiques indépendants :"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "d11a7b8a",
   "metadata": {},
   "outputs": [],
   "source": [
    "plt.plot(annees, temperatures_paris, color='blue')\n",
    "plt.show()\n",
    "plt.plot(annees, temperatures_marseille, color='red')\n",
    "plt.show()\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f80c6a53",
   "metadata": {},
   "source": [
    "### Ajouter des informations\n",
    "\n",
    "Enfin, il peut être utilise d'ajouter une **légende** ou des **informations** sur vos graphiques. C'est notamment le cas si vous souhaitez les utiliser pour des rapports ou des mémoires. Pour cela, listons quelques fonctions :\n",
    "* `title` pour donner un titre au graphique (placé en haut par défaut)\n",
    "* `xlabel` et `ylabel` pour donner un nom aux axes\n",
    "* `axis` pour définir les valeurs minimales et maximales pour l'affichage des axes x et y (par exemple, si l'on fournit `[0, 10, -2, 2]` en paramètre à `axis`,  cela signifie que l'on souhaite que l'axe des x commence à $0$ et termine à $10$, et que l'axe des y commence à $-2$ et termine à $2$)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "b4abede3",
   "metadata": {},
   "outputs": [],
   "source": [
    "annees = [i for i in range(2010, 2022) ]\n",
    "temperatures_paris = [11.8, 13.7, 12.7, 12.1, 13.6, 13.4, 12.9, 13.4, 13.8, 13.6, 14.3, 12.8]\n",
    "temperatures_marseille = [14.8, 16.2, 15.8, 15.2, 16.8, 16.3, 16.4, 16.2, 17, 16.4, 16.5, 15.9]\n",
    "\n",
    "plt.plot(annees, temperatures_paris, color='blue')\n",
    "plt.plot(annees, temperatures_marseille, color='red')\n",
    "\n",
    "plt.xlabel('Année')\n",
    "plt.ylabel('Température (°C)')\n",
    "plt.title('Température annuelle moyenne à Paris et à Marseille, entre 2010 et 2021')\n",
    "plt.axis([2009, 2022, 8, 20])\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f4c9cb80",
   "metadata": {},
   "source": [
    "### Tracer une fonction\n",
    "\n",
    "Pour tracer une fonction \"usuelle\" $f : [a, b] \\to \\mathbb{R}$ avec ``matplotlib.pyplot``, une idée est de calculer les valeurs de $f(x)$ pour $x$ parcourant $[a, b]$ avec un petit pas.\n",
    "\n",
    "Par exemple, si on souhaite tracer la fonction $f : x \\mapsto x^2$ entre $-2$ et $2$, on va diviser l'intevalle en pas de $0.01$, puis calculer les $f(x)$ pour les valeurs $x = -2$, $x=-1.99$, $x=-1.98$, ..., $x=1.99$, $x=2$."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "f3a57d67",
   "metadata": {},
   "outputs": [],
   "source": [
    "a, b = [-2, 2]\n",
    "X = [a + 0.01 * i for i in range(401)]\n",
    "Y = [x**2 for x in X]\n",
    "\n",
    "plt.plot(X, Y)\n",
    "plt.show()"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "python",
   "language": "python",
   "name": "python"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
