{
"cells": [
{
"cell_type": "markdown",
"id": "9d80ce9d",
"metadata": {},
"source": [
"# Huitième exercice en Python (Niveau Lycée)"
]
},
{
"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) :"
]
},
{
"attachments": {},
"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": 1,
"id": "75f3e4e1",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"[2, 9]"
]
},
"execution_count": 1,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"pile = [ ] # pile vide\n",
"pile.append(2) # on empile la valeur 2\n",
"pile.append(9) # et la valeur 9\n",
"pile"
]
},
{
"cell_type": "code",
"execution_count": 2,
"id": "4a9d5794",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"[2]"
]
},
"execution_count": 2,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"pile.pop() # On dépile suivant \"Last In First Out\"\n",
"pile"
]
},
{
"cell_type": "markdown",
"id": "86b4f9cf",
"metadata": {},
"source": [
"## Evaluer une expression en python et javascript"
]
},
{
"cell_type": "markdown",
"id": "b050d504",
"metadata": {},
"source": [
"Une première solution est d'utiliser `eval` :"
]
},
{
"cell_type": "code",
"execution_count": 3,
"id": "e419a222",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"5"
]
},
"execution_count": 3,
"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": 4,
"id": "d1c3cf40",
"metadata": {},
"outputs": [],
"source": [
"OPS = { \\\n",
" '+': lambda x, y: x + y, '-': lambda x, y: x - y, \\\n",
" '*': lambda x, y: x * y, '/': lambda x, y: x / y \\\n",
" }"
]
},
{
"cell_type": "code",
"execution_count": 5,
"id": "9e066011",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"5"
]
},
"execution_count": 5,
"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."
]
},
{
"cell_type": "code",
"execution_count": 6,
"id": "0af84e9e",
"metadata": {},
"outputs": [],
"source": [
"def calc(s):\n",
" OPS = { \\\n",
" '+': lambda x, y: x + y, '-': lambda x, y: x - y, \\\n",
" '*': lambda x, y: x * y, '/': lambda x, y: x / y \\\n",
" }\n",
" pile = [ ] # Pile vide\n",
" for v in s.split(): # On parcourt les éléments\n",
" if v in OPS: # Est-ce un opérateur ?\n",
" b, a = pile.pop(), pile.pop() # on dépile 2 éléments\n",
" pile.append(OPS[v](a, b)) # calcul + empiler le résultat\n",
" else: # sinon\n",
" pile.append(float(v)) # on empile la valeur\n",
" return pile.pop() # Contenu de la pile"
]
},
{
"cell_type": "code",
"execution_count": 7,
"id": "acd9363c",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"14.0"
]
},
"execution_count": 7,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"calc('5 1 2 + 4 * + 3 -')"
]
},
{
"cell_type": "code",
"execution_count": 8,
"id": "d7d8d068",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"6.0"
]
},
"execution_count": 8,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"calc('3.5 2.5 +')"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"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.9.6"
}
},
"nbformat": 4,
"nbformat_minor": 5
}