{
"cells": [
{
"cell_type": "markdown",
"id": "55bf8f76",
"metadata": {},
"source": [
"# Neuvième exercice JavaScript"
]
},
{
"cell_type": "markdown",
"id": "74595666",
"metadata": {},
"source": [
"
"
]
},
{
"cell_type": "markdown",
"id": "30847ac2",
"metadata": {},
"source": [
"
"
]
},
{
"cell_type": "markdown",
"id": "0638a4c2",
"metadata": {},
"source": [
"*Résumé en français* : Des lapins naissent et deviennent matures au bout de 1 mois, âge auquel ils pourront se reproduire.\n",
"Créez une fonction qui détermine le nombre de **paires de lapins** matures après `n` mois en commençant par un **unique** couple de lapins immatures et qui se reproduisent à raison de `b` paires à la fin de chaque mois. Voir le tableau ci-dessus dans le cas de `n` = 5 mois avec un taux de reproduction de `b` = 3 pour bien comprendre le déroulement. Quelques autres exemples :\n",
"\n",
"
>> lapins(0, 4)\n",
"0 # Après 0 mois, il n'y a pas de paire adultes\n",
">> lapins(1, 4)\n",
"1 # Après 1 mois, une seule paire d'adultes\n",
">>lapins(4, 0)\n",
"1 # Lapins stériles (taux = 0), on reste à 1\n",
">> lapins(6, 3) \n",
"40 \n",
">> lapins(8, 12)\n",
"8425\n",
">> lapins(7, 4)\n",
"181 \n",
"\n",
"# (1 0) > (0 1) > (4 1) > (4 5) > (20 9) > (36 29) > (116 65) > 181"
]
},
{
"cell_type": "markdown",
"id": "7a1ada45",
"metadata": {},
"source": [
"Cet exercice étant assez facile, proposons **différentes versions** :"
]
},
{
"cell_type": "markdown",
"id": "bab884f1",
"metadata": {},
"source": [
"## Une simple boucle"
]
},
{
"cell_type": "markdown",
"id": "b4d90e1f",
"metadata": {},
"source": [
"On part de **0** adulte et d'une paire de lapins **immatures**. **Chaque mois**, le nouveau nombre d'**immatures** est **égal** au nombre d'**adultes qui se reproduisent avec un taux** `b` (c'est-à-dire la multiplication du nombre d'adultes par le coefficient `b`). Et le nouveau nombre d'**adultes** est égal au nombre d'**adultes précédents** + les **immatures précédents** qui deviennent adultes.\n",
"\n",
"Il faut faire attention à l'écriture du processus, voici une version **INCORRECTE** :"
]
},
{
"cell_type": "code",
"execution_count": 1,
"id": "9f140906",
"metadata": {},
"outputs": [],
"source": [
" var lapins = (n, b) => {\n",
" let [immatures, adultes] = [1, 0];\n",
" for (let i = 0; i < n; i++) {\n",
" immatures = adultes * b; // on écrase immatures trop tôt\n",
" adultes += immatures;\n",
" }\n",
" return adultes;\n",
"}"
]
},
{
"cell_type": "markdown",
"id": "f2080430",
"metadata": {},
"source": [
"En effet, on commence par mettre à jour la variable `immatures` puis on utilise cette valeur à la ligne suivante, or nous avions besoin de la valeur **précédente** de `immatures` et non pas de la valeur actualisée. Une technique classique est d'utiliser une variable **temporaire** :"
]
},
{
"cell_type": "code",
"execution_count": 2,
"id": "8bc05d80",
"metadata": {},
"outputs": [],
"source": [
" var lapins = (n, b) => {\n",
" let [immatures, adultes] = [1, 0];\n",
" for (let i = 0; i < n; i++) {\n",
" temp = immatures // On mémorise valeur précédente\n",
" immatures = b * adultes\n",
" adultes += temp; // que l'on utilise ici\n",
" }\n",
" return adultes;\n",
"}"
]
},
{
"cell_type": "markdown",
"id": "8b742a73",
"metadata": {},
"source": [
"On peut également utiliser cette écriture **CORRECTE** :"
]
},
{
"cell_type": "code",
"execution_count": 3,
"id": "d807277a",
"metadata": {},
"outputs": [],
"source": [
" var lapins = (n, b) => {\n",
" let [immatures, adultes] = [1, 0];\n",
" for (let i = 0; i < n; i++) {\n",
" [immatures, adultes] = [adultes * b, immatures + adultes];\n",
" }\n",
" return adultes;\n",
"}"
]
},
{
"cell_type": "code",
"execution_count": 4,
"id": "63136c34",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"8425"
]
},
"execution_count": 4,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"lapins(8,12)"
]
},
{
"cell_type": "code",
"execution_count": 5,
"id": "d6284822",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"0"
]
},
"execution_count": 5,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"lapins(0,4)"
]
},
{
"cell_type": "code",
"execution_count": 6,
"id": "e3b8f30f",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"1"
]
},
"execution_count": 6,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"lapins(4,0)"
]
},
{
"cell_type": "markdown",
"id": "1e99f44c",
"metadata": {},
"source": [
"## Version récursive"
]
},
{
"cell_type": "markdown",
"id": "4eef2ea6",
"metadata": {},
"source": [
"Reprenons l'exemple proposé dans l'énoncé avec n = 5 et b = 3. Le nombre de paires d'adultes matures est successivement : 0 → 1 → 1 → 4 → 7 → 19"
]
},
{
"cell_type": "markdown",
"id": "d9d50440",
"metadata": {},
"source": [
"Si on note u la suite donnant le nombre d'adultes au fil des mois, on a u(0) = 0, u(1) = 1 etc."
]
},
{
"cell_type": "markdown",
"id": "16ccdde1",
"metadata": {},
"source": [
"Cette suite peut être définie par une **relation de récurrence** :\n",
"\n",
"$$\\left\\{\\begin{matrix}\n",
"u(0)=0 \\mbox{ et } u(1) = 1\\\\\n",
"u(n+1) = 3 \\times u(n-1) + u(n)\\\\\n",
"\\end{matrix}\\right.$$"
]
},
{
"cell_type": "markdown",
"id": "77483e7a",
"metadata": {},
"source": [
"Ce qui signifie que le nombre de paires d'adultes au mois `n+1` est **3 fois** le nombre de paires **d'adultes 2 mois avant** (reproduction) + les **immatures** du **mois précédent** qui deviennent adultes."
]
},
{
"cell_type": "markdown",
"id": "87db5892",
"metadata": {},
"source": [
"Essayez en effet de vous convaincre que 0 → 1 → 1 → 4 → 7 → 19 correspond à :\n",
"\n",
"u(2) = 1 = 3 * 0 + 1, u(3) = 4 = 3 * 1 + 1, u(4) = 7 = 3 * 1 + 4, u(5) = 19 = 3 * 4 + 7 🤔"
]
},
{
"cell_type": "markdown",
"id": "d1a878c7",
"metadata": {},
"source": [
"Traduction en Python :"
]
},
{
"cell_type": "code",
"execution_count": 7,
"id": "c69dfaaa",
"metadata": {},
"outputs": [],
"source": [
"var lapins = (n, b) => n <= 1 ? \n",
" n : \n",
" b * lapins(n - 2, b) + lapins(n - 1, b)"
]
},
{
"cell_type": "code",
"execution_count": 8,
"id": "0256da90",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"19"
]
},
"execution_count": 8,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"lapins(5,3)"
]
},
{
"cell_type": "code",
"execution_count": 9,
"id": "94e028d3",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"8425"
]
},
"execution_count": 9,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"lapins(8,12)"
]
},
{
"cell_type": "markdown",
"id": "545c307c",
"metadata": {},
"source": [
"## Version matricielle"
]
},
{
"cell_type": "markdown",
"id": "7e5ec90d",
"metadata": {},
"source": [
"Autre vision en utilisant cette fois-ci un **calcul matriciel**. En effet, observons que :\n",
"\n",
"$$\\begin{pmatrix}\n",
"u_{n+1} \\\\\n",
"u_n\n",
"\\end{pmatrix} = \\begin{pmatrix}\n",
"u_n + 3\\times u_{n-1} \\\\\n",
"u_n\n",
"\\end{pmatrix}=\n",
"\\begin{pmatrix}\n",
"1 & 3\\\\\n",
"1 & 0 \\\\\n",
"\\end{pmatrix} \\begin{pmatrix}\n",
"u_{n} \\\\\n",
"u_{n-1}\n",
"\\end{pmatrix}$$"
]
},
{
"cell_type": "markdown",
"id": "4d1d1adf",
"metadata": {},
"source": [
"On peut donc calculer **u(n+1)** et **u(n)** à l'aide des **puissances** d'une unique matrice 2 x 2 :\n",
"\n",
"$$\\begin{pmatrix}\n",
"u_{n+1} \\\\\n",
"u_n\n",
"\\end{pmatrix} =\n",
"\\begin{pmatrix}\n",
"1 & 3\\\\\n",
"1 & 0 \\\\\n",
"\\end{pmatrix}^n \\begin{pmatrix}\n",
"1 \\\\\n",
"0\n",
"\\end{pmatrix}$$"
]
},
{
"cell_type": "markdown",
"id": "ddd3110d",
"metadata": {},
"source": [
"De façon **plus générale**, le nombre de paires d'adultes pour un taux de reproduction `b` peut être calculé par :\n",
"\n",
"$$\\begin{pmatrix}\n",
"u_{n+1} \\\\\n",
"u_n\n",
"\\end{pmatrix} =\n",
"\\begin{pmatrix}\n",
"1 & b\\\\\n",
"1 & 0 \\\\\n",
"\\end{pmatrix}^n \\begin{pmatrix}\n",
"1 \\\\\n",
"0\n",
"\\end{pmatrix}$$"
]
},
{
"cell_type": "markdown",
"id": "9b46de78",
"metadata": {},
"source": [
"Il existe des bibliothèques JavaScript pour faire du calcul matriciel, par exemple math.js :\n",
"\n",
">> m = [[1, 3], [1, 0]]\n",
"\n",
">> math.pow(m,4)\n",
"0: [19, 21]\n",
"1: [7, 12]\n",
"\n",
">> math.pow(m,70)\n",
"0: [1.455103155612549e+25, 1.8956729415189765e+25]\n",
"1: [6.318909805063255e+24, 8.232121751062236e+24]"
]
},
{
"cell_type": "markdown",
"id": "77148790",
"metadata": {},
"source": [
"Sinon, vous pouvez vous créer une petite fonction permettant de mettre une matrice 2 x 2 à une puissance quelconque, par exemple :"
]
},
{
"cell_type": "code",
"execution_count": 10,
"id": "4662e4ca",
"metadata": {},
"outputs": [],
"source": [
"var power = (m, n) => // Matrice m à la puissance n\n",
"{\n",
" [[a, b], [c, d]] = m; // On récupère les coefficients\n",
" r = [[1, 0], [0, 1]] // Matrice unité\n",
" for (i = 0; i < n; i++) // n multiplications matricielles\n",
" {\n",
" [e, f] = [a * r[0][0] + c * r[0][1], b * r[0][0] + d * r[0][1]];\n",
" [g, h] = [a * r[1][0] + c * r[1][1], b * r[1][0] + d * r[1][1]];\n",
" r = [[e, f], [g, h]];\n",
" };\n",
" return r\n",
"}"
]
},
{
"cell_type": "code",
"execution_count": 11,
"id": "ee75f2d4",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"[ [ 19, 21 ], [ 7, 12 ] ]"
]
},
"execution_count": 11,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"power([[1, 3],[1, 0]], 4)"
]
},
{
"cell_type": "code",
"execution_count": 12,
"id": "e0055b83",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"[\n",
" [ 1.455103155612549e+25, 1.8956729415189765e+25 ],\n",
" [ 6.318909805063255e+24, 8.232121751062236e+24 ]\n",
"]"
]
},
"execution_count": 12,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"power([[1, 3],[1, 0]], 70)"
]
},
{
"cell_type": "markdown",
"id": "0fe3836c",
"metadata": {},
"source": [
"Programme final en JavaScript qui utilise la fonction `power` ci-dessus :"
]
},
{
"cell_type": "code",
"execution_count": 13,
"id": "d3422456",
"metadata": {},
"outputs": [],
"source": [
"var lapins = (n, b) => power([[1, b],[1, 0]], n)[1][0]"
]
},
{
"cell_type": "code",
"execution_count": 14,
"id": "08fb276e",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"8425"
]
},
"execution_count": 14,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"lapins(8, 12)"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "JavaScript (Node.js)",
"language": "javascript",
"name": "javascript"
},
"language_info": {
"file_extension": ".js",
"mimetype": "application/javascript",
"name": "javascript",
"version": "18.3.0"
}
},
"nbformat": 4,
"nbformat_minor": 5
}