{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<div style=\"width:100%\"><a href=\"https://www.dunod.com/sciences-techniques/programmation-python-par-pratique-problemes-et-exercices-corriges\"><img src=\"https://python.guillod.org/livre/banner.png\"/></a></div>\n",
    "\n",
    "Ce fichier reflète les énoncés des exercices d'un chapitre du livre *[Programmation Python par la pratique](https://www.dunod.com/sciences-techniques/programmation-python-par-pratique-problemes-et-exercices-corriges)*. Tous les énoncés peuvent être téléchargés au format [Jupyter Notebook](https://python.guillod.org/livre/) ou exécutés directement en ligne sur [GESIS](https://notebooks.gesis.org/binder/v2/gh/guillod/livre-python/v1errata). Les corrigés sont disponibles dans le livre en version papier (ISBN [9782100815142](https://www.dunod.com/sciences-techniques/programmation-python-par-pratique-problemes-et-exercices-corriges)) ou numérique (ISBN [9782100819089](https://www.dunod.com/sciences-techniques/programmation-python-par-pratique-problemes-et-exercices-corriges)) publiés chez Dunod. Ce fichier reflète les exercices tels que publiés dans cet ouvrage et diffère quelque peu des exercices présentés à la page [python.guillod.org](https://python.guillod.org/)."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 2 Structures de données"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<div id=\"ch:structures\"></div>\n",
    "\n",
    "Pour représenter des structures de données, Python propose quatre types de base: les listes (type `list`), les tuples (type `tuple`), les ensembles (type `set`) et les dictionnaires (type `dict`). Le but  de ce chapitre est de montrer les différences fondamentales entre ces structures de données et d'expliquer à quoi elles sont le plus adaptées. La documentation détaillée sur les structures de données est disponible [ici](https://docs.python.org/fr/3/tutorial/datastructures.html).\n",
    "\n",
    "**Concepts abordés:**\n",
    "\n",
    "* structures de données (liste, tuple, ensemble, dictionnaire)\n",
    "\n",
    "* types mutable et immutable\n",
    "\n",
    "* type hashable\n",
    "\n",
    "* compréhensions de liste, ensemble et dictionnaire\n",
    "\n",
    "* suites numériques\n",
    "\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Exercice 2.1: Listes"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<div id=\"exer:structures-listes\"></div>\n",
    "\n",
    "Une liste est une structure permettant de stocker des éléments hétérogènes:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "list0 = [0, 5.4, \"chaîne\", True]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Les listes sont mutables, c'est-à-dire qu'il est possible d'y modifier un élément, d'en rajouter un ou d'en supprimer un sans avoir à redéfinir toute la liste."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "list0[3] = False # remplace True par False\n",
    "list0.append(\"nouveau\") # ajoute la chaîne de caractères \"nouveau\" à la liste\n",
    "list0.insert(2, 34) # insère 34 à la place 2\n",
    "list0.remove(0) # enlève 0"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "En particulier, il faut faire attention en copiant une liste. Si l'on exécute le code suivant:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "list1 = list0\n",
    "list1[2] = \"change\"\n",
    "list0"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "alors `list0` est aussi modifié et est égal à `list1`. Pour créer une vraie copie, il faut utiliser le code suivant:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "list2 = list0.copy()\n",
    "list2[2] = \"rechange\"\n",
    "list0"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "qui ne modifie pas `list0`.\n",
    "À noter qu'il est possible de modifier les éléments d'une liste à l'intérieur d'une fonction:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "def f(l):\n",
    "    l[0] = 0\n",
    "f(list0)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Enfin il est possible de créer des listes à l'aide de la compréhension de listes:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "list1 = [2*i+1 for i in range(10)]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**a)**\n",
    "Chercher dans la documentation la syntaxe pour concaténer deux listes.\n",
    "\n",
    "**Indication.**\n",
    "Voir la documentation [ici](https://docs.python.org/fr/3/library/stdtypes.html#sequence-types-list-tuple-range).\n",
    "\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "\n",
    "**b)**\n",
    "Chercher dans la documentation la syntaxe pour extraire une tranche d'une liste, c'est-à-dire: si `a` est par exemple une liste de longueur 10, retourner les éléments de 6 à 9.\n",
    "\n",
    "**Indication.**\n",
    "Voir la documentation [ici](https://docs.python.org/fr/3/library/stdtypes.html#sequence-types-list-tuple-range).\n",
    "\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "\n",
    "**c)**\n",
    "Chercher dans la documentation la syntaxe pour retourner la longueur d'une liste.\n",
    "\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "\n",
    "**d)**\n",
    "Écrire une fonction `fibonacci(N)` qui retourne la liste des $N\\geq2$ premiers termes de la suite de Fibonacci définie par $u_{n+2} = u_{n+1}+u_n$ avec $u_0=0$ et $u_1=1$.\n",
    "\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "\n",
    "**e)**\n",
    "Écrire une fonction `pascal(N)` qui retourne la $N$-ième ligne du triangle de Pascal:\n",
    "\n",
    "<center><img src=\"data:image/png;base64,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\" style=\"width:90%;max-width:150px;\"></center>\n",
    "\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "\n",
    "**f)**\n",
    "Soit les suites $(u_n)_{n\\in\\mathbb{N}}$ et $(v_n)_{n\\in\\mathbb{N}}$ définies par $u_0=1$, $v_0=1$, et"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "$$\n",
    "\\begin{align*}\n",
    "u_{n+1} &= u_n + v_n \\,, & v_{n+1} &= 2u _n - v_n \\,,\n",
    "\\end{align*}\n",
    "$$"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "pour $n\\geq0$. Calculer $u_{100}$ et $v_{100}$.\n",
    "\n",
    "**Réponse.**\n",
    "$u_{100}=v_{100}=717897987691852588770249$.\n",
    "\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "\n",
    "**g)**\n",
    "Écrire une fonction `vk(n0,K)`, qui pour deux entiers $n_0$ et $K\\geq1$ calcule la suite des valeurs $v_k$ définies par $v_0 = n_0$ et"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "$$\n",
    "v_{k+1}=\\begin{cases}\n",
    "3v_{k}+1 & \\text{si $v_{k}$ est impair},\\\\ \n",
    "\\frac{v_{k}}{2} & \\text{si $v_{k}$ est pair},\n",
    "\\end{cases}\n",
    "$$"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "pour $0 \\leq k < K$. Pour $K = 1 000$ et diverses valeurs de $n_0 \\in \\{10, 100, 1 000, 10 000\\}$, afficher les cinq dernières\n",
    "valeurs calculées, c'est-à-dire $(v_{K-4},v_{K-3},v_{K-2},v_{K-1},v_K)$.\n",
    "\n",
    "**Réponse.**\n",
    "Les assertions suivantes sont vraies:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "vk(10,1000) == [1, 4, 2, 1, 4]\n",
    "vk(100,1000) == [2, 1, 4, 2, 1]\n",
    "vk(1000,1000) == [1, 4, 2, 1, 4]\n",
    "vk(10000,1000) == [4, 2, 1, 4, 2]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "\n",
    "<!-- --- end exercise --- -->\n",
    "\n",
    "\n",
    "\n",
    "\n",
    "<!-- --- begin exercise --- -->"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Exercice 2.2: Tuples"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<div id=\"exer:structures-tuples\"></div>\n",
    "\n",
    "Les tuples permettent tout comme les listes de stocker des éléments hétérogènes:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "tuple0 = (0, 5.4, \"chaîne\", True)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Mais au contraire des listes, les tuples ne sont pas mutables. Il n'est pas possible d'y modifier un élément, d'en rajouter un ou d'en supprimer un sans redéfinir tout le tuple. L'avantage d'un tuple sur une liste est qu'il tuple est hashable, c'est-à-dire qu'il peut être utilisé comme clef dans un dictionnaire.\n",
    "\n",
    "Enfin il est possible d'affecter des variables à l'intérieur d'un tuple, par exemple:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "(a,b) = (1,9)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Cela est en particulier très utile pour échanger deux variables sans avoir à utiliser une variable supplémentaire:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "(a,b) = (b,a)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**a)**\n",
    "Vérifier qu'un tuple est bien immutable.\n",
    "\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "\n",
    "**b)**\n",
    "Définir une fonction `mdlast(lst,val)` ayant pour argument une liste de tuples d'entiers `lst` et un entier `val` et retourner la liste de tuples avec le dernier élément de chaque tuple remplacé par `val`. Par exemple si `lst = [(10, 20), (30, 40, 50, 60), (70, 80, 90)]` alors `mdlast(lst,100)` doit retourner `[(10, 100), (30, 40, 50, 100), (70, 80, 100)]`.\n",
    "\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "\n",
    "**c)**\n",
    "Comment convertir un tuple en liste et réciproquement ?\n",
    "\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Exercice 2.3: Ensembles"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<div id=\"exer:structures-ensembles\"></div>\n",
    "\n",
    "Les ensembles permettent de stocker des éléments hétérogènes au sens mathématique de la théorie des ensembles:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "set0 = {0, 5.4, \"chaîne\", True}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Il est possible de tester si un élément appartient à un ensemble:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "if \"chaîne\" in set0:\n",
    "    print(\"dedans\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Les ensembles sont mutables, il est donc possible de rajouter ou retirer un élément d'un ensemble:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "set0.add(18) # ajoute 18 à l'ensemble\n",
    "set0.add(0) # ajoute 0 à l'ensemble (ne fait rien car 0 est déjà dedans)\n",
    "set0.remove(\"chaîne\") # retire \"chaîne de l'ensemble"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "En revanche les ensembles ne peuvent contenir que des éléments hashables, c'est-à-dire immutables. En particulier un ensemble ne peut pas contenir un autre ensemble:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "set1 = {{1,2},{3},{4}}\n",
    "TypeError: unhashable type: 'set'"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "À noter qu'il existe également en Python des ensembles immutables `frozenset`:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "frozenset0 = frozenset([0, 5.4, \"chaîne\", True])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Une chaîne de caractères peut être transformée en ensemble:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "set1 = set('abracadabra')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Comme pour les listes, il est possible de faire des compréhensions d'ensembles:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "set2 = {x for x in 'abracadabra' if x not in 'abc'}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Dans cet exemple, les chaînes de caractères sont automatiquement transformées en ensemble.\n",
    "À noter que l'ensemble vide est défini par `set()`.\n",
    "\n",
    "**a)**\n",
    "Définir une fonction `divisible(n)` qui retourne l'ensemble des nombres entiers divisibles par `n` inférieurs ou égaux à 100.\n",
    "\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "\n",
    "**b)**\n",
    "Chercher dans la documentation comment faire l'intersection, l'union et la différence de deux ensembles. Déterminer les nombres inférieurs ou égaux à 100 qui sont non divisibles par 2 mais divisibles par 3 et 5.\n",
    "\n",
    "**Indication.**\n",
    "Voir la documentation de `set` [ici](https://docs.python.org/fr/3/library/stdtypes.html#set).\n",
    "\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Exercice 2.4: Dictionnaires"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<div id=\"exer:structures-dictionnaires\"></div>\n",
    "\n",
    "Les dictionnaires sont une structure permettant de stocker des éléments hétérogènes indexés par des clefs (elles aussi hétérogènes):"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "dict0 = {\"pommes\": 0, \"poires\": 4, 12: 2}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Les éléments d'un dictionnaire sont accessibles par les clefs:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 32,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "dict0[\"pommes\"]\n",
    "dict0[12]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Un dictionnaire peut être vu comme un tableau associatif associant à chaque clef une valeur. La liste des clefs et celle des valeurs sont accessibles respectivement avec `dict0.keys()` et `dict0.values()`.\n",
    "Les dictionnaires sont mutables, il est donc possible de modifier une association clef-valeur et d'en rajouter ou supprimer une:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 33,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "dict0[\"pommes\"] = 3 # modifie la valeur associée à pommes\n",
    "dict0[\"oranges\"] = \"beaucoup\" # rajoute oranges comme clef avec la valeur \"beaucoup\"\n",
    "del dict0[\"poires\"] # supprime le couple clef-valeur associé à poires\n",
    "dict0.pop(\"pommes\") # supprime le couple clef-valeur associé à pommes"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Bien qu'un dictionnaire soit mutable, les clefs qui le composent doivent être des objets hashables, c'est-à-dire immutables. Ainsi une liste ou un ensemble ne peuvent pas servir de clefs dans un dictionnaire:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 34,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "dict0[list0] = \"test\"\n",
    "TypeError: unhashable type: 'list'\n",
    "dict0[set0] = \"retest\"\n",
    "TypeError: unhashable type: 'set'"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "En revanche il est possible d'avoir un tuple ou un frozenset comme clef:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 35,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "dict0[tuple0] = \"test\"\n",
    "dict0[frozenset0] = \"rest\""
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "d'où l'intérêt des frozensets.\n",
    "Comme pour les listes et les ensembles, il est possible de faire des compréhensions de dictionnaires:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 36,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "dict1 = {x: x**2 for x in range(5)}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Finalement une chose intéressante avec les dictionnaires est l'unpaking illustré par l'exemple suivant:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 37,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "def add(a=0, b=0):\n",
    "    return a + b\n",
    "d = {'a': 2, 'b': 3}\n",
    "add(**d)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**a)**\n",
    "Comment définir un dictionnaire vide ?\n",
    "\n",
    "**b)**\n",
    "Comment concaténer plusieurs dictionnaires entre eux ?\n",
    "\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "\n",
    "**c)**\n",
    "On considère une liste de mots:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 40,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "mots = ['Abricot', 'Airelle', 'Ananas', 'Banane', 'Cassis', 'Cerise', 'Citron', 'Clémentine', 'Coing', 'Datte', 'Fraise', 'Framboise', 'Grenade', 'Groseille', 'Kaki', 'Kiwi', 'Litchi', 'Mandarine', 'Mangue', 'Melon', 'Mirabelle', 'Nectarine', 'Orange', 'Pamplemousse', 'Papaye', 'Pêche', 'Poire', 'Pomme', 'Prune', 'Raisin']"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Écrire une fonction `position(mots, x, n)` qui retourne la liste des mots ayant le caractère `x` comme `n`-ième lettre.\n",
    "\n",
    "**Réponse.**\n",
    "Par exemple `position(mots,'e',4)` doit retourner la liste:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 41,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "['Clémentine', 'Datte', 'Groseille', 'Pêche', 'Poire', 'Pomme', 'Prune']"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "\n",
    "**d)**\n",
    "En imaginant que la liste des mots soit très longue, alors à chaque évaluation de la fonction `position` l'ensemble des mots est parcouru, ce qui prend pas mal de temps. Pour améliorer cela, construire un dictionnaire `mots_dict` ayant pour clefs les tuples `(x,n)` et comme valeurs la liste des mots ayant le caractère `x` comme `n`-ième lettre, c'est-à-dire tel que `mots_dict[x,n]` retourne la même chose que `position(mots, x , n)` à l'ordre près. Ainsi la liste `mots` n'est parcourue qu'une seule fois lors de la construction du dictionnaire et ensuite l'évaluation du dictionnaire est extrêmement rapide pour n'importe quelle requête.\n",
    "\n"
   ]
  }
 ],
 "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.8.5"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}