{
"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
}