{ "cells": [ { "cell_type": "markdown", "metadata": { "toc": "true" }, "source": [ "# Table of Contents\n", "
" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# TP 2 - Programmation pour la préparation à l'agrégation maths option info\n", "- En Python, version 3." ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "3.5.3 (default, Jan 19 2017, 14:11:04) \n", "[GCC 6.3.0 20170118]\n" ] } ], "source": [ "from sys import version\n", "print(version)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "----\n", "# Listes\n", "Ces exercices sont un peu foireux : les \"*listes*\" en Python **ne sont pas des listes simplement chaînées** !" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Exercice 1 : `taille`" ] }, { "cell_type": "code", "execution_count": 11, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "0" ] }, "execution_count": 11, "metadata": {}, "output_type": "execute_result" }, { "data": { "text/plain": [ "3" ] }, "execution_count": 11, "metadata": {}, "output_type": "execute_result" }, { "data": { "text/plain": [ "0" ] }, "execution_count": 11, "metadata": {}, "output_type": "execute_result" }, { "data": { "text/plain": [ "3" ] }, "execution_count": 11, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from typing import TypeVar, List\n", "_a = TypeVar('alpha')\n", "\n", "# O(n^2) temps, O(n) espace\n", "def taille(liste : List[_a]) -> int:\n", " if not liste:\n", " return 0\n", " else:\n", " queue = liste[1:]\n", " return 1 + taille(queue)\n", "\n", "taille([])\n", "taille([1, 2, 3])\n", "\n", "# O(n) temps, O(1) espace\n", "def taille(liste : List[_a]) -> int:\n", " longueur = 0\n", " for _ in liste:\n", " longueur += 1\n", " return longueur\n", "\n", "taille([])\n", "taille([1, 2, 3])" ] }, { "cell_type": "code", "execution_count": 12, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "4" ] }, "execution_count": 12, "metadata": {}, "output_type": "execute_result" } ], "source": [ "taille(\"OKOK\")" ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "0" ] }, "execution_count": 7, "metadata": {}, "output_type": "execute_result" }, { "data": { "text/plain": [ "3" ] }, "execution_count": 7, "metadata": {}, "output_type": "execute_result" } ], "source": [ "len([])\n", "len([1, 2, 3])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Exercice 2 : `concat`" ] }, { "cell_type": "code", "execution_count": 16, "metadata": {}, "outputs": [], "source": [ "from typing import TypeVar, List\n", "_a = TypeVar('alpha')\n", "\n", "def concatene(liste1 : List[_a], liste2 : List[_a]) -> List[_a]:\n", " # return liste1 + liste2 # easy solution\n", " liste = []\n", " for i in liste1:\n", " liste.append(i)\n", " for i in liste2:\n", " liste.append(i)\n", " return liste" ] }, { "cell_type": "code", "execution_count": 19, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[1, 2, 3, 4]" ] }, "execution_count": 19, "metadata": {}, "output_type": "execute_result" }, { "data": { "text/plain": [ "[1, 2, 3, 4]" ] }, "execution_count": 19, "metadata": {}, "output_type": "execute_result" } ], "source": [ "concatene([1, 2], [3, 4])\n", "[1, 2] + [3, 4]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Mais attention le typage est toujours optionnel en Python :" ] }, { "cell_type": "code", "execution_count": 20, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[1, 2, 'pas', 'entier', '?']" ] }, "execution_count": 20, "metadata": {}, "output_type": "execute_result" } ], "source": [ "concatene([1, 2], [\"pas\", \"entier\", \"?\"])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Exercice 3 : `appartient`" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "False" ] }, "execution_count": 3, "metadata": {}, "output_type": "execute_result" }, { "data": { "text/plain": [ "True" ] }, "execution_count": 3, "metadata": {}, "output_type": "execute_result" }, { "data": { "text/plain": [ "True" ] }, "execution_count": 3, "metadata": {}, "output_type": "execute_result" }, { "data": { "text/plain": [ "False" ] }, "execution_count": 3, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from typing import TypeVar, List\n", "_a = TypeVar('alpha')\n", "\n", "def appartient(x : _a, liste : List[_a]) -> bool:\n", " for y in liste:\n", " if x == y:\n", " return True # on stoppe avant la fin\n", " return False\n", "\n", "appartient(1, [])\n", "appartient(1, [1])\n", "appartient(1, [1, 2, 3])\n", "appartient(4, [1, 2, 3])" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "False" ] }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" }, { "data": { "text/plain": [ "True" ] }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" }, { "data": { "text/plain": [ "True" ] }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" }, { "data": { "text/plain": [ "False" ] }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from typing import TypeVar, List\n", "_a = TypeVar('alpha')\n", "\n", "def appartient2(x : _a, liste : List[_a]) -> bool:\n", " if not liste:\n", " return False\n", " if x == liste[0]:\n", " return True\n", " return appartient2(x, liste[1:]) # récursivement, pas récursif terminal\n", "\n", "appartient2(1, [])\n", "appartient2(1, [1])\n", "appartient2(1, [1, 2, 3])\n", "appartient2(4, [1, 2, 3])" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "False" ] }, "execution_count": 5, "metadata": {}, "output_type": "execute_result" }, { "data": { "text/plain": [ "True" ] }, "execution_count": 5, "metadata": {}, "output_type": "execute_result" }, { "data": { "text/plain": [ "True" ] }, "execution_count": 5, "metadata": {}, "output_type": "execute_result" }, { "data": { "text/plain": [ "False" ] }, "execution_count": 5, "metadata": {}, "output_type": "execute_result" } ], "source": [ "1 in []\n", "1 in [1]\n", "1 in [1, 2, 3]\n", "4 in [1, 2, 3]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Notre implémentation est évidemment plus lente que le test `x in liste` de la librarie standard...\n", "Mais pas tant :" ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "17.8 µs ± 1.15 µs per loop (mean ± std. dev. of 7 runs, 100000 loops each)\n", "24.5 µs ± 4.43 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)\n", "1.04 ms ± 79.5 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)\n" ] } ], "source": [ "import random\n", "%timeit random.randint(0, 500) in list(range(1000))\n", "%timeit appartient(random.randint(0, 500), list(range(1000)))\n", "%timeit appartient2(random.randint(0, 500), list(range(1000)))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Exercice 4 : `miroir`" ] }, { "cell_type": "code", "execution_count": 26, "metadata": {}, "outputs": [], "source": [ "from typing import TypeVar, List\n", "_a = TypeVar('alpha')\n", "\n", "def miroir(liste : List[_a]) -> List[_a]:\n", " # return liste[::-1] # version facile\n", " liste2 = []\n", " for x in liste:\n", " liste2.insert(0, x)\n", " return liste2" ] }, { "cell_type": "code", "execution_count": 28, "metadata": { "scrolled": true }, "outputs": [ { "data": { "text/plain": [ "[11, 7, 5, 3, 2]" ] }, "execution_count": 28, "metadata": {}, "output_type": "execute_result" }, { "data": { "text/plain": [ "[11, 7, 5, 3, 2]" ] }, "execution_count": 28, "metadata": {}, "output_type": "execute_result" } ], "source": [ "miroir([2, 3, 5, 7, 11])\n", "[2, 3, 5, 7, 11][::-1]" ] }, { "cell_type": "code", "execution_count": 29, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "968 ns ± 67.4 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)\n", "216 ns ± 8.77 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)\n" ] } ], "source": [ "%timeit miroir([2, 3, 5, 7, 11])\n", "%timeit [2, 3, 5, 7, 11][::-1]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Exercice 5 : `alterne`" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "La sémantique n'était pas très claire, mais on peut imaginer quelque chose comme ça :" ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [], "source": [ "from typing import TypeVar, List\n", "_a = TypeVar('alpha')\n", "\n", "def alterne(liste1 : List[_a], liste2 : List[_a]) -> List[_a]:\n", " liste3 = []\n", " i, j = 0, 0\n", " n, m = len(liste1), len(liste2)\n", " while i < n and j < m: # encore deux\n", " liste3.append(liste1[i])\n", " i += 1\n", " liste3.append(liste2[j])\n", " j += 1\n", " while i < n: # si n > m\n", " liste3.append(liste1[i])\n", " i += 1\n", " while j < m: # ou si n < m\n", " liste3.append(liste2[j])\n", " j += 1\n", " return liste3" ] }, { "cell_type": "code", "execution_count": 31, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[3, 2, 5, 4, 6]" ] }, "execution_count": 31, "metadata": {}, "output_type": "execute_result" }, { "data": { "text/plain": [ "[1, 2, 3, 4, 5, 6]" ] }, "execution_count": 31, "metadata": {}, "output_type": "execute_result" }, { "data": { "text/plain": [ "[1, 4, 3, 6, 5]" ] }, "execution_count": 31, "metadata": {}, "output_type": "execute_result" } ], "source": [ "alterne([3, 5], [2, 4, 6])\n", "alterne([1, 3, 5], [2, 4, 6])\n", "alterne([1, 3, 5], [4, 6])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "La complexité est linéaire en $\\mathcal{O}(\\max(|\\text{liste 1}|, |\\text{liste 2}|)$." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Exercice 6 : `nb_occurrences`" ] }, { "cell_type": "code", "execution_count": 32, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "0" ] }, "execution_count": 32, "metadata": {}, "output_type": "execute_result" }, { "data": { "text/plain": [ "1" ] }, "execution_count": 32, "metadata": {}, "output_type": "execute_result" }, { "data": { "text/plain": [ "3" ] }, "execution_count": 32, "metadata": {}, "output_type": "execute_result" }, { "data": { "text/plain": [ "0" ] }, "execution_count": 32, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from typing import TypeVar, List\n", "_a = TypeVar('alpha')\n", "\n", "def nb_occurrences(x : _a, liste : List[_a]) -> int:\n", " nb = 0\n", " for y in liste:\n", " if x == y:\n", " nb += 1\n", " return nb\n", "\n", "nb_occurrences(0, [1, 2, 3, 4])\n", "nb_occurrences(2, [1, 2, 3, 4])\n", "nb_occurrences(2, [1, 2, 2, 3, 2, 4])\n", "nb_occurrences(5, [1, 2, 3, 4])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Exercice 7 : `pairs`\n", "\n", "C'est un filtrage :" ] }, { "cell_type": "code", "execution_count": 33, "metadata": { "collapsed": true }, "outputs": [], "source": [ "filter?" ] }, { "cell_type": "code", "execution_count": 36, "metadata": {}, "outputs": [], "source": [ "from typing import List\n", "\n", "def pairs(liste : List[int]) -> List[int]:\n", " # return list(filter(lambda x : x % 2 == 0, liste))\n", " return [x for x in liste if x % 2 == 0]" ] }, { "cell_type": "code", "execution_count": 37, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[2, 4, 6]" ] }, "execution_count": 37, "metadata": {}, "output_type": "execute_result" }, { "data": { "text/plain": [ "[2, 4, 6, 100000]" ] }, "execution_count": 37, "metadata": {}, "output_type": "execute_result" }, { "data": { "text/plain": [ "[2, 4, 6, 100000000000]" ] }, "execution_count": 37, "metadata": {}, "output_type": "execute_result" }, { "data": { "text/plain": [ "[2, 4, 6, 1000000000000000000]" ] }, "execution_count": 37, "metadata": {}, "output_type": "execute_result" } ], "source": [ "pairs([1, 2, 3, 4, 5, 6])\n", "pairs([1, 2, 3, 4, 5, 6, 7, 100000])\n", "pairs([1, 2, 3, 4, 5, 6, 7, 100000000000])\n", "pairs([1, 2, 3, 4, 5, 6, 7, 1000000000000000000])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Exercice 8 : `range`" ] }, { "cell_type": "code", "execution_count": 84, "metadata": {}, "outputs": [], "source": [ "from typing import List\n", "\n", "def myrange(n : int) -> List[int]:\n", " liste = []\n", " i = 1\n", " while i <= n:\n", " liste.append(i)\n", " i += 1\n", " return liste" ] }, { "cell_type": "code", "execution_count": 85, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[1, 2, 3, 4]" ] }, "execution_count": 85, "metadata": {}, "output_type": "execute_result" } ], "source": [ "myrange(4)" ] }, { "cell_type": "code", "execution_count": 47, "metadata": { "collapsed": true }, "outputs": [], "source": [ "from typing import List\n", "\n", "def intervale(a : int, b : int=None) -> List[int]:\n", " if b == None:\n", " a, b = 1, a\n", " liste = []\n", " i = a\n", " while i <= b:\n", " liste.append(i)\n", " i += 1\n", " return liste" ] }, { "cell_type": "code", "execution_count": 48, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]" ] }, "execution_count": 48, "metadata": {}, "output_type": "execute_result" }, { "data": { "text/plain": [ "[1, 2, 3, 4]" ] }, "execution_count": 48, "metadata": {}, "output_type": "execute_result" } ], "source": [ "intervale(10)\n", "intervale(1, 4)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Exercice 9 : `premiers`\n", "Plusieurs possibilités. Un filtre d'Erathosthène marche bien, ou une filtration.\n", "Je ne vais pas utiliser de tableaux donc on est un peu réduit d'utiliser une filtration (filtrage ? *pattern matching*)" ] }, { "cell_type": "code", "execution_count": 77, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "1" ] }, "execution_count": 77, "metadata": {}, "output_type": "execute_result" }, { "data": { "text/plain": [ "2" ] }, "execution_count": 77, "metadata": {}, "output_type": "execute_result" }, { "data": { "text/plain": [ "10" ] }, "execution_count": 77, "metadata": {}, "output_type": "execute_result" }, { "data": { "text/plain": [ "346" ] }, "execution_count": 77, "metadata": {}, "output_type": "execute_result" } ], "source": [ "def racine(n : int) -> int:\n", " i = 1\n", " for i in range(n + 1):\n", " if i*i > n:\n", " return i - 1\n", " return i\n", "\n", "racine(1)\n", "racine(5)\n", "racine(102)\n", "racine(120031)" ] }, { "cell_type": "code", "execution_count": 78, "metadata": {}, "outputs": [], "source": [ "from typing import List\n", "\n", "def intervale2(a : int, b : int, pas : int=1) -> List[int]:\n", " assert pas > 0\n", " liste = []\n", " i = a\n", " while i <= b:\n", " liste.append(i)\n", " i += pas\n", " return liste" ] }, { "cell_type": "code", "execution_count": 79, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]" ] }, "execution_count": 79, "metadata": {}, "output_type": "execute_result" }, { "data": { "text/plain": [ "[2, 5, 8, 11]" ] }, "execution_count": 79, "metadata": {}, "output_type": "execute_result" } ], "source": [ "intervale2(2, 12, 1)\n", "intervale2(2, 12, 3)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Une version purement fonctionnelle est moins facile qu'une version impérative avec une référence booléenne." ] }, { "cell_type": "code", "execution_count": 80, "metadata": {}, "outputs": [], "source": [ "def estDivisible(n : int, k : int) -> bool:\n", " return (n % k) == 0" ] }, { "cell_type": "code", "execution_count": 81, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "True" ] }, "execution_count": 81, "metadata": {}, "output_type": "execute_result" }, { "data": { "text/plain": [ "False" ] }, "execution_count": 81, "metadata": {}, "output_type": "execute_result" }, { "data": { "text/plain": [ "False" ] }, "execution_count": 81, "metadata": {}, "output_type": "execute_result" }, { "data": { "text/plain": [ "True" ] }, "execution_count": 81, "metadata": {}, "output_type": "execute_result" } ], "source": [ "estDivisible(10, 2)\n", "estDivisible(10, 3)\n", "estDivisible(10, 4)\n", "estDivisible(10, 5)" ] }, { "cell_type": "code", "execution_count": 107, "metadata": { "collapsed": true }, "outputs": [], "source": [ "def estPremier(n : int) -> bool:\n", " return (n == 2) or (n == 3) or not any(map(lambda k: estDivisible(n, k), intervale2(2, racine(n), 1)))" ] }, { "cell_type": "code", "execution_count": 108, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "2 []\n", "3 []\n", "4 [True]\n", "5 [False]\n", "6 [True]\n", "7 [False]\n", "8 [True]\n", "9 [False, True]\n", "10 [True, False]\n", "11 [False, False]\n", "12 [True, True]\n", "13 [False, False]\n", "14 [True, False]\n", "15 [False, True]\n", "16 [True, False, True]\n", "17 [False, False, False]\n", "18 [True, True, False]\n", "19 [False, False, False]\n" ] } ], "source": [ "for n in range(2, 20):\n", " print(n, list(map(lambda k: estDivisible(n, k), intervale2(2, racine(n), 1))))" ] }, { "cell_type": "code", "execution_count": 109, "metadata": {}, "outputs": [], "source": [ "from typing import List\n", "\n", "def premiers(n : int) -> List[int]:\n", " return [p for p in intervale2(2, n, 1) if estPremier(p)]" ] }, { "cell_type": "code", "execution_count": 110, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[2, 3, 5, 7]" ] }, "execution_count": 110, "metadata": {}, "output_type": "execute_result" } ], "source": [ "premiers(10)" ] }, { "cell_type": "code", "execution_count": 111, "metadata": { "scrolled": true }, "outputs": [ { "data": { "text/plain": [ "[2,\n", " 3,\n", " 5,\n", " 7,\n", " 11,\n", " 13,\n", " 17,\n", " 19,\n", " 23,\n", " 29,\n", " 31,\n", " 37,\n", " 41,\n", " 43,\n", " 47,\n", " 53,\n", " 59,\n", " 61,\n", " 67,\n", " 71,\n", " 73,\n", " 79,\n", " 83,\n", " 89,\n", " 97]" ] }, "execution_count": 111, "metadata": {}, "output_type": "execute_result" } ], "source": [ "premiers(100)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "----\n", "# Quelques tris par comparaison" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "On fera les tris en ordre croissant." ] }, { "cell_type": "code", "execution_count": 27, "metadata": { "scrolled": true }, "outputs": [], "source": [ "test = [3, 1, 8, 4, 5, 6, 1, 2]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Exercice 10 : Tri insertion" ] }, { "cell_type": "code", "execution_count": 28, "metadata": {}, "outputs": [], "source": [ "from typing import TypeVar, List\n", "_a = TypeVar('alpha')\n", "\n", "# Temps O(n^2) à cause des recopies, espace O(n)\n", "def insere(x : _a, liste : List[_a]) -> List[_a]:\n", " if len(liste) == 0:\n", " return [x]\n", " else:\n", " t, q = liste[0], liste[1:]\n", " if x <= t:\n", " return [x] + liste\n", " else:\n", " return [t] + insere(x, q)" ] }, { "cell_type": "code", "execution_count": 29, "metadata": {}, "outputs": [], "source": [ "# Temps O(n^3) à cause des recopies, espace O(n^2)\n", "def tri_insertion(liste : List[_a]) -> List[_a]:\n", " if len(liste) == 0:\n", " return []\n", " else:\n", " t, q = liste[0], liste[1:]\n", " return insere(t, tri_insertion(q))" ] }, { "cell_type": "code", "execution_count": 30, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[1, 1, 2, 3, 4, 5, 6, 8]" ] }, "execution_count": 30, "metadata": {}, "output_type": "execute_result" } ], "source": [ "tri_insertion(test)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Complexité en temps $\\mathcal{O}(n^2)$ si on faisait les recopies correctement, $\\mathcal{O}(n^3)$ ici." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Exercice 11 : Tri insertion générique" ] }, { "cell_type": "code", "execution_count": 31, "metadata": {}, "outputs": [], "source": [ "from typing import TypeVar, List, Callable\n", "_a = TypeVar('alpha')\n", "\n", "def insere2(ordre : Callable[[_a, _a], bool], x : _a, liste : List[_a]) -> List[_a]:\n", " if len(liste) == 0:\n", " return [x]\n", " else:\n", " t, q = liste[0], liste[1:]\n", " if ordre(x, t):\n", " return [x] + liste\n", " else:\n", " return [t] + insere2(ordre, x, q)" ] }, { "cell_type": "code", "execution_count": 32, "metadata": {}, "outputs": [], "source": [ "def tri_insertion2(ordre : Callable[[_a, _a], bool], liste : List[_a]) -> List[_a]:\n", " if len(liste) == 0:\n", " return []\n", " else:\n", " t, q = liste[0], liste[1:]\n", " return insere2(ordre, t, tri_insertion2(ordre, q))" ] }, { "cell_type": "code", "execution_count": 33, "metadata": {}, "outputs": [], "source": [ "ordre_croissant = lambda x, y: x <= y" ] }, { "cell_type": "code", "execution_count": 34, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[1, 1, 2, 3, 4, 5, 6, 8]" ] }, "execution_count": 34, "metadata": {}, "output_type": "execute_result" } ], "source": [ "tri_insertion2(ordre_croissant, test)" ] }, { "cell_type": "code", "execution_count": 35, "metadata": {}, "outputs": [], "source": [ "ordre_decroissant = lambda x, y: x >= y" ] }, { "cell_type": "code", "execution_count": 36, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[8, 6, 5, 4, 3, 2, 1, 1]" ] }, "execution_count": 36, "metadata": {}, "output_type": "execute_result" } ], "source": [ "tri_insertion2(ordre_decroissant, test)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Exercice 12 : Tri selection" ] }, { "cell_type": "code", "execution_count": 37, "metadata": {}, "outputs": [], "source": [ "from typing import TypeVar, List, Tuple\n", "_a = TypeVar('alpha')\n", "\n", "def selectionne_min(liste : List[_a]) -> Tuple[_a, List[_a]]:\n", " if len(liste) == 0:\n", " raise ValueError(\"Selectionne_min sur liste vide\")\n", " else:\n", " def cherche_min(mini : _a, autres : List[_a], reste : List[_a]) -> Tuple[_a, List[_a]]:\n", " if len(reste) == 0:\n", " return (mini, autres)\n", " else:\n", " t, q = reste[0], reste[1:]\n", " if t < mini:\n", " return cherche_min(t, [mini] + autres, q)\n", " else:\n", " return cherche_min(mini, [t] + autres, q)\n", " t, q = liste[0], liste[1:]\n", " return cherche_min(t, [], q)" ] }, { "cell_type": "code", "execution_count": 38, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[3, 1, 8, 4, 5, 6, 1, 2]" ] }, "execution_count": 38, "metadata": {}, "output_type": "execute_result" }, { "data": { "text/plain": [ "(1, [2, 1, 6, 5, 4, 8, 3])" ] }, "execution_count": 38, "metadata": {}, "output_type": "execute_result" } ], "source": [ "test\n", "selectionne_min(test)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "(On voit que la liste `autre` a été inversée)" ] }, { "cell_type": "code", "execution_count": 39, "metadata": {}, "outputs": [], "source": [ "def tri_selection(liste : List[_a]) -> List[_a]:\n", " if len(liste) == 0:\n", " return []\n", " else:\n", " mini, autres = selectionne_min(liste)\n", " return [mini] + tri_selection(autres)" ] }, { "cell_type": "code", "execution_count": 40, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[1, 1, 2, 3, 4, 5, 6, 8]" ] }, "execution_count": 40, "metadata": {}, "output_type": "execute_result" } ], "source": [ "tri_selection(test)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Complexité en temps : $\\mathcal{O}(n^2)$." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Exercices 13, 14, 15 : Tri fusion" ] }, { "cell_type": "code", "execution_count": 41, "metadata": {}, "outputs": [], "source": [ "from typing import TypeVar, List, Tuple\n", "_a = TypeVar('alpha')\n", "\n", "def separe(liste : List[_a]) -> Tuple[List[_a], List[_a]]:\n", " if len(liste) == 0:\n", " return ([], [])\n", " elif len(liste) == 1:\n", " return ([liste[0]], [])\n", " else:\n", " x, y, q = liste[0], liste[1], liste[2:]\n", " a, b = separe(q)\n", " return ([x] + a, [y] + b)" ] }, { "cell_type": "code", "execution_count": 42, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[3, 1, 8, 4, 5, 6, 1, 2]" ] }, "execution_count": 42, "metadata": {}, "output_type": "execute_result" }, { "data": { "text/plain": [ "([3, 8, 5, 1], [1, 4, 6, 2])" ] }, "execution_count": 42, "metadata": {}, "output_type": "execute_result" } ], "source": [ "test\n", "separe(test)" ] }, { "cell_type": "code", "execution_count": 43, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[1, 2, 3, 3, 7, 8]" ] }, "execution_count": 43, "metadata": {}, "output_type": "execute_result" } ], "source": [ "def fusion(liste1 : List[_a], liste2 : List[_a]) -> List[_a]:\n", " if (len(liste1), len(liste2)) == (0, 0):\n", " return []\n", " elif len(liste1) == 0:\n", " return liste2\n", " elif len(liste2) == 0:\n", " return liste1\n", " else: # les deux sont non vides\n", " x, a = liste1[0], liste1[1:]\n", " y, b = liste2[0], liste2[1:]\n", " if x <= y:\n", " return [x] + fusion(a, [y] + b)\n", " else:\n", " return [y] + fusion([x] + a, b)\n", "\n", " \n", "fusion([1, 3, 7], [2, 3, 8])" ] }, { "cell_type": "code", "execution_count": 44, "metadata": {}, "outputs": [], "source": [ "def tri_fusion(liste : List[_a]) -> List[_a]:\n", " if len(liste) <= 1:\n", " return liste\n", " else:\n", " a, b = separe(liste)\n", " return fusion(tri_fusion(a), tri_fusion(b))" ] }, { "cell_type": "code", "execution_count": 45, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[1, 1, 2, 3, 4, 5, 6, 8]" ] }, "execution_count": 45, "metadata": {}, "output_type": "execute_result" } ], "source": [ "tri_fusion(test)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Complexité en temps $\\mathcal{O}(n \\log n)$." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Comparaisons" ] }, { "cell_type": "code", "execution_count": 46, "metadata": { "scrolled": true }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "8.62 µs ± 329 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)\n", "34 µs ± 802 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)\n", "21 µs ± 262 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)\n" ] } ], "source": [ "%timeit tri_insertion(test)\n", "%timeit tri_selection(test)\n", "%timeit tri_fusion(test)" ] }, { "cell_type": "code", "execution_count": 47, "metadata": {}, "outputs": [], "source": [ "from sys import setrecursionlimit\n", "setrecursionlimit(100000)\n", "# nécessaire pour tester les différentes fonctions récursives sur de grosses listes" ] }, { "cell_type": "code", "execution_count": 48, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[-423, -966, 54, 851, 192, -290, -845, -426, -837, -598]" ] }, "execution_count": 48, "metadata": {}, "output_type": "execute_result" } ], "source": [ "test_random(10)" ] }, { "cell_type": "code", "execution_count": 50, "metadata": {}, "outputs": [], "source": [ "import timeit" ] }, { "cell_type": "code", "execution_count": 54, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "For n = 10\n", " and tri = tri_insertion\n", "0.04783497499738587\n", " and tri = tri_selection\n", "0.06762562999938382\n", " and tri = tri_fusion\n", "0.0398557940061437\n", "\n", "For n = 100\n", " and tri = tri_insertion\n", "1.7052169400049024\n", " and tri = tri_selection\n", "3.4673834670029464\n", " and tri = tri_fusion\n", "0.940109923001728\n", "\n", "For n = 1000\n", " and tri = tri_insertion\n" ] }, { "ename": "KeyboardInterrupt", "evalue": "", "output_type": "error", "traceback": [ "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", "\u001b[0;31mKeyboardInterrupt\u001b[0m Traceback (most recent call last)", "\u001b[0;32m