Le problème

Le problème consiste à créer une sorte de calculatrice qui permet de calculer les expressions écrites dans la notation polonaise inverse (NPI).
Cette notation transforme une expression écrite avec des paranthèses comme celle-ci « 3 × (4 + 7) » en une expression écrite différemment. Donc en notation polonaise inverse l'expression « 3 × (4 + 7) » s'écrit « 4 7 + 3 × ».

Comment faire un calcul en NPI ?

On doit stocker tous les nombres qu'on croise. Bien sûr on parcours l'expression depuis son début. Quand on passe par un opérateur, on doit sortir du stockage les 2 derniers nombres enregistrés, faire un calcul de ces 2 nombres et l'opérateur puis stocker le résultat du calcul. À la fin du code, il n'y aura qu'une valeur stockée.

Pour une facilité de compréhension, voici un exemple : « 4 7 5 - 3 * + » qui peut aussi être écrit comme ceci « (7 - 5) x 3 + 4 ».

Entrée Stockage des données
4 4
7 4 7
5 4 7 5
- 4 2
3 4 2 3
* 4 6
+ 10

Résolution de problème

Le type abstrait de donnée

Le type que j'ai utilisé pour résoudre ce problème est une pile car dans l'énoncé il est dit qu'il faut les 2 dernières valeurs enregistrées pour faire le calcul. Et que la pile est le type de donnée où ce sont les derniers éléments enregistrés qui sortent en premier.

La structure du code

Mon code est en 2 parties.

La première partie est un test pour vérifier que le code est bien écrit et qu'il n'y aura pas de problème si l'expression fournie par l'utilisateur contient une erreur. Pour cela j'ai vérifié qu'il y a un opérateur de moins que de nombre et qu'il y a au moins 2 nombres au début de la formule arithmétique, sinon le premier calcul ne pourra pas être calculé et cela causera une erreur.

La deuxième partie parcourt le code et fait les calculs quand c'est nécessaire. Dans cette partie quand on croise un opérateur, on dépile les 2 dernières valeurs stockées et normalement s'il n'y a pas de problème de test alors les valeurs stockées sont uniquement des nombres. Après chaque calcul, on doit transformer le int en str sinon la fonction eval utilisée dans cette fonction ne fonctionnera pas car elle ne marche qu'avec des str.

Le code


from pile import PileOptim

def NPI (chaine : str) -> int :
    """calcule les expression écrite en NPI (qui est une notation qui change la forme d'une expression écrite de ça « 3 × (4 + 7) » à ça « 4 7 + 3 × ») et vérifie que les expressions fournies sont correctes"""
    valeurS = chaine.split(' ')
    operateur = '+-/*'
    pile = PileOptim()
    nb_de_nombre = 0
    nb_d_operateur = 0
	nb_de_tour =0

    #vérifie que l'expression est bien écrite
    for caractere in valeurS :
        nb_de_tour += 1
        if caractere not in operateur and isinstance(int(caractere),(int)) : #vérifie que la caractère est un nombre
            nb_de_nombre +=1
            
        if nb_de_tour ==2 and nb_de_nombre != 2 : #vérifie qu'il y a au moins 2 nombres au début de l'expression
                return "L'expression fournie n'est pas écrite correctement. Nous ne pouvons pas faire le calcul."
            
        else :
            nb_d_operateur += 1


    if nb_d_operateur+1 != nb_de_nombre : #il y a toujours un operateur de moins que de nombre c'est de la que vient le test
        return "L'expression fournie n'est pas écrite correctement. Nous ne pouvons pas faire le calcul."


    #Parcours l'expression pour faire le calcul
    for caractere in valeurS :
        #vérifie si le caractere n'est pas un operateur et ajoute le caractere actuel dans la pile si c'est le cas
        if caractere not in operateur:
            pile.empiler(caractere)

        #dans le cas contraire on fait des calculs
        else :
            #sort les 2 derniers operandes de la pile
            operande2 = pile.depiler() #d'abord operande2 car la 2eme valeur est la premiere dépilée
            operande1 = pile.depiler()

            #fait le calcul des 2 operandes avec le bon operateur grâce à la fonction eval et empile dans la pile le résultat
            resultat = eval(operande1+caractere+operande2)
            pile.empiler(str(resultat)) #le résultat du calcul est un int mais la fonction eval ne fonctionne qu'avec des str

    resultat_calcul = pile.depiler()

    return resultat_calcul


			

Des tests

exp = "3 10 2 - *"
print(NPI(exp))
print()
			
exp1 = '6 8 - 9 + 8 7'
print(NPI(exp1))
print()
	
exp2 = '6 8 - 9 + / 7 - +'
print(NPI(exp2))
print()
	
exp3 = '4 8 + 3 *'
print(NPI(exp3))
print()
	
exp4 = '6 6 6 6 + + +'
print(NPI(exp4))
print()
	
exp5 = '4 7 5 - 3 * +'
print(NPI(exp5))
print()
	
exp6 = '6 + 6 6 7 + +'
print(NPI(exp6))