{ "cells": [ { "cell_type": "markdown", "id": "b5a2bcdd", "metadata": { "nbsphinx": "hidden" }, "source": [ "[home](../index.ipynb) | [next: Encore plus d'exercices](more-exercises.ipynb)" ] }, { "cell_type": "markdown", "id": "d44479bc", "metadata": { "tags": [] }, "source": [ "# Banque d'exercices\n" ] }, { "cell_type": "markdown", "id": "9164fbb2", "metadata": {}, "source": [ "Cette page regroupe les exercices proposés au gré de la formation.\n", "\n", "Certains des exercices sont des classiques revisités et d'autres sont librement inspirés d'[ici](https://inventwithpython.com/pythongently/) et de [là](https://dabeaz-course.github.io/practical-python/Notes/Contents.html)" ] }, { "cell_type": "markdown", "id": "b4034d3e-3017-41f4-9f16-6b1dfaf5801b", "metadata": { "jp-MarkdownHeadingCollapsed": true, "tags": [] }, "source": [ "## Exercice 1 : double" ] }, { "cell_type": "markdown", "id": "b6c23eee", "metadata": { "tags": [] }, "source": [ "### Énoncé\n", "\n", "Section [Introduction aux fonctions](../start-python/fonction-intro.ipynb)\n", "\n", "Écrire la fonction `double(x)` qui renvoie le double de `x`.\n", "\n", "Vérifier les résultats de cette fonction avec `assert`, par exemple:\n", "```python\n", "assert double(21) == 42\n", "assert double(0) == 0\n", "assert double(-99) == -198\n", "assert double(3150) == 6300\n", "```\n", "\n", "Voir ce qui se passe avec \n", "```python\n", "assert double(5)==9\n", "```" ] }, { "cell_type": "markdown", "id": "144f954e", "metadata": { "jp-MarkdownHeadingCollapsed": true, "tags": [] }, "source": [ "### Solution" ] }, { "cell_type": "code", "execution_count": 5, "id": "391b5fc1", "metadata": {}, "outputs": [], "source": [ "def double(x):\n", " return 2*x" ] }, { "cell_type": "code", "execution_count": 6, "id": "6f6d3509", "metadata": {}, "outputs": [], "source": [ "assert double(21) == 42\n", "assert double(0) == 0\n", "assert double(-99) == -198\n", "assert double(3150) == 6300" ] }, { "cell_type": "code", "execution_count": 7, "id": "0d0044a2", "metadata": {}, "outputs": [ { "ename": "AssertionError", "evalue": "", "output_type": "error", "traceback": [ "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m", "\u001b[1;31mAssertionError\u001b[0m Traceback (most recent call last)", "Cell \u001b[1;32mIn[7], line 1\u001b[0m\n\u001b[1;32m----> 1\u001b[0m \u001b[38;5;28;01massert\u001b[39;00m double(\u001b[38;5;241m5\u001b[39m)\u001b[38;5;241m==\u001b[39m\u001b[38;5;241m9\u001b[39m\n", "\u001b[1;31mAssertionError\u001b[0m: " ] } ], "source": [ "assert double(5)==9" ] }, { "cell_type": "markdown", "id": "da13da78-3b8d-4c03-be2f-586268e71280", "metadata": { "jp-MarkdownHeadingCollapsed": true, "tags": [] }, "source": [ "## Exercice 2 : conversion de température" ] }, { "cell_type": "markdown", "id": "1b593cba-84b4-45e2-9dab-234ffc30a94c", "metadata": { "jp-MarkdownHeadingCollapsed": true, "tags": [] }, "source": [ "### Énoncé\n", "\n", "Section [Introduction aux fonctions](../start-python/fonction-intro.ipynb)\n", "\n", "Écrire la fonction `to_celsius(temp)` qui renvoie en °C la température `temp` donnée en °F.\n", "\n", "[La formule est donnée par $ Celsius = \\frac{5}{9}(Fahrenheit - 32) $](https://fr.wikipedia.org/wiki/Degr%C3%A9_Fahrenheit).\n", "\n", "Écrire la fonction inverse `to_farenheit(temp)`.\n", "\n", "Vérifier les résultats :\n", "```python\n", "assert to_celsius(32) == 0\n", "assert to_farenheit(100) == 212\n", "assert to_celsius(-40) == -40\n", "assert to_farenheit(-40) == -40\n", "assert to_celsius(to_farenheit(15.)) == 15.\n", "```\n", "\n", "*[source de l'exercice](http://inventwithpython.com/pythongently/exercise2/)*" ] }, { "cell_type": "markdown", "id": "b88996b8-f956-4cd7-98e7-f4236231bb57", "metadata": { "jp-MarkdownHeadingCollapsed": true, "tags": [] }, "source": [ "### Solution" ] }, { "cell_type": "code", "execution_count": 15, "id": "223bbffe-ca05-4430-827c-2db31aea3863", "metadata": {}, "outputs": [], "source": [ "def to_celsius(temp):\n", " return 5/9 * (temp-32)\n", "\n", "def to_farenheit(temp):\n", " return temp * 9/5 +32" ] }, { "cell_type": "code", "execution_count": 16, "id": "d13b4d16-592d-478e-8fdb-694d4cbe5dd3", "metadata": { "tags": [] }, "outputs": [], "source": [ "assert to_celsius(32) == 0\n", "assert to_farenheit(100) == 212\n", "assert to_celsius(-40) == -40\n", "assert to_farenheit(-40) == -40\n", "assert to_celsius(to_farenheit(15.)) == 15." ] }, { "cell_type": "markdown", "id": "c169aa1e-f19a-4dc8-bab0-64510bfe8a64", "metadata": { "jp-MarkdownHeadingCollapsed": true, "tags": [] }, "source": [ "## Exercice 3 : conversion de secondes" ] }, { "cell_type": "markdown", "id": "bf0d75fd-81b0-4163-934b-a8d0490ee85f", "metadata": { "tags": [] }, "source": [ "### Énoncé\n", "\n", "Section [Introduction aux fonctions](../start-python/fonction-intro.ipynb)\n", "\n", "Écrire une fonction `h_m_s(seconds)` qui convertit un nombre total de secondes `h_m_s(seconds)` en heures, minutes et secondes sous la forme d'une chaine de caractères. Les nombres seront des entiers, et les secondes restantes seront arrondies à l'entier inférieur.\n", "\n", "Vérifier les résultats :\n", "```python\n", "assert h_m_s(0) == '0h 0m 0s'\n", "assert h_m_s(60) == '0h 1m 0s'\n", "assert h_m_s(3600) == '1h 0m 0s'\n", "assert h_m_s(5700) == '1h 35m 0s'\n", "assert h_m_s(18453) == '5h 7m 33s'\n", "assert h_m_s(60.12586) == '0h 1m 0s'\n", "```\n", "\n", "### Étape 2\n", "\n", "Section [Structure de contrôle](../start-python/controle-flux.ipynb)\n", "\n", "Mettre à jour la fonction pour qu'elle n'affiche les heures et minutes que si nécessaire.\n", "\n", "```python\n", "assert h_m_s(0) == '00s'\n", "assert h_m_s(60) == '01m 00s'\n", "assert h_m_s(3600) == '1h 00m 00s'\n", "assert h_m_s(5700) == '1h 35m 00s'\n", "assert h_m_s(18453) == '5h 07m 33s'\n", "assert h_m_s(60.12586) == '01m 00s'\n", "```\n", "\n", "### Étape 3\n", "\n", "Section [Utilisation avancée des chaines de caractères](../more-python/string-template.ipynb)\n", "\n", "Mettre à jour la fonction afin qu'elle affiche les minutes et les secondes sur 2 caractères.\n", "\n", "```python\n", "assert h_m_s(0) == '00s'\n", "assert h_m_s(60) == '01m 00s'\n", "assert h_m_s(3600) == '1h 00m 00s'\n", "assert h_m_s(5700) == '01h 35m 00s'\n", "assert h_m_s(18453) == '05h 07m 33s'\n", "assert h_m_s(60.12586) == '01m 00s'\n", "```\n", "\n", "*[source de l'exercice](http://inventwithpython.com/pythongently/exercise11/)*" ] }, { "cell_type": "markdown", "id": "3f1312f1-8864-4cec-8435-e2e01658115e", "metadata": { "jp-MarkdownHeadingCollapsed": true, "tags": [] }, "source": [ "### Solution (étape 1)" ] }, { "cell_type": "code", "execution_count": 34, "id": "d6df5460-ecfb-40ee-9d13-0f0e9dd13cef", "metadata": { "tags": [] }, "outputs": [], "source": [ "def h_m_s(seconds):\n", " seconds = int(seconds)\n", " hours = seconds//3600\n", " seconds = seconds%3600\n", " minutes = seconds//60\n", " seconds = seconds%60\n", " result = str(hours) + 'h ' + str(minutes) + 'm ' + str(seconds) + 's'\n", " return result" ] }, { "cell_type": "code", "execution_count": 35, "id": "c9a56d1b-76ea-473d-ad38-fcfdbd9cbf90", "metadata": { "tags": [] }, "outputs": [], "source": [ "assert h_m_s(0) == '0h 0m 0s'\n", "assert h_m_s(60) == '0h 1m 0s'\n", "assert h_m_s(3600) == '1h 0m 0s'\n", "assert h_m_s(5700) == '1h 35m 0s'\n", "assert h_m_s(18453) == '5h 7m 33s'\n", "assert h_m_s(60.12586) == '0h 1m 0s'" ] }, { "cell_type": "markdown", "id": "d5da1df9-97ea-4cf6-80ed-ca5112d62007", "metadata": { "jp-MarkdownHeadingCollapsed": true, "tags": [] }, "source": [ "### Solution (étape 2, avec `if`)" ] }, { "cell_type": "code", "execution_count": 36, "id": "7c30f4eb-e6f8-40a9-9d78-c80790ddfa15", "metadata": {}, "outputs": [], "source": [ "def h_m_s(seconds):\n", " seconds = int(seconds)\n", " hours = seconds//3600\n", " seconds = seconds%3600\n", " minutes = seconds//60\n", " seconds = seconds%60\n", " if hours > 0:\n", " result = str(hours) + 'h ' + str(minutes) + 'm '\n", " elif minutes > 0:\n", " result = str(minutes) + 'm '\n", " else:\n", " result = ''\n", " result = result + str(seconds) + 's'\n", " return result" ] }, { "cell_type": "code", "execution_count": 37, "id": "4d5786c5-cca2-4801-8088-caa625a8b36e", "metadata": { "tags": [] }, "outputs": [], "source": [ "assert h_m_s(0) == '0s'\n", "assert h_m_s(60) == '1m 0s'\n", "assert h_m_s(3600) == '1h 0m 0s'\n", "assert h_m_s(5700) == '1h 35m 0s'\n", "assert h_m_s(18453) == '5h 7m 33s'\n", "assert h_m_s(60.12586) == '1m 0s'" ] }, { "cell_type": "markdown", "id": "ae6703c1-605f-452a-9134-bd2304391452", "metadata": { "jp-MarkdownHeadingCollapsed": true, "tags": [] }, "source": [ "### Solution (étape 3, avec `f-string`)" ] }, { "cell_type": "code", "execution_count": 38, "id": "5d3385df-3708-4247-9f25-8e28d18adc32", "metadata": {}, "outputs": [], "source": [ "def h_m_s(seconds):\n", " seconds = int(seconds)\n", " hours = seconds//3600\n", " seconds = seconds%3600\n", " minutes = seconds//60\n", " seconds = seconds%60\n", " if hours > 0:\n", " hours = f'{hours}h '\n", " else:\n", " hours = ''\n", " if minutes > 0 or hours:\n", " minutes = f'{minutes:>02}m '\n", " else:\n", " minutes = ''\n", " seconds = f'{seconds:>02}s'\n", " return f'{hours}{minutes}{seconds}'" ] }, { "cell_type": "code", "execution_count": 39, "id": "be77c719-7580-4dca-8b3e-5fac22d556cf", "metadata": { "tags": [] }, "outputs": [], "source": [ "assert h_m_s(0) == '00s'\n", "assert h_m_s(60) == '01m 00s'\n", "assert h_m_s(3600) == '1h 00m 00s'\n", "assert h_m_s(5700) == '1h 35m 00s'\n", "assert h_m_s(18453) == '5h 07m 33s'\n", "assert h_m_s(60.12586) == '01m 00s'" ] }, { "cell_type": "markdown", "id": "ba0904a0-4590-4c2e-bf74-a465d8605744", "metadata": { "jp-MarkdownHeadingCollapsed": true, "tags": [] }, "source": [ "## Exercice 4 : liste de zéros" ] }, { "cell_type": "markdown", "id": "df02b7d9-456a-4d87-868e-f2734aac0973", "metadata": { "tags": [] }, "source": [ "### Énoncé\n", "\n", "Section [Les conteneurs de base](../start-python/data-structures.ipynb)\n", "\n", "Créer une fonction `make_zeros_list(nzeros)` qui renvoie une liste avec `nzeros` 0 sous la forme de flottants.\n", "\n", "La fonction s'assurera que `nzeros` est un entier positif mais traitera le cas `nzeros=0`.\n", "\n", "Vérifier les résultats :\n", "```python\n", "assert make_zeros_list(5) == [0., 0., 0., 0., 0.]\n", "assert make_zeros_list(1) == [0.]\n", "assert make_zeros_list(0) == []\n", "```" ] }, { "cell_type": "markdown", "id": "3d88f1b0-44e0-4130-aa3c-f7b0df7890ed", "metadata": { "jp-MarkdownHeadingCollapsed": true, "tags": [] }, "source": [ "### Solution" ] }, { "cell_type": "code", "execution_count": 1, "id": "a6d7e40d-8469-424a-b6d6-877b67181c3e", "metadata": {}, "outputs": [], "source": [ "def make_zeros_list(nzeros):\n", " assert isinstance(nzeros, int)\n", " assert nzeros >= 0\n", " return [0.]*nzeros" ] }, { "cell_type": "code", "execution_count": 2, "id": "37a47c6c-e739-4d6e-b757-46a7e8ba2ba0", "metadata": { "tags": [] }, "outputs": [], "source": [ "assert make_zeros_list(5) == [0., 0., 0., 0., 0.]\n", "assert make_zeros_list(1) == [0.]\n", "assert make_zeros_list(0) == []" ] }, { "cell_type": "markdown", "id": "31c559af-c20a-4170-a1ee-73c241961db8", "metadata": { "jp-MarkdownHeadingCollapsed": true, "tags": [] }, "source": [ "## Exercice 5 : compte occurences" ] }, { "cell_type": "markdown", "id": "d7d03c12-4fd0-49bf-9092-ed516ebabaa7", "metadata": { "tags": [] }, "source": [ "### Énoncé\n", "\n", "Section [Structure de contrôle](../start-python/controle-flux.ipynb)\n", "\n", "Ecrire une fonction `compte_occurences(chaîne)` qui compte le nombre d'occurrences de chaque caractère dans la chaîne de caractères `chaîne`.\n", "La fonction retournera un `dict` où les clés seront les caractères rencontrés et les valeurs, le nombre d'occurences de chaque caractère.\n", "\n", "Vérifier les résultats :\n", "```python\n", "assert compte_occurences('python') == {'h': 1,'n': 1, 'o': 1, 'p': 1, 't': 1, 'y': 1}\n", "assert compte_occurences('cool') == {'c': 1, 'l': 1, 'o': 2}\n", "```\n", "\n", "### Étape 2\n", "\n", "Section [Utilisation avancée des conteneurs](../more-python/container-methods.ipynb)\n", "\n", "Mettre à jour la fonction en utilisant une/des méthode(s) des dictionnaires.\n", "\n", "Vérifier les résultats (identiques aux précédents)\n", "\n", "### Bonus\n", "\n", "Section [Qu'est-ce qu'un module ?](../python-modules/intro.ipynb)\n", "\n", "La librairie standard ne proposerait-elle pas déjà quelque chose? Au hasard, module [*collections*](https://docs.python.org/3/library/collections.html)?\n", "\n", "Vérifier les résultats (identiques aux précédents)" ] }, { "cell_type": "markdown", "id": "0ae3b7d4-1acd-4b7a-b982-e6b17773d0b2", "metadata": { "jp-MarkdownHeadingCollapsed": true, "tags": [] }, "source": [ "### Solution (étape 1)" ] }, { "cell_type": "code", "execution_count": 2, "id": "e952a72e-4caf-4d50-8d5d-314eef61dcda", "metadata": { "tags": [] }, "outputs": [], "source": [ "def compte_occurences(chaîne):\n", " mon_dico = {}\n", " for char in chaîne:\n", " if char in mon_dico:\n", " mon_dico[char] += 1\n", " else:\n", " mon_dico[char] = 1\n", " return mon_dico" ] }, { "cell_type": "code", "execution_count": 3, "id": "20278c2c-7063-461e-a1f4-286e79e91098", "metadata": { "tags": [] }, "outputs": [], "source": [ "assert compte_occurences('python') == {'h': 1,'n': 1, 'o': 1, 'p': 1, 't': 1, 'y': 1}\n", "assert compte_occurences('cool') == {'c': 1, 'l': 1, 'o': 2}" ] }, { "cell_type": "markdown", "id": "ba662d60-817b-45ec-8a66-ae02d402e050", "metadata": { "jp-MarkdownHeadingCollapsed": true, "tags": [] }, "source": [ "### Solution (étape 2, avec méthode)" ] }, { "cell_type": "code", "execution_count": 25, "id": "cb68dbbb-7186-4717-bb6e-318eb8d05ac5", "metadata": {}, "outputs": [], "source": [ "def compte_occurences(chaîne):\n", " mon_dico = {}\n", " for char in chaîne:\n", " mon_dico[char] = mon_dico.get(char, 0) + 1\n", " return mon_dico\n", "\n", "def compte_occurences(chaîne):\n", " # Variante\n", " mon_dico = {}\n", " for char in chaîne:\n", " mon_dico.setdefault(char, 0)\n", " mon_dico[char] += 1\n", " return mon_dico" ] }, { "cell_type": "code", "execution_count": 26, "id": "b440c063-0ce6-4ae6-929a-af322e91ce30", "metadata": { "tags": [] }, "outputs": [], "source": [ "assert compte_occurences('python') == {'h': 1,'n': 1, 'o': 1, 'p': 1, 't': 1, 'y': 1}\n", "assert compte_occurences('cool') == {'c': 1, 'l': 1, 'o': 2}" ] }, { "cell_type": "markdown", "id": "c3934093-8f0c-4f29-83b8-669ce0c151c4", "metadata": { "jp-MarkdownHeadingCollapsed": true, "tags": [] }, "source": [ "### Solution (bonus)" ] }, { "cell_type": "code", "execution_count": 68, "id": "7f228171-d61d-4d80-b7ce-10515dce4278", "metadata": {}, "outputs": [], "source": [ "from collections import Counter as compte_occurences" ] }, { "cell_type": "code", "execution_count": 69, "id": "66229579-211b-4479-9d9f-c4366b83b0ea", "metadata": { "tags": [] }, "outputs": [], "source": [ "assert compte_occurences('python') == {'h': 1,'n': 1, 'o': 1, 'p': 1, 't': 1, 'y': 1}\n", "assert compte_occurences('cool') == {'c': 1, 'l': 1, 'o': 2}" ] }, { "cell_type": "markdown", "id": "1f325932-5d38-4f8a-a606-442327a52afb", "metadata": {}, "source": [ "Pourtant, ce que retourne la fonction n'est pas un dictionnaire?" ] }, { "cell_type": "code", "execution_count": 70, "id": "ba907d9a-61c6-4a8e-928d-520cd1e26b4c", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "Counter({'p': 1, 'y': 1, 't': 1, 'h': 1, 'o': 1, 'n': 1})" ] }, "execution_count": 70, "metadata": {}, "output_type": "execute_result" } ], "source": [ "compte_occurences('python')" ] }, { "cell_type": "markdown", "id": "13ca8d82-d5fd-47cb-83ef-85e5a569af11", "metadata": {}, "source": [ "**Mais**, Python s'occupe de la conversion derrière le rideau lors du test de comparaison!" ] }, { "cell_type": "code", "execution_count": 71, "id": "cfe0aed1-7a00-4224-b0cb-c3ab62b90828", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "{'p': 1, 'y': 1, 't': 1, 'h': 1, 'o': 1, 'n': 1}" ] }, "execution_count": 71, "metadata": {}, "output_type": "execute_result" } ], "source": [ "dict(compte_occurences('python'))" ] }, { "cell_type": "markdown", "id": "37601f14-75c5-4712-b7c6-4e1a5fb65e66", "metadata": { "jp-MarkdownHeadingCollapsed": true, "tags": [] }, "source": [ "## Exercice 6 : suite de Collatz" ] }, { "cell_type": "markdown", "id": "3c193abb-e7f8-4cc8-99e6-be37bf013578", "metadata": { "tags": [] }, "source": [ "### Énoncé\n", "\n", "Section [Structure de contrôle](../start-python/controle-flux.ipynb)\n", "\n", "Construire une fonction `collatz(n)` qui, partant d'un nombre entier `n`, construit la [suite de Collatz](https://fr.wikipedia.org/wiki/Lothar_Collatz#Suite_de_Collatz)\n", "qui est définie selon :\n", "```\n", " | u(n)/2 si u(n) est pair\n", "u(n+1) = | \n", " | 3u(n)+1 sinon\n", "```\n", "\n", "La fonction vérifiera que `n` est un entier positif et retournera une liste avec les valeurs de la suite.\n", "\n", "**NB:** arrêter la boucle de construction dès lors que `u(n) = 1` ([conjecture de Collatz](https://fr.wikipedia.org/wiki/Conjecture_de_Syracuse))\n", "\n", "Vérifier les résultats :\n", "```python\n", "assert collatz(1) == [1]\n", "assert collatz(10) == [10, 5, 16, 8, 4, 2, 1]\n", "assert collatz(11) == [11, 34, 17, 52, 26, 13, 40, 20, 10, 5, 16, 8, 4, 2, 1]\n", "assert collatz(12) == [12, 6, 3, 10, 5, 16, 8, 4, 2, 1]\n", "assert len(collatz(256)) == 9\n", "assert len(collatz(257)) == 123\n", "```\n", "\n", "*[source de l'exercice](http://inventwithpython.com/pythongently/exercise39/)*\n", "\n", "### Bonus\n", "\n", "Section [Les générateurs](../more-python/generator.ipynb)\n", "\n", "Plutôt que de retourner une liste, on pourrait produire un générateur : `gen_collatz(n)`. \n", "L'intérêt est d'économiser de la mémoire, mais il peut être moins évident d'interroger la séquence : valeur maximum ? taille ?" ] }, { "cell_type": "markdown", "id": "e1f59699-10cb-431b-88b0-84e244d64412", "metadata": { "jp-MarkdownHeadingCollapsed": true, "tags": [] }, "source": [ "### Solution" ] }, { "cell_type": "code", "execution_count": 45, "id": "26afd937-b419-4530-9d13-08c33579494c", "metadata": {}, "outputs": [], "source": [ "def collatz(n):\n", " assert isinstance(n, int)\n", " assert n > 0\n", " sequence = [n]\n", " while n != 1:\n", " is_even = n%2==0\n", " if is_even:\n", " n //= 2\n", " else:\n", " n = 3*n+1\n", " sequence.append(n)\n", " return sequence" ] }, { "cell_type": "code", "execution_count": 46, "id": "febdcb9e-4141-4bb1-8f58-61000679eafa", "metadata": { "tags": [] }, "outputs": [], "source": [ "assert collatz(1) == [1]\n", "assert collatz(10) == [10, 5, 16, 8, 4, 2, 1]\n", "assert collatz(11) == [11, 34, 17, 52, 26, 13, 40, 20, 10, 5, 16, 8, 4, 2, 1]\n", "assert collatz(12) == [12, 6, 3, 10, 5, 16, 8, 4, 2, 1]\n", "assert len(collatz(256)) == 9\n", "assert len(collatz(257)) == 123" ] }, { "cell_type": "markdown", "id": "c0c6609d-74d1-4705-be9f-04262950fa43", "metadata": { "jp-MarkdownHeadingCollapsed": true, "tags": [] }, "source": [ "### Solution (bonus)" ] }, { "cell_type": "code", "execution_count": 2, "id": "e2b99043-4bc5-4833-9a36-9dd9d44c701c", "metadata": {}, "outputs": [], "source": [ "def gen_collatz(n):\n", " assert isinstance(n, int)\n", " assert n > 0\n", " yield n\n", " while n != 1:\n", " is_even = n%2==0\n", " if is_even:\n", " n //= 2\n", " else:\n", " n = 3*n+1\n", " yield n" ] }, { "cell_type": "code", "execution_count": 4, "id": "fb3a2dc6-5f3c-4169-94be-9ed1b3a3cf78", "metadata": {}, "outputs": [], "source": [ "assert list(gen_collatz(1)) == [1]\n", "assert list(gen_collatz(10)) == [10, 5, 16, 8, 4, 2, 1]\n", "assert list(gen_collatz(11)) == [11, 34, 17, 52, 26, 13, 40, 20, 10, 5, 16, 8, 4, 2, 1]\n", "assert list(gen_collatz(12)) == [12, 6, 3, 10, 5, 16, 8, 4, 2, 1]\n", "assert len(list(gen_collatz(256))) == 9\n", "assert len(list(gen_collatz(257))) == 123\n", "assert max(gen_collatz(10)) == 16\n", "assert max(gen_collatz(11)) == 52\n", "assert max(gen_collatz(12)) == 16" ] }, { "cell_type": "markdown", "id": "19c720a6-fc85-407d-ae34-b19e8986ff68", "metadata": { "jp-MarkdownHeadingCollapsed": true, "tags": [] }, "source": [ "## Exercice 7 : statistiques d'un échantillon" ] }, { "cell_type": "markdown", "id": "f9dc6486-2d20-4fae-ba3d-d790b3d18a91", "metadata": { "tags": [] }, "source": [ "### Énoncé\n", "\n", "Section [Lire et écrire des fichiers](../more-python/open-files.ipynb)\n", "\n", "Créer une fonction `get_stats(fname)` qui renvoie les minimum, maximum, moyenne et écart-type d'une liste de nombres lus dans un fichier de nom `fname`.\n", "\n", "Le résultat se fera sous la forme d'un dictionnaire de clés `'min'`, `'max'`, `'mean'`, `'std'`.\n", "\n", "**NB** :\n", "- les fonctions `min`, `max`, `mean`, `std` peuvent être importées depuis le module numpy\n", "- on admettra que le fichier d'entrée n'a qu'une seule valeur par ligne, du type :\n", "```shell\n", "3548.279704\n", "3589.7804263\n", "3095.09156402\n", "...\n", "```\n", "\n", "Vérifier les résultats :\n", "```python\n", "assert get_stats('demo_stats.txt') # s'assure que la fonction ne retourne pas un dictionnaire vide\n", "assert get_stats('demo_stats.txt')['min'] == 2561.50070722\n", "assert get_stats('demo_stats.txt')['max'] == 3722.25284478\n", "assert np.allclose(get_stats('demo_stats.txt')['mean'], 3150)\n", "assert np.allclose(get_stats('demo_stats.txt')['std'], 314)\n", "```" ] }, { "cell_type": "markdown", "id": "a5fe4c1f-1f03-4e30-a9bb-d5c61e21c518", "metadata": { "jp-MarkdownHeadingCollapsed": true, "tags": [] }, "source": [ "### Solution" ] }, { "cell_type": "code", "execution_count": 54, "id": "fcd9a9d6-3b48-4111-a974-871c062be79e", "metadata": {}, "outputs": [], "source": [ "import numpy as np\n", "\n", "def get_stats(fname):\n", " values = []\n", " with open(fname) as rd:\n", " for line in rd:\n", " values.append(float(line.strip()))\n", " return dict(\n", " min=np.min(values),\n", " max=np.max(values),\n", " mean=np.mean(values),\n", " std=np.std(values)\n", " )" ] }, { "cell_type": "code", "execution_count": 66, "id": "430fb0ed-89d8-426e-8b48-25e6795ed0a5", "metadata": {}, "outputs": [], "source": [ "assert get_stats('demo_stats.txt') # s'assure que la fonction ne retourne pas un dictionnaire vide\n", "assert get_stats('demo_stats.txt')['min'] == 2561.50070722\n", "assert get_stats('demo_stats.txt')['max'] == 3722.25284478\n", "assert np.allclose(get_stats('demo_stats.txt')['mean'], 3150)\n", "assert np.allclose(get_stats('demo_stats.txt')['std'], 314)" ] }, { "cell_type": "markdown", "id": "0e6dab67-51fc-42a8-afa8-88052218d5c7", "metadata": { "tags": [] }, "source": [ "### Bonus" ] }, { "cell_type": "markdown", "id": "8107bfdf-d85d-4347-96e0-8edcf4fd8262", "metadata": {}, "source": [ "**Ne pas réinventer la roue, des librairies font très bien le travail!**" ] }, { "cell_type": "code", "execution_count": 67, "id": "afd605f9-27ae-49b0-a0f2-15efbfce836b", "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
Sample
count50.000000
mean3150.000000
std317.187899
min2561.500707
25%2950.424439
50%3160.149710
75%3414.406663
max3722.252845
\n", "
" ], "text/plain": [ " Sample\n", "count 50.000000\n", "mean 3150.000000\n", "std 317.187899\n", "min 2561.500707\n", "25% 2950.424439\n", "50% 3160.149710\n", "75% 3414.406663\n", "max 3722.252845" ] }, "execution_count": 67, "metadata": {}, "output_type": "execute_result" } ], "source": [ "import pandas as pd\n", "values = pd.read_csv('demo_stats.txt', names=['Sample'])\n", "values.describe()" ] }, { "cell_type": "markdown", "id": "e910e6e8-a7ab-45a5-bb99-22960fabbd19", "metadata": { "jp-MarkdownHeadingCollapsed": true, "tags": [] }, "source": [ "## Exercice 8 : filtrage de liste" ] }, { "cell_type": "markdown", "id": "461c4e00-8025-4e61-a390-e7dab7f2e624", "metadata": { "jp-MarkdownHeadingCollapsed": true }, "source": [ "### Énoncé\n", "\n", "Section [Listes en intension](../more-python/list-comprehension.ipynb)\n", "\n", "Créer une fonction `keep_positive(values)` qui recoit une liste de valeurs et renvoie une liste similaire mais avec seulement les valeurs positives.\n", "\n", "Vérifier les résultats :\n", "```python\n", "assert keep_positive([4, 5, 2, 9]) == [4, 5, 2, 9]\n", "assert keep_positive([1, -2, 3, -4]) == [1, 3]\n", "assert keep_positive([-1, -2]) == []\n", "```" ] }, { "cell_type": "markdown", "id": "ac90106b-038d-4ec4-a42d-e2245c433a71", "metadata": { "jp-MarkdownHeadingCollapsed": true, "tags": [] }, "source": [ "### Solution" ] }, { "cell_type": "code", "execution_count": 8, "id": "2d1885ea-8d7b-4ef5-88bb-0dfa23dc76d7", "metadata": {}, "outputs": [], "source": [ "keep_positive = lambda values: [v for v in values if v>=0]" ] }, { "cell_type": "code", "execution_count": 9, "id": "774ecc86-bbe1-4c42-9035-34096fd15546", "metadata": {}, "outputs": [], "source": [ "assert keep_positive([4, 5, 2, 9]) == [4, 5, 2, 9]\n", "assert keep_positive([1, -2, 3, -4]) == [1, 3]\n", "assert keep_positive([-1, -2]) == []" ] }, { "cell_type": "markdown", "id": "d8e78718-7966-4929-b5a7-a6c860f9e645", "metadata": { "jp-MarkdownHeadingCollapsed": true, "tags": [] }, "source": [ "## Exercice 9 : matrice de zéros" ] }, { "cell_type": "markdown", "id": "f47baf5d-980e-440d-843c-47a7f3d2befb", "metadata": {}, "source": [ "### Enoncé\n", "\n", "Section [Noms et objets non immuables](../more-python/naming-vs-pointer.ipynb)\n", "\n", "Créer une fonction `make_zeros_matrix(nrows, ncols)` qui produit une liste de `nrows` listes, chacune remplie de `ncols` zéros. \n", "Cette structure imbriquée est un prototype pour une représentation de matrice, on peut jouer à y affecter des valeurs dans des cellules via une double indexation.\n", "\n", "Une idée pourrait être la suivante:\n", "```python\n", "# It's a trap !\n", "def make_zeros_matrix(nrows, ncols):\n", " return [[0] * ncols] * nrows\n", "```\n", "Mais il s'avère que la matrice produite a un problème... lequel ?\n", "\n", "Vérifier les résultats :\n", "```python\n", "assert make_zeros_matrix(1, 1) == [[0]]\n", "assert make_zeros_matrix(4, 0) == [[], [], [], []]\n", "assert make_zeros_matrix(0, 4) == []\n", "assert make_zeros_matrix(3, 2) == [[0, 0],\n", " [0, 0],\n", " [0, 0]]\n", "mat = make_zeros_matrix(2, 3)\n", "assert mat == [[0, 0, 0],\n", " [0, 0, 0]]\n", "mat[0][0] = 1\n", "assert mat == [[1, 0, 0],\n", " [0, 0, 0]]\n", "```" ] }, { "cell_type": "markdown", "id": "9977e11d-911c-4e9b-83c3-4c4a585136ce", "metadata": { "jp-MarkdownHeadingCollapsed": true, "tags": [] }, "source": [ "### Solution" ] }, { "cell_type": "code", "execution_count": 20, "id": "0be8912a-7534-492a-a7d8-9801a83a2912", "metadata": {}, "outputs": [], "source": [ "def make_zeros_matrix(nrows, ncols):\n", " matrix = []\n", " for _ in range(nrows):\n", " matrix.append([0] * ncols)\n", " return matrix" ] }, { "cell_type": "code", "execution_count": 21, "id": "25cfebcf-85f2-4f2a-8a8b-47a9493ccf8f", "metadata": {}, "outputs": [], "source": [ "assert make_zeros_matrix(1, 1) == [[0]]\n", "assert make_zeros_matrix(4, 0) == [[], [], [], []]\n", "assert make_zeros_matrix(0, 4) == []\n", "assert make_zeros_matrix(3, 2) == [[0, 0],\n", " [0, 0],\n", " [0, 0]]\n", "mat = make_zeros_matrix(2, 3)\n", "assert mat == [[0, 0, 0],\n", " [0, 0, 0]]\n", "mat[0][0] = 1\n", "assert mat == [[1, 0, 0],\n", " [0, 0, 0]]" ] }, { "cell_type": "markdown", "id": "1d7e0af7-41b1-4db4-bbe0-ca9332fe86a0", "metadata": {}, "source": [ "**Quel est le problème avec la suggestion de l'énoncé ?**\n", "\n", "La structure imbriquée construite contient en fait UNE SEULE LISTE POUR TOUTES LES LIGNES !!!\n", "\n", "Modifier une ligne va modifier cette liste, et donc modifier toutes les lignes..." ] }, { "cell_type": "code", "execution_count": 2, "id": "f5647b68-8036-40bf-b89d-a88b29d2a892", "metadata": {}, "outputs": [], "source": [ "def wrong_make_zeros_matrix(nrows, ncols):\n", " return [[0] * ncols] * nrows\n", "\n", "wrong_mat = wrong_make_zeros_matrix(2, 3)\n", "wrong_mat[0][0] = 1\n", "assert wrong_mat == [[1, 0, 0],\n", " [1, 0, 0]] # <- cette ligne ne devrait pas être modifiée !" ] }, { "cell_type": "markdown", "id": "f85465f1-9c28-4dda-b22d-eadc963beb40", "metadata": {}, "source": [ "**La preuve en images ci-dessous**\n", "\n", "[*lien*](https://pythontutor.com/render.html#code=def%20wrong_make_zeros_matrix%28nrows,%20ncols%29%3A%0A%20%20%20%20return%20%5B%5B0%5D%20*%20ncols%5D%20*%20nrows%0A%0Awrong_mat%20%3D%20wrong_make_zeros_matrix%282,%203%29%0Awrong_mat%5B0%5D%5B0%5D%20%3D%201&cumulative=false&curInstr=0&heapPrimitives=nevernest&mode=display&origin=opt-frontend.js&py=3&rawInputLstJSON=%5B%5D&textReferences=false)" ] }, { "cell_type": "code", "execution_count": 1, "id": "98273448-7da6-4f37-9374-a8525214b109", "metadata": { "tags": [] }, "outputs": [ { "data": { "text/html": [ "\n", " \n", " " ], "text/plain": [ "" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from IPython.display import IFrame\n", "IFrame(\"https://pythontutor.com/iframe-embed.html#code=def%20wrong_make_zeros_matrix%28nrows,%20ncols%29%3A%0A%20%20%20%20return%20%5B%5B0%5D%20*%20ncols%5D%20*%20nrows%0A%0Awrong_mat%20%3D%20wrong_make_zeros_matrix%282,%203%29%0Awrong_mat%5B0%5D%5B0%5D%20%3D%201&cumulative=false&curInstr=0&heapPrimitives=nevernest&mode=display&origin=opt-frontend.js&py=3&rawInputLstJSON=%5B%5D&textReferences=false\",\n", " width='100%', height=300)" ] } ], "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.11.4" } }, "nbformat": 4, "nbformat_minor": 5 }