{ "cells": [ { "cell_type": "markdown", "id": "9d80ce9d", "metadata": {}, "source": [ "# Huitième exercice en JavaScript" ] }, { "cell_type": "markdown", "id": "a9f6c8c6", "metadata": {}, "source": [ "" ] }, { "cell_type": "markdown", "id": "ecbdb248", "metadata": {}, "source": [ "Quelques explications sur la **notation polonaise inverse** (**RPN**), utilisée par exemple sur les calculatrices de la marque HP (vidéo sur ma chaine Youtube pour en savoir plus) :" ] }, { "cell_type": "markdown", "id": "bb2c5af0", "metadata": {}, "source": [ "" ] }, { "cell_type": "markdown", "id": "75ae8941", "metadata": {}, "source": [ "Utilisez ce simulateur pour faire les calculs ci-dessous :\n", "\n", "
2 ENTER 3 +\n",
    "Affichage : 5\n",
    "\n",
    "3 ENTER 4 ENTER 5 * +\n",
    "Affichage : 23
" ] }, { "cell_type": "markdown", "id": "4dbba5ba", "metadata": {}, "source": [ "Ces calculatrices utilisent une **pile** (**stack**) pour placer (**empiler**) les valeurs (**opérandes**) et les calculs sont effectués dès que l'on appuie sur un **opérateur** (+, -, *, sin, etc.). Pour cela la machine dépile 1 ou plusieurs éléments sur le principe du \"dernier arrivé, premier sorti\" (LIFO = Last In First Out). Pour des opérateurs **dyadiques** comme l'**addition** ou la **multiplication**, il faut dépiler **2 éléments**. Pour un opérateur **monadique**, comme **sinus**, on ne dépile qu'**une seule valeur**." ] }, { "cell_type": "markdown", "id": "9e1c6706", "metadata": {}, "source": [ "Reprenons les étapes de l'exemple proposé dans l'énoncé : `5 1 2 + 4 * + 3 -`\n", "\n", "
5 ENTER 1 ENTER 2  // Pile = 5 | 1 | 2     (3 éléments empilés)\n",
    "+                  // Pile = 5 | 3         (calcul 1 + 2 = 3)\n",
    "4                  // Pile = 5 | 3 | 4     (4 empilé)\n",
    "*                  // Pile = 5 | 12        (calcul 3 * 4 = 12)\n",
    "+                  // Pile = 17            (calcul 5 + 12 = 17) \n",
    "3                  // Pile = 17 | 3        (3 empilé)\n",
    "-                  // Pile = 14            (calcul 17 - 3 = 14) 
\n", "\n", "Un des intérêts du RPN est qu'il n'y a pas **besoin de parenthèses**, d'ailleurs vous n'en trouverez pas sur les anciennes calculatrices HP." ] }, { "cell_type": "markdown", "id": "71e7e345", "metadata": {}, "source": [ "Les **piles** sont simplement des **listes** où l'on va pouvoir **empiler** et/ou **dépiler** des éléments :" ] }, { "cell_type": "code", "execution_count": 4, "id": "75f3e4e1", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[ 2, 9 ]" ] }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" } ], "source": [ "pile = [ ] // pile vide\n", "pile.push(2) // on empile 2\n", "pile.push(9) // et 9\n", "pile" ] }, { "cell_type": "code", "execution_count": 5, "id": "4a9d5794", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[ 2 ]" ] }, "execution_count": 5, "metadata": {}, "output_type": "execute_result" } ], "source": [ "pile.pop() // on dépile\n", "pile" ] }, { "cell_type": "markdown", "id": "86b4f9cf", "metadata": {}, "source": [ "## Evaluer une expression" ] }, { "cell_type": "markdown", "id": "b050d504", "metadata": {}, "source": [ "Une première solution est d'utiliser `eval` :" ] }, { "cell_type": "code", "execution_count": 6, "id": "e419a222", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "5" ] }, "execution_count": 6, "metadata": {}, "output_type": "execute_result" } ], "source": [ "eval('2 + 3')" ] }, { "cell_type": "markdown", "id": "36fabfbb", "metadata": {}, "source": [ "Une autre idée est de voir **2 + 3** comme **l'opérateur** `+` appliqué aux **opérandes** `2` et `3`, c'est-à-dire `+(2,3)`. C'est tout simplement la notation `f(x,y)` utilisée en mathématique." ] }, { "cell_type": "code", "execution_count": 7, "id": "d1c3cf40", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "{\n", " '+': [Function: +],\n", " '-': [Function: -],\n", " '*': [Function: *],\n", " '/': [Function: /]\n", "}" ] }, "execution_count": 7, "metadata": {}, "output_type": "execute_result" } ], "source": [ "OPS = {\n", " '+': (x, y) => x + y, '-': (x, y) => x - y, \n", " '*': (x, y) => x * y, '/': (x, y) => x / y\n", "}" ] }, { "cell_type": "code", "execution_count": 8, "id": "9e066011", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "5" ] }, "execution_count": 8, "metadata": {}, "output_type": "execute_result" } ], "source": [ "OPS['+'](2,3)" ] }, { "cell_type": "markdown", "id": "59916de4", "metadata": {}, "source": [ "## Idée du programme" ] }, { "cell_type": "markdown", "id": "4a541e34", "metadata": {}, "source": [ "Gardons l'exemple : `5 1 2 + 4 * + 3 -`" ] }, { "cell_type": "markdown", "id": "d411b272", "metadata": {}, "source": [ "On va **séparer** (`split`) les différents éléments de la chaine puis, en partant de la gauche, **empiler si** c'est un **nombre**, sinon **si** c'est un **opérateur**, **dépiler** les **2 derniers** éléments (les 4 opérateurs `+-/*` étant tous dyadiques), effectuer le **calcul** et **empiler** le résultat." ] }, { "cell_type": "markdown", "id": "882ef3cb", "metadata": {}, "source": [ "
On empile 5 puis 1 puis 2\n",
    "'+' étant un opérateur dyadique, on dépile 1 et 2\n",
    "On effectue le calcul +(1,2) qui donne 3\n",
    "On empile cette valeur, etc.
\n", "\n", "Pour récupèrer les clés d’un dictionnaire on peut utiliser la fonction `Object.keys`." ] }, { "cell_type": "code", "execution_count": 9, "id": "0af84e9e", "metadata": {}, "outputs": [], "source": [ "var calc = s => \n", "{\n", " OPS = \n", " {\n", " '+': (x, y) => x + y, '-': (x, y) => x - y, \n", " '*': (x, y) => x * y, '/': (x, y) => x / y\n", " };\n", " pile = [ ];\n", " for (v of s.split(' ')) \n", " {\n", " if (Object.keys(OPS).includes(v)) // includes = contient\n", " {\n", " [b, a] = [pile.pop(), pile.pop()];\n", " pile.push(OPS[v](a, b)) // Ajout du résultat\n", " }\n", " else \n", " {\n", " pile.push(+v) // '+' pour convertir en nombre\n", " }\n", " }\n", " return pile.pop()\n", "}" ] }, { "cell_type": "code", "execution_count": 10, "id": "acd9363c", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "14" ] }, "execution_count": 10, "metadata": {}, "output_type": "execute_result" } ], "source": [ "calc('5 1 2 + 4 * + 3 -')" ] }, { "cell_type": "code", "execution_count": 11, "id": "d7d8d068", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "6" ] }, "execution_count": 11, "metadata": {}, "output_type": "execute_result" } ], "source": [ "calc('3.5 2.5 +')" ] } ], "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 }