Exemple : calculatrice RPN
Principe
Calculatrice RPN
Principe : un calcul est effectué à l’aide d’une pile
Les nombres rentrés par l’utilisateur sont stockés dans une pile (empilés les uns sur les autres), et lorsqu’on fait une opération, on reprend de la pile les éléments nécessaires à l’opération, et on remet ensuite le résultat dans la pile.
Exemple : http://www.poleyland.com/hp48/
Opérations
Pour réaliser ce genre d’outil, on a besoin de pouvoir mettre des chiffres dans une pile : le dernier nombre rentré est le premier qu’on peut récupérer : LIFO : Last In First Out
On doit pouvoir réaliser les opérations suivante sur une pile (spécification) :
- créer une pile :
newpile()ouPile() -> pile - rajouter un élément dans la pile :
empile(pile, elt) -> Noneoupile.empile(elt) -> None - récupérer le dernier élément de la pile (et le supprimer de la pile
par la même occasion) :
depile(pile) -> nombre(erreur si la pile est vide), ou bienpile.depile() -> nombre(pour une pile objet) - renvoyer le nombre d’éléments dans la pile
nbelts(pile) -> nombre, oulen(pile) -> nombre(pour une pile objet)
La manière exacte de réaliser ces opérations est réalisée lors de l’implémentation.
Implémentation d’une pile
Implémentation avec une liste
Programme
def newpile():
return list()
def empile(pile, elt):
pile.append(elt)
def depile(pile):
assert len(pile) > 0, "Pile vide"
return pile.pop()
def nbelts(pile):
return len(pile)Tests
## Test de cette implémentation
pile = newpile()
empile(pile, 1)
empile(pile, 2)
assert nbelts(pile) == 2, pile
assert depile(pile) == 2, pile
assert nbelts(pile) == 1, pile
assert depile(pile) == 1, pile
assert nbelts(pile) == 0, pile
try:
depile(pile)
print("Une erreur aurait dû avoir lieu")
except AssertionError:
passImplémentation pile 2
Via un objet et une liste
class Pile():
def __init__(self):
self.__liste = []
def empile(self, elt):
self.__liste.append(elt)
def depile(self):
assert len(self.__liste) > 0, "Pile vide"
return self.__liste.pop()
def nbelts(self):
return len(self.__liste)
def __str__(self):
return str(self.__liste)
def __len__(self):
return len(self.__liste)Tests
## Test de cette implémentation
pile3 = Pile()
pile3.empile(1)
pile3.empile(2)
assert str(pile3) == "[1, 2]"
assert pile3.nbelts() == 2
assert len(pile3) == 2
assert pile3.depile() == 2
assert pile3.nbelts() == 1
assert pile3.depile() == 1
assert pile3.nbelts() == 0
try:
pile3.depile()
print("Une erreur aurait dû avoir lieu")
except AssertionError:
passSpécification d’une structure de données
A retenir
Spécification
Lorsqu’on veut développer un programme, il faut le plus vite possible identifier et spécifier les structures de données.
Une spécification est une définition formelle du comportement d’une certaine structure de données.
- c’est un contrat entre l’utilisateur et la personne qui va développer (implémenter) la structure de données
- elle dit ce que doit faire la structure de données
- elle ne dit pas comment le faire (implémentation)
- elle doit être précise et rigoureuse
- elle doit éviter de poser des contraintes d’implémentation
File
Principe
File
Une file est une structure de données qui permet de stocker des éléments dans un ordre précis : le premier élément entré est le premier élément sorti (FIFO : First In First Out).
Spécification et implémentation(s)
Spécification
En vous inspirant de la spécification de la pile, écrivez la spécification d’une file et écrivez les tests permettant de la vérifier, pour une pile implémentée sous forme de fonctions, puis sous forme d’objet.
Implémentation
- en vous inspirant de l’implémentation de la pile, écrivez une
implémentation d’une file de manière fonctionnelle (info utile :
pop()prend aussi un argumentindexpour sortir un élément à un index donné, en particulier 0 pour sortir le premier élément). - en vous inspirant de l’implémentation de la pile, écrivez une implémentation d’une file de manière objet.
Mini projet
Calculatrice RPN
A faire
Ecrire une fonction rpn(pile, actions) prenant comme
arguments une pile pile et une chaîne de caractères
actions, qui réalise les opérations contenues dans
action sur la pile pile.
Ecrire les assertions permettant de vérifier le bon fonctionnement de la calculatrice.
Exemples
- pile vide, actions = “2 2 + 3 *” : réalise les actions “empiler 2”, “empiler 2”, “depiler deux valeurs, les additionner et empiler le résultat”, “empiler 3”, “dépiler deux valeurs, les multiplier et empiler le résultat”. La pile contient donc à la fin un seul nombre : 12
- pile contenant 2 (bas) et 3 (haut), actions = “/ 1 +” : réalise les action “dépiler deux valeurs, les diviser (3/2) et remettre le résultat dans la pile”, “empiler 1”, “dépiler deux valeurs, les additionner et remettre le résultat dans la pile”. La pile contient donc à la fin un seul nombre : 2,5.
Actions possibles :
+,-,*,/,^
ou **, cos, sin,
tan, dup (dupliquer le dernier élément),
swap (échanger les deux derniers éléments de la pile) et
drop (supprimer le dernier élément de la pile)
Indications
actions.split(" ")permet de couper une chaîne de caractères à chaque espace pour la transformer en listefloat(str)permet de transformer une chaîne de caractères en nombre, en levant une exceptionValueErrorsi le nombre est invalide- depuis 2021, le python a une structure de contrôle match/case qui
peut remplacer des suites de
elif(ce qui ne veut pas dire que c’est à utiliser forcément ici) :
command = 'Hello, World!'
match command:
case 'Hello, World!':
print('Hello to you too!')
case 'Goodbye, World!':
print('See you later')
case other:
print('No match found')