alexandre.aboulin
2 years ago
7 changed files with 454 additions and 42 deletions
@ -1 +1,51 @@ |
|||||
from lexer import Token |
import re |
||||
|
|
||||
|
class Token: |
||||
|
NUMBER = 0 |
||||
|
OPERATOR = 1 |
||||
|
PARENTHESE = 2 |
||||
|
FUNCTION = 3 |
||||
|
|
||||
|
@staticmethod |
||||
|
def isNumber(n): |
||||
|
return re.match(r'\d+', str(n)) is not None |
||||
|
|
||||
|
@staticmethod |
||||
|
def getPrecedence(tok): |
||||
|
if tok == "(" or tok == "": |
||||
|
return 4 |
||||
|
elif tok == "*" or tok == "/": |
||||
|
return 3 |
||||
|
elif tok == "+" or tok == "-": |
||||
|
return 2 |
||||
|
|
||||
|
|
||||
|
def __init__(self, type, val): |
||||
|
self.type = type |
||||
|
self.val = val |
||||
|
|
||||
|
class Expression: |
||||
|
|
||||
|
def __init__(self, val=None, gauche=None, droite=None): |
||||
|
if Token.isNumber(val) and (gauche != None or droite != None): |
||||
|
raise AttributeError("gauche et droite ne peuvent pas exister si val est un nombre") |
||||
|
self.val = val |
||||
|
self.gauche = gauche |
||||
|
self.droite = droite |
||||
|
|
||||
|
def evalue(self): |
||||
|
if self.val == "+": |
||||
|
return self.gauche.evalue() + self.droite.evalue() |
||||
|
elif self.val == "-": |
||||
|
return self.gauche.evalue() - self.droite.evalue() |
||||
|
elif self.val == "*": |
||||
|
return self.gauche.evalue() * self.droite.evalue() |
||||
|
elif self.val == "/": |
||||
|
return self.gauche.evalue() / self.droite.evalue() |
||||
|
else: |
||||
|
return float(self.val) |
||||
|
|
||||
|
def __str__(self): |
||||
|
if Token.isNumber(self.val): |
||||
|
return str(self.val) |
||||
|
return "(" + str(self.gauche.__str__()) + str(self.val) + str(self.droite.__str__()) + ")" |
@ -0,0 +1,114 @@ |
|||||
|
#!/usr/bin/env python3 |
||||
|
# -*- coding: utf-8 -*- |
||||
|
|
||||
|
class File_lst: |
||||
|
"""Implémentation d'une file par une liste.""" |
||||
|
def __init__(self): |
||||
|
"""Crée une file vide.""" |
||||
|
self.__file = [] |
||||
|
|
||||
|
def est_vide(self): |
||||
|
"""Indique si la file est vide.""" |
||||
|
return self.__file == [] |
||||
|
|
||||
|
def enfiler(self, valeur): |
||||
|
"""Enfile l'élément valeur.""" |
||||
|
self.__file.append(valeur) |
||||
|
|
||||
|
def defiler(self): |
||||
|
"""Défile la tête de la file et la renvoie.""" |
||||
|
return self.__file.pop(0) |
||||
|
|
||||
|
def taille(self): |
||||
|
"""Renvoie la taille de la file.""" |
||||
|
return len(self.__file) |
||||
|
|
||||
|
def tete(self): |
||||
|
"""Renvoie la tête de la file (sans la défiler).""" |
||||
|
return self.__file[0] |
||||
|
|
||||
|
def __str__(self): |
||||
|
s = "tete->" |
||||
|
for val in self.__file: |
||||
|
s += str(val) + "->" |
||||
|
return s + "queue" |
||||
|
|
||||
|
|
||||
|
class Maillon: |
||||
|
"""Un maillon d'une liste doublement chaînée.""" |
||||
|
def __init__(self, precedent, valeur, suivant): |
||||
|
self.valeur = valeur |
||||
|
self.precedent = precedent |
||||
|
self.suivant = suivant |
||||
|
|
||||
|
def __str__(self): |
||||
|
return str(self.valeur) |
||||
|
|
||||
|
|
||||
|
class File_chaine: |
||||
|
"""Implémentation d'une file par une liste doublement chaînée.""" |
||||
|
def __init__(self): |
||||
|
"""Crée une file vide.""" |
||||
|
self.__debut = self.__fin = None |
||||
|
self.__taille = 0 |
||||
|
|
||||
|
def est_vide(self): |
||||
|
"""Indique si la file est vide.""" |
||||
|
return self.__taille == 0 |
||||
|
|
||||
|
def enfiler(self, valeur): |
||||
|
"""Enfile l'élément valeur.""" |
||||
|
maillon = Maillon(self.__fin, valeur, None) |
||||
|
if self.est_vide(): |
||||
|
self.__debut = self.__fin = maillon |
||||
|
else: |
||||
|
self.__fin.suivant = maillon |
||||
|
self.__fin = maillon |
||||
|
self.__taille += 1 |
||||
|
|
||||
|
def defiler(self): |
||||
|
"""Défile la tête de la file et la renvoie.""" |
||||
|
if self.est_vide(): |
||||
|
raise IndexError("Impossible de défiler une file vide.") |
||||
|
valeur = self.__debut.valeur |
||||
|
self.__taille -= 1 |
||||
|
if self.est_vide(): |
||||
|
self.__debut = self.__fin = None |
||||
|
else: |
||||
|
self.__debut = self.__debut.suivant |
||||
|
self.__debut.precedent = None |
||||
|
return valeur |
||||
|
|
||||
|
def taille(self): |
||||
|
"""Renvoie la taille de la file.""" |
||||
|
return self.__taille |
||||
|
|
||||
|
def tete(self): |
||||
|
"""Renvoie la tête de la file (sans la défiler).""" |
||||
|
if self.est_vide(): |
||||
|
raise IndexError("Une file vide n'a pas de tête.") |
||||
|
return self.__debut.valeur |
||||
|
|
||||
|
def __str__(self): |
||||
|
s = "tete->" |
||||
|
maillon = self.__debut |
||||
|
while maillon is not None: |
||||
|
s += str(maillon) + "->" |
||||
|
maillon = maillon.suivant |
||||
|
return s + "queue" |
||||
|
|
||||
|
|
||||
|
if __name__ == "__main__": |
||||
|
f = File_lst() |
||||
|
print(f.est_vide()) |
||||
|
f.enfiler('A') |
||||
|
f.enfiler('B') |
||||
|
f.enfiler('C') |
||||
|
print(f.est_vide()) |
||||
|
print(f.tete()) |
||||
|
print(f) |
||||
|
print(f.taille()) |
||||
|
print(f.defiler()) |
||||
|
print(f.defiler()) |
||||
|
print(f.defiler()) |
||||
|
print(f.est_vide()) |
@ -0,0 +1,91 @@ |
|||||
|
#!/usr/bin/env python3 |
||||
|
# -*- coding: utf-8 -*- |
||||
|
|
||||
|
from lib.listeChaine import ListeChaine |
||||
|
|
||||
|
class Pile_lst: |
||||
|
"""Implémentation d'une pile par une liste.""" |
||||
|
def __init__(self): |
||||
|
"""Crée une pile vide.""" |
||||
|
self.__pile = [] |
||||
|
|
||||
|
def est_vide(self): |
||||
|
"""Indique si la pile est vide.""" |
||||
|
return self.__pile == [] |
||||
|
|
||||
|
def empiler(self, valeur): |
||||
|
"""Empile la valeur.""" |
||||
|
self.__pile.append(valeur) |
||||
|
|
||||
|
def depiler(self): |
||||
|
"""Dépile le sommet de la pile et le renvoie.""" |
||||
|
return self.__pile.pop() |
||||
|
|
||||
|
def taille(self): |
||||
|
"""Renvoie la taille de la pile.""" |
||||
|
return len(self.__pile) |
||||
|
|
||||
|
def sommet(self): |
||||
|
"""Renvoie le sommet de la pile (sans le dépiler).""" |
||||
|
return self.__pile[-1] |
||||
|
|
||||
|
def __str__(self): |
||||
|
s = "|" |
||||
|
for val in self.__pile: |
||||
|
s = str(val) + "->" + s |
||||
|
return s |
||||
|
|
||||
|
|
||||
|
class Pile_chaine: |
||||
|
"""Implémentation d'une pile par une liste chaînée.""" |
||||
|
def __init__(self): |
||||
|
"""Crée une pile vide.""" |
||||
|
self.__pile = ListeChaine() |
||||
|
self.__taille = 0 |
||||
|
|
||||
|
def est_vide(self): |
||||
|
"""Indique si la pile est vide.""" |
||||
|
return self.__taille == 0 |
||||
|
|
||||
|
def empiler(self, valeur): |
||||
|
"""Empile la valeur.""" |
||||
|
self.__pile.ajoute(valeur) |
||||
|
self.__taille += 1 |
||||
|
|
||||
|
def depiler(self): |
||||
|
"""Dépile le sommet de la pile et le renvoie.""" |
||||
|
if self.est_vide(): |
||||
|
raise IndexError("Impossible de dépiler une pile vide.") |
||||
|
valeur = self.__pile.tete() |
||||
|
self.__pile = self.__pile.queue() |
||||
|
self.__taille -= 1 |
||||
|
return valeur |
||||
|
|
||||
|
def taille(self): |
||||
|
"""Renvoie la taille de la pile.""" |
||||
|
return self.__taille |
||||
|
|
||||
|
def sommet(self): |
||||
|
"""Renvoie le sommet de la pile (sans le dépiler).""" |
||||
|
if self.est_vide(): |
||||
|
raise IndexError("Une pile vide n'a pas de sommet.") |
||||
|
return self.__pile.tete() |
||||
|
|
||||
|
def __str__(self): |
||||
|
return str(self.__pile) + "->|" |
||||
|
|
||||
|
|
||||
|
if __name__ == "__main__": |
||||
|
p = Pile_lst() |
||||
|
print(p.est_vide()) |
||||
|
p.empiler('A') |
||||
|
p.empiler('B') |
||||
|
p.empiler('C') |
||||
|
print(p.est_vide()) |
||||
|
print(p.sommet()) |
||||
|
print(p) |
||||
|
print(p.taille()) |
||||
|
print(p.depiler()) |
||||
|
print(p.depiler()) |
||||
|
print(p.depiler()) |
||||
|
print(p.est_vide()) |
@ -0,0 +1,111 @@ |
|||||
|
#!/usr/bin/env python3 |
||||
|
# -*- coding: utf-8 -*- |
||||
|
""" |
||||
|
Created on Tue Sep 22 20:44:35 2020 |
||||
|
|
||||
|
@author: manu |
||||
|
""" |
||||
|
|
||||
|
|
||||
|
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) |
@ -0,0 +1,4 @@ |
|||||
|
from reader import * |
||||
|
|
||||
|
cal = input("Entrez votre calcul en NPI : ") |
||||
|
print(npi2tree(tokenize(cal)).evalue()) |
@ -0,0 +1,79 @@ |
|||||
|
from expression import Token, Expression |
||||
|
from lib.Pile import Pile_chaine as Pile |
||||
|
from lib.File import File_chaine as File |
||||
|
|
||||
|
def tokenize(text): |
||||
|
buffer = "" |
||||
|
tokens = [] |
||||
|
for char in text: |
||||
|
#NUMBER |
||||
|
if Token.isNumber(char) or char == ".": |
||||
|
buffer += char |
||||
|
else: |
||||
|
#PUSH |
||||
|
if buffer != "": |
||||
|
print("a") |
||||
|
tokens.append(Token(Token.NUMBER, buffer)) |
||||
|
buffer = "" |
||||
|
#SINGLE CHAR |
||||
|
if char != " ": |
||||
|
if char == "(" or char == ")": |
||||
|
tokens.append(Token(Token.PARENTHESE, char)) |
||||
|
else: |
||||
|
tokens.append(Token(Token.OPERATOR, char)) |
||||
|
if buffer != "": |
||||
|
tokens.append(Token(Token.NUMBER, buffer)) |
||||
|
for token in tokens: |
||||
|
print(token.type, ":", token.val) |
||||
|
return tokens |
||||
|
|
||||
|
def shutting_yard(tokens): |
||||
|
output = File() |
||||
|
opertator = Pile() |
||||
|
for token in tokens: |
||||
|
if token.type == Token.NUMBER: |
||||
|
output.enfiler(token) |
||||
|
elif token.type == Token.FUNCTION: |
||||
|
opertator.empiler(token) |
||||
|
elif token.type == Token.OPERATOR: |
||||
|
if not opertator.est_vide(): |
||||
|
o2 = opertator.sommet() |
||||
|
a = o2 != "(" |
||||
|
print(o2.val) |
||||
|
b = Token.getPrecedence(o2.val) > Token.getPrecedence(token.val) |
||||
|
c = Token.getPrecedence(token.val) == Token.getPrecedence(o2.val) |
||||
|
|
||||
|
while a and (b or (c)): #and d)) |
||||
|
output.enfiler(opertator.depiler()) |
||||
|
opertator.empiler(token) |
||||
|
elif token.val == "(": |
||||
|
opertator.empiler(token) |
||||
|
elif token.val == ")": |
||||
|
while opertator.sommet() != "(": |
||||
|
assert not opertator.est_vide() |
||||
|
output.enfiler(opertator.depiler()) |
||||
|
assert opertator.sommet() == "(" |
||||
|
opertator.depiler() |
||||
|
if opertator.sommet().type == Token.FUNCTION: |
||||
|
output.enfiler(opertator.depiler()) |
||||
|
|
||||
|
while not opertator.est_vide(): |
||||
|
assert opertator.sommet != "(" |
||||
|
output.enfiler(opertator.depiler()) |
||||
|
|
||||
|
return output |
||||
|
|
||||
|
|
||||
|
def npi2tree(tokens): |
||||
|
pile = Pile() |
||||
|
for token in tokens: |
||||
|
if token in ["+", "-", "*", "/"]: |
||||
|
exp = Expression(token, pile.depiler(), pile.depiler()) |
||||
|
pile.empiler(exp) |
||||
|
else: |
||||
|
pile.empiler(Expression(token)) |
||||
|
return pile.depiler() |
||||
|
|
||||
|
if __name__ == "__main__": |
||||
|
print(shutting_yard(tokenize("2+44(4+21)"))) |
||||
|
#print(npi2tree(tokenize("6 4 3 + *"))) |
Loading…
Reference in new issue