diff --git a/Recursivité/TP_Recursivite.ipynb b/Recursivité/TP_Recursivite.ipynb new file mode 100644 index 0000000..ebf4ef2 --- /dev/null +++ b/Recursivité/TP_Recursivite.ipynb @@ -0,0 +1,298 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "46bf4ba0", + "metadata": {}, + "source": [ + "# TP : La Récursivité et le Diviser pour Régner\n", + "\n", + "## Objectifs :\n", + "- Comprendre le principe de la récursivité.\n", + "- Appliquer la récursivité pour résoudre des problèmes simples.\n", + "- Approfondir la méthode du **diviser pour régner** à travers des exemples concrets.\n", + "- Compléter un algorithme de **tri fusion**.\n", + "\n", + "### Rappel sur la récursivité :\n", + "La récursivité est une méthode où une fonction s'appelle elle-même pour résoudre un problème. Chaque appel de la fonction permet de simplifier le problème jusqu'à atteindre une condition de base (appelée **cas de base**) qui permet de terminer la récursion.\n", + "\n", + "**Exemple classique :** Calcul de la factorielle d'un nombre entier positif `n`.\n", + "```python\n", + "def factorielle(n):\n", + " if n == 0:\n", + " return 1 # Cas de base\n", + " else:\n", + " return n * factorielle(n-1) # Appel récursif\n", + "```" + ] + }, + { + "cell_type": "markdown", + "id": "ab363a2d", + "metadata": {}, + "source": [ + "### Exercice 1 : Fonction récursive `traduire_romain`\n", + "**But :** Écrire une fonction récursive `traduire_romain` qui prend en paramètre une chaîne de caractères non vide représentant un nombre écrit en chiffres romains, et qui renvoie son écriture décimale.\n", + "\n", + "**Consignes :**\n", + "- Chaque chiffre romain a une valeur : `I=1, V=5, X=10, L=50, C=100, D=500, M=1000`.\n", + "- Si un chiffre plus petit précède un chiffre plus grand (ex : IV), cela signifie qu'il faut soustraire la valeur du chiffre plus petit.\n", + " \n", + "**Exemple :**\n", + "```python\n", + "traduire_romain(\"IX\") # Renvoie 9\n", + "traduire_romain(\"MCMXCIV\") # Renvoie 1994\n", + "```\n", + "\n", + "**Indication :** Utilisez la récursion pour traiter un caractère à la fois, et soustrayez ou ajoutez en fonction de la position relative des caractères.\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "8e5b99eb", + "metadata": {}, + "outputs": [], + "source": [ + "# Commencez à écrire la fonction traduire_romain ici :\n", + "def traduire_romain(chaine):\n", + " pass\n", + "\n", + "# Exemple de test\n", + "print(traduire_romain(\"IX\")) # Doit afficher 9\n" + ] + }, + { + "cell_type": "markdown", + "id": "24c596a6", + "metadata": {}, + "source": [ + "### Exercice 2 : Compléter un Tri Fusion\n", + "**But :** Compléter l'algorithme du tri fusion.\n", + "\n", + "Le tri fusion est un exemple typique de la méthode de **diviser pour régner**. L'idée est de diviser le tableau en deux, de trier chaque moitié, puis de fusionner les deux moitiés triées.\n", + "\n", + "Voici un code partiellement écrit que vous devez compléter :\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "4672ddfc", + "metadata": {}, + "outputs": [], + "source": [ + "def tri_fusion(tab):\n", + " if len(tab) <= 1:\n", + " return tab # Cas de base\n", + " milieu = len(tab) // 2\n", + " gauche = tri_fusion(tab[:milieu]) # Appel récursif\n", + " droite = tri_fusion(tab[milieu:]) # Appel récursif\n", + " return fusionner(gauche, droite)\n", + "\n", + "def fusionner(gauche, droite):\n", + " tableau_fusionne = []\n", + " i, j = 0, 0\n", + " # Complétez la fonction pour fusionner les deux sous-tableaux ici :\n", + " # ---------------------------------------------\n", + "\n", + " # ---------------------------------------------\n", + " # Ajoutez ici les éléments restants des sous-tableaux\n", + " tableau_fusionne ...\n", + " tableau_fusionne ...\n", + " return tableau_fusionne\n", + "\n", + "# Test de la fonction tri_fusion\n", + "print(tri_fusion([38, 27, 43, 3, 9, 82, 10])) # Doit afficher une liste triée\n" + ] + }, + { + "cell_type": "markdown", + "id": "6a42b282", + "metadata": {}, + "source": [ + "### Exercice 3 : Diviser pour Régner — Recherche d'un élément dans un tableau\n", + "**But :** Implémenter la recherche d'un élément dans un tableau trié en utilisant la méthode de **diviser pour régner** (recherche dichotomique).\n", + "\n", + "La recherche dichotomique consiste à diviser le tableau en deux parties à chaque étape :\n", + "- Si l'élément recherché est au milieu, vous avez terminé.\n", + "- Si l'élément est plus petit que l'élément du milieu, il se trouve dans la première moitié du tableau.\n", + "- Sinon, il se trouve dans la deuxième moitié.\n", + "\n", + "Voici un squelette à compléter :\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b4ced24d", + "metadata": {}, + "outputs": [], + "source": [ + "def recherche_dichotomique(tab, element, debut=0, fin=None):\n", + " if fin is None:\n", + " fin = len(tab) - 1\n", + " if debut > fin:\n", + " return -1 # L'élément n'est pas dans le tableau\n", + " milieu = ...\n", + " if tab[milieu] == element:\n", + " return ... # L'élément est trouvé\n", + " # Complétez ici avec les appels récursifs manquants :\n", + " # --------------------------------------------------\n", + " \n", + " # --------------------------------------------------\n", + " \n", + "# Test de la fonction\n", + "tab = [3, 9, 10, 27, 38, 43, 82]\n", + "element = 27\n", + "print(recherche_dichotomique(tab, element)) # Doit afficher l'index de l'élément trouvé\n" + ] + }, + { + "cell_type": "markdown", + "id": "0b7d4ec9", + "metadata": {}, + "source": [ + "### Exercice 4 : " + ] + }, + { + "cell_type": "markdown", + "id": "a6669740", + "metadata": {}, + "source": [ + "On considère des tableaux de nombres dont tous les éléments sont présents exactement trois fois à la suite, sauf un élément qui est présent une unique fois et que l'on appelle « l'intrus ». \n", + "\n", + "Voici quelques exemples :" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "1fd8e3e5", + "metadata": {}, + "outputs": [], + "source": [ + "\n", + "\n", + "tab_a = [3, 3, 3, 9, 9, 9, 1, 1, 1, 7, 2, 2, 2, 4, 4, 4, 8, 8, 8, 5,\n", + "5, 5]\n", + "#l'intrus est 7\n", + "tab_b = [8, 5, 5, 5, 9, 9, 9, 18, 18, 18, 3, 3, 3]\n", + "#l'intrus est 8\n", + "tab_c = [5, 5, 5, 1, 1, 1, 0, 0, 0, 6, 6, 6, 3, 8, 8, 8]\n", + "#l'intrus est 3\n" + ] + }, + { + "cell_type": "markdown", + "id": "39e0af5b", + "metadata": {}, + "source": [ + "On remarque qu'avec de tels tableaux :\n", + "- pour les indices multiples de 3 situés strictement avant l'intrus, l'élément\n", + "correspondant et son voisin de droite sont égaux,\n", + "- pour les indices multiples de 3 situés après l'intrus, l'élément correspondant et\n", + "son voisin de droite - s'il existe - sont différents.\n", + "\n", + "\n", + "Ce que l'on peut observer ci-dessous en observant les valeurs des paires de voisins\n", + "marquées par des caractères ^ :" + ] + }, + { + "cell_type": "markdown", + "id": "4b18edcb", + "metadata": {}, + "source": [ + "[3, 3, 3, 9, 9, 9, 1, 1, 1, 7, 2, 2, 2, 4, 4, 4, 8, 8, 8, 5, 5, 5]\n", + "\n", + "\n", + "^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^\n", + "\n", + "\n", + "0 3 6 9 12 15 18 21 " + ] + }, + { + "cell_type": "markdown", + "id": "ec77719b", + "metadata": {}, + "source": [ + "Dans des listes comme celles ci-dessus, un algorithme récursif pour trouver l'intrus consiste alors à choisir un indice i multiple de 3 situé approximativement au milieu des indices parmi lesquels se trouve l'intrus.\n", + "\n", + "\n", + "Puis, en fonction des valeurs de l'élément d'indice i et de son voisin de droite, à appliquer récursivement l'algorithme à la moitié droite ou à la moitié gauche des indices parmi lesquels se trouve l'intrus." + ] + }, + { + "cell_type": "markdown", + "id": "d8eadcb1", + "metadata": {}, + "source": [ + "Par exemple, si on s’intéresse à l’indice 12, on voit les valeurs 2 et 4 qui sont différentes : l’intrus est donc à gauche de l’indice 12 (indice 12 compris).\n", + "\n", + "\n", + "En revanche, si on s’intéresse à l’indice 3, on voit les valeurs 9 et 9 qui sont identiques : l’intrus est donc à droite des indices 3-4-5, donc à partir de l’indice 6." + ] + }, + { + "cell_type": "markdown", + "id": "46e17050", + "metadata": {}, + "source": [ + "Compléter la fonction récursive **trouver_intrus** proposée page suivante qui met\n", + "en œuvre cet algorithme." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "38558d62", + "metadata": {}, + "outputs": [], + "source": [ + "def trouver_intrus(tab, g, d):\n", + " '''Renvoie la valeur de l'intrus situé entre les indices g et d dans la liste tab où : tab vérifie les conditions de l'exercice, g et d sont des multiples de 3.\n", + " \n", + " '''\n", + " if g == d:\n", + " return ...\n", + " else:\n", + " nombre_de_triplets = (d – g) // ...\n", + " indice = g + 3 * (nombre_de_triplets // 2)\n", + " if ... :\n", + " return ...\n", + " else:\n", + " return ..." + ] + }, + { + "cell_type": "markdown", + "id": "ddc432d3", + "metadata": {}, + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "base", + "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.12.4" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +}