From 872ee50c45a65021a76ba0d779c82247a40af5f0 Mon Sep 17 00:00:00 2001 From: Elith Date: Tue, 3 Mar 2026 18:53:22 +0100 Subject: [PATCH] Calculatrice --- calculatrice.py | 74 +++++++++++++++++++++++++++++++++ expression.py | 90 +++++++++++++++++++++------------------- listeChaine.py | 106 ++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 229 insertions(+), 41 deletions(-) create mode 100644 calculatrice.py create mode 100644 listeChaine.py diff --git a/calculatrice.py b/calculatrice.py new file mode 100644 index 0000000..f53b948 --- /dev/null +++ b/calculatrice.py @@ -0,0 +1,74 @@ +import tkinter as tk +from tkinter import messagebox +from expression import npi2tree + + +def ajouter(val): + entree.insert(tk.END, val + " ") + + +def calculer(): + try: + texte = entree.get() + liste = texte.split() + arbre = npi2tree(liste) + resultat.config(text="Résultat : " + str(arbre.evalue())) + except: + messagebox.showerror("Erreur", "Expression invalide") + + +def effacer(): + entree.delete(0, tk.END) + resultat.config(text="") + + +fenetre = tk.Tk() +fenetre.title("Calculatrice NPI") +fenetre.geometry("500x600") + +entree = tk.Entry(fenetre, width=35, font=("Arial", 18)) +entree.pack(pady=20) + +frame = tk.Frame(fenetre) +frame.pack() + +chiffres = ["7", "8", "9", + "4", "5", "6", + "1", "2", "3", + "0"] + +i = 0 +for c in chiffres: + b = tk.Button(frame, + text=c, + width=6, + height=2, + font=("Arial", 16), + command=lambda x=c: ajouter(x)) + b.grid(row=i//3, column=i%3, padx=5, pady=5) + i += 1 + +plus = tk.Button(frame, text="+", width=6, height=2, + font=("Arial", 16), + command=lambda: ajouter("+")) +plus.grid(row=0, column=3, padx=5, pady=5) + +fois = tk.Button(frame, text="*", width=6, height=2, + font=("Arial", 16), + command=lambda: ajouter("*")) +fois.grid(row=1, column=3, padx=5, pady=5) + +btn_calc = tk.Button(fenetre, text="Calculer", + font=("Arial", 16), height=2, + command=calculer) +btn_calc.pack(pady=10) + +btn_clear = tk.Button(fenetre, text="Effacer", + font=("Arial", 16), height=2, + command=effacer) +btn_clear.pack(pady=5) + +resultat = tk.Label(fenetre, text="", font=("Arial", 16), fg="red") +resultat.pack(pady=20) + +fenetre.mainloop() \ No newline at end of file diff --git a/expression.py b/expression.py index 63412fc..d1ba520 100644 --- a/expression.py +++ b/expression.py @@ -1,60 +1,68 @@ -from Pile import Pile_lst as p -class Expression : - def __init__ (self, valeur, gauche, droit): - """Initialise la valeur de la racine (’+’, ’*’ ou un entier) et les fils gauche et - droit (qui seront soit None si la racine est un entier, soit des arbres) ;""" +from Pile import Pile_lst + + +class Expression: + """ + Représente une expression arithmétique sous forme d’arbre binaire. + """ + + def __init__(self, valeur, gauche=None, droit=None): + """ + Initialise un noeud avec une valeur ('+', '*' ou entier) + et éventuellement deux sous-arbres gauche et droit. + """ self.valeur = valeur self.gauche = gauche self.droit = droit - - - def evalue (self) : - """Renvoie la valeur de l’expression.""" - if self.gauche is None and self.droit is None : + + def evalue(self): + """ + Évalue récursivement l'expression et renvoie sa valeur entière. + """ + # Cas feuille (entier) + if self.gauche is None and self.droit is None: return self.valeur - - if self.valeur == "+" : + + # Cas opérateur + if self.valeur == "+": return self.gauche.evalue() + self.droit.evalue() elif self.valeur == "*": return self.gauche.evalue() * self.droit.evalue() + else: + raise ValueError("Opérateur inconnu") - - def __str__ (self) : - """Affiche l'expression""" - if self.gauche is None and self.droite is None : + def __str__(self): + """ + Renvoie une chaîne représentant l’expression avec parenthèses. + """ + # Cas feuille + if self.gauche is None and self.droit is None: return str(self.valeur) + # Cas opérateur + return "(" + str(self.gauche) + self.valeur + str(self.droit) + ")" -exp = Expression('*', - Expression(6, None, None), - Expression('+', - Expression(4, None, None), - Expression(3, None, None) - ) - ) -exp.evalue() +def npi2tree(liste_npi): + """ + Convertit une liste d’éléments en notation polonaise inversée (NPI) + en un arbre d’expression de type Expression. + """ + pile = Pile_lst() + for elem in liste_npi: - -def npi2tree (liste_npi) : - """Prends en paramètre une liste correspondant à l’expression en notation -polonaise inversée et renvoyant l’arbre (de type Expression) correspondant""" - pile = p() - for elem in liste_npi : - if elem == "+" : - droit = pile.depiler() - gauche = p.depiler() - exp = Expression(elem, gauche, droit) - p.empiler(exp) - elif elem == "*" : + # Si c'est un opérateur + if elem == "+" or elem == "*": droit = pile.depiler() gauche = pile.depiler() exp = Expression(elem, gauche, droit) pile.empiler(exp) - else : - exp = Expression(elem, None, None) + + # Sinon c'est un entier + else: + nombre = int(elem) + exp = Expression(nombre, None, None) pile.empiler(exp) - return p.sommet() - - \ No newline at end of file + + return pile.sommet() \ No newline at end of file diff --git a/listeChaine.py b/listeChaine.py new file mode 100644 index 0000000..0bee268 --- /dev/null +++ b/listeChaine.py @@ -0,0 +1,106 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + + +class Maillon: + """Un maillon d'une liste chaînée.""" + def __init__(self, valeur, suivant): + self.valeur = valeur + self.suivant = suivant + + def __str__(self): + """Renvoie une chane de caractères représentant le maillon.""" + return str(self.valeur) + + +class ListeChaine: + """Une liste chaînée.""" + def __init__(self, tete=None): + """Crée une liste vide, ou une liste dont la tete (un maillon) + est donnée.""" + self.__tete = tete + + def est_vide(self): + """Indique si la liste est vide.""" + return self.__tete is None + + def tete(self): + """Renvoie la valeur du premier élément de la liste.""" + if self.est_vide(): + raise IndexError("La liste vide n'a pas de tête") + return self.__tete.valeur + + def queue(self): + """Renvoie la queue de la liste.""" + if self.est_vide(): + raise IndexError("La liste vide n'a pas de queue") + return ListeChaine(self.__tete.suivant) + + def ajoute(self, valeur): + """ajoute `valeur` en tête de la liste.""" + self.__tete = Maillon(valeur, self.__tete) + + def __str__(self): + """Renvoie une chaîne de caractères représentant la liste.""" + maillon = self.__tete + s = '' + while maillon is not None: + s = s + str(maillon.valeur) + maillon = maillon.suivant + if maillon is not None: + s += '->' + return s + + def __len__(self): + """Renvoie la longueur de la liste.""" + maillon = self.__tete + long = 0 + while maillon is not None: + long = long + 1 + maillon = maillon.suivant + return long + + def __getitem__(self, n): + """Renvoie l'élément d'indice n de la liste.""" + maillon = self.__tete + i = 0 + while i < n and maillon is not None: + i = i + 1 + maillon = maillon.suivant + if maillon is None or n < 0: + raise IndexError("Indice non valide") + return maillon.valeur + + def __add__(self, other): + """Renvoie la liste correspondant à la concaténation des 2 listes.""" + if self.est_vide(): + return other + v = self.tete() + q = self.queue() + return ListeChaine(Maillon(v, (q + other).__tete)) + + def reverse(self): + """Renvoie une liste correspondant à la liste renversée.""" + res = ListeChaine() + maillon = self.__tete + while maillon is not None: + res.ajoute(maillon.valeur) + maillon = maillon.suivant + return res + + +if __name__ == "__main__": + lst = ListeChaine() + print(lst.est_vide()) + lst.ajoute(306) + lst.ajoute(42) + lst.ajoute(205) + print(lst) + print(lst.est_vide()) + print(lst[0]) + print(lst[1]) + print(len(lst)) + lst2 = ListeChaine() + lst2.ajoute(18) + lst2.ajoute(45) + print(lst + lst2)