Após estudar e entender o enunciado do EP, baixe os arquivos para este EP9.
Em seguida, depois de alterar o nome do módulo esqueleto_calculadora.py para calculadora.py copie a implementação que você fez da classe Calculadora para o EP8.
Se você não fez o EP8, ainda assim você poderá fazer quase a totalidade deste EP.
O EP9 consiste, essencialmente, na implementação da função infixa_para_posfixa() que está no módulo calculadora.py.
def infixa_para_posfixa(infixa):
'''(list de Tokens) -> list de Tokens
Recebe uma lista infixa de Tokens representando uma
expressão em notação infixa e retorna uma lista de
tokens representando uma expressão equivalente
na notação posfixa.
Essa função utiliza uma pilha que contém apenas
operadores e abre parênteses. Veja as notas de aula.
Pode ser útil utilizar nessa função o dicionário PREC do
modulo operadores.py. Nesse dicionário as chaves são os
operadores (str) e os valores (int) representam a
precedência dos operadores: quanto maior o valor, maior
a precedência.
Exemplos:
>>>
>>> tokens = tokeniza("a = 2 * 31.4")
>>> imprima_tokens(tokens)
[V('a'), O('='), N(2), O('*'), N(31.4)]
>>> posfixa = infixa_para_posfixa(tokens)
>>> imprima_tokens(posfixa)
[V('a'), N(2), N(31.4), O('*'), O('=')]
>>>
>>> tokens = tokeniza("2+3+4")
>>> imprima_tokens(tokens)
[N(2), O('+'), N(3), O('+'), N(4)]
>>> posfixa = infixa_para_posfixa(tokens)
>>> imprima_tokens(posfixa)
[N(2), N(3), O('+'), N(4), O('+')]
>>>
>>> tokens = tokeniza("2^3^4")
>>> imprima_tokens(tokens)
[N(2), O('^'), N(3), O('^'), N(4)]
>>> posfixa = infixa_para_posfixa(tokens)
>>> imprima_tokens(posfixa)
[N(2), N(3), N(4), O('^'), O('^')]
>>>
>>> tokens = tokeniza("(2+3)*4")
>>> imprima_tokens(tokens)
[P('('), N(2), O('+'), N(3), P(')'), O('*'), N(4)]
>>> posfixa = infixa_para_posfixa(tokens)
>>> imprima_tokens(posfixa)
[N(2), N(3), O('+'), N(4), O('*')]
>>>
>>> tokens = tokeniza("22+33*4.4")
>>> imprima_tokens(tokens)
[N(22), O('+'), N(33), O('*'), N(4.4)]
>>> posfixa = infixa_para_posfixa(tokens)
>>> imprima_tokens(posfixa)
[N(22), N(33), N(4.4), O('*'), O('+')]
>>>
'''
Para implementar a função infixa_para_posfixa() você deve consultar as notas de aula ou estudar uma das duas referências a seguir:
Conversion of Infix Expressions to Prefix and Postfix do capítulo Infix, Prefix and Postfix Expressions do livro Problem Solving with Algorithms and Data Structures.
Outra aplicação: notação polonesa do capítulo Pilhas do página de Projeto de Algoritmos em C do Prof. Paulo Feofiloff.
Depois de carregar o módulo calculadora.py execute o módulo (= Run -> Run Module) e teste a função infixa_para_posfixa() no Python Shell. Os exemplos a seguir mostram o comportamento da função.
Python 3.4.3 (default, Mar 26 2015, 22:03:40)
[GCC 4.9.2] on linux
Type "copyright", "credits" or "license()" for more information.
>>> ================================ RESTART ================================
>>>
>>> tokens = tokeniza("11")
>>> imprima_tokens(tokens)
[N(11)]
>>> posfixa = infixa_para_posfixa(tokens)
>>> imprima_tokens(posfixa)
[N(11)]
>>>
>>> tokens = tokeniza("11 2.34 aa bb cc")
>>> imprima_tokens(tokens)
[N(11), N(2.34), V('aa'), V('bb'), V('cc')]
>>> posfixa = infixa_para_posfixa(tokens)
>>> imprima_tokens(posfixa)
[N(11), N(2.34), V('aa'), V('bb'), V('cc')]
>>>
>>> tokens = tokeniza("11 + 22")
>>> imprima_tokens(tokens)
[N(11), O('+'), N(22)]
>>> posfixa = infixa_para_posfixa(tokens)
>>> imprima_tokens(posfixa)
[N(11), N(22), O('+')]
>>>
>>> tokens = tokeniza("1 + 2 - 3")
>>> imprima_tokens(tokens)
[N(1), O('+'), N(2), O('-'), N(3)]
>>> posfixa = infixa_para_posfixa(tokens)
>>> imprima_tokens(posfixa)
[N(1), N(2), O('+'), N(3), O('-')]
>>>
>>> tokens = tokeniza("1 - 2 + 3")
>>> imprima_tokens(tokens)
[N(1), O('-'), N(2), O('+'), N(3)]
>>> posfixa = infixa_para_posfixa(tokens)
>>> imprima_tokens(posfixa)
[N(1), N(2), O('-'), N(3), O('+')]
>>>
>>> tokens = tokeniza("1 + 2 * 3")
>>> imprima_tokens(tokens)
[N(1), O('+'), N(2), O('*'), N(3)]
>>> posfixa = infixa_para_posfixa(tokens)
>>> imprima_tokens(posfixa)
[N(1), N(2), N(3), O('*'), O('+')]
>>>
>>> tokens = tokeniza("1 / 2 * 3 % 4")
>>> imprima_tokens(tokens)
[N(1), O('/'), N(2), O('*'), N(3), O('%'), N(4)]
>>> posfixa = infixa_para_posfixa(tokens)
>>> imprima_tokens(posfixa)
[N(1), N(2), O('/'), N(3), O('*'), N(4), O('%')]
>>>
>>> tokens = tokeniza("!1")
>>> imprima_tokens(tokens)
[O('!'), N(1)]
>>> posfixa = infixa_para_posfixa(tokens)
>>> imprima_tokens(posfixa)
[N(1), O('!')]
>>>
>>> tokens = tokeniza("!1 + 2")
>>> imprima_tokens(tokens)
[O('!'), N(1), O('+'), N(2)]
>>> posfixa = infixa_para_posfixa(tokens)
>>> imprima_tokens(posfixa)
[N(1), O('!'), N(2), O('+')]
>>>
>>> tokens = tokeniza("1 + !2")
>>> imprima_tokens(tokens)
[N(1), O('+'), O('!'), N(2)]
>>> posfixa = infixa_para_posfixa(tokens)
>>> imprima_tokens(posfixa)
[N(1), N(2), O('!'), O('+')]
>>>
>>> tokens = tokeniza("1 + !2 * 3")
>>> imprima_tokens(tokens)
[N(1), O('+'), O('!'), N(2), O('*'), N(3)]
>>> posfixa = infixa_para_posfixa(tokens)
>>> imprima_tokens(posfixa)
[N(1), N(2), O('!'), N(3), O('*'), O('+')]
>>>
>>> tokens = tokeniza("(1 + 2) * 3")
>>> imprima_tokens(tokens)
[P('('), N(1), O('+'), N(2), P(')'), O('*'), N(3)]
>>> posfixa = infixa_para_posfixa(tokens)
>>> imprima_tokens(posfixa)
[N(1), N(2), O('+'), N(3), O('*')]
>>>
>>> tokens = tokeniza("4 / (1 + 2 * 3) * 3")
>>> imprima_tokens(tokens)
[N(4), O('/'), P('('), N(1), O('+'), N(2), O('*'), N(3), P(')'), O('*'), N(3)]
>>> posfixa = infixa_para_posfixa(tokens)
>>> imprima_tokens(posfixa)
[N(4), N(1), N(2), N(3), O('*'), O('+'), O('/'), N(3), O('*')]
>>>
>>> tokens = tokeniza("a + (b + (c + (d + (e + f))))")
>>> imprima_tokens(tokens)
[V('a'), O('+'), P('('), V('b'), O('+'), P('('), V('c'), O('+'), P('('), V('d'), O('+'), P('('), V('e'), O('+'), V('f'), P(')'), P(')'), P(')'), P(')')]
>>> posfixa = infixa_para_posfixa(tokens)
>>> imprima_tokens(posfixa)
[V('a'), V('b'), V('c'), V('d'), V('e'), V('f'), O('+'), O('+'), O('+'), O('+'), O('+')]
>>>
>>> tokens = tokeniza("a + (b * (c / (d % (e - f))))")
>>> imprima_tokens(tokens)
[V('a'), O('+'), P('('), V('b'), O('*'), P('('), V('c'), O('/'), P('('), V('d'), O('%'), P('('), V('e'), O('-'), V('f'), P(')'), P(')'), P(')'), P(')')]
>>> posfixa = infixa_para_posfixa(tokens)
>>> imprima_tokens(posfixa)
[V('a'), V('b'), V('c'), V('d'), V('e'), V('f'), O('-'), O('%'), O('/'), O('*'), O('+')]
>>>
>>> tokens = tokeniza("2 ^ 3 ^ 4 ^ 5")
>>> imprima_tokens(tokens)
[N(2), O('^'), N(3), O('^'), N(4), O('^'), N(5)]
>>> posfixa = infixa_para_posfixa(tokens)
>>> imprima_tokens(posfixa)
[N(2), N(3), N(4), N(5), O('^'), O('^'), O('^')]
>>>
>>> tokens = tokeniza("!!!!2")
>>> imprima_tokens(tokens)
[O('!'), O('!'), O('!'), O('!'), N(2)]
>>> posfixa = infixa_para_posfixa(tokens)
>>> imprima_tokens(posfixa)
[N(2), O('!'), O('!'), O('!'), O('!')]
>>>
>>> tokens = tokeniza("!2 ^ !3 ^ !4 ^ !5")
>>> imprima_tokens(tokens)
[O('!'), N(2), O('^'), O('!'), N(3), O('^'), O('!'), N(4), O('^'), O('!'), N(5)]
>>> posfixa = infixa_para_posfixa(tokens)
>>> imprima_tokens(posfixa)
[N(2), N(3), N(4), N(5), O('!'), O('^'), O('!'), O('^'), O('!'), O('^'), O('!')]
>>>
>>> tokens = tokeniza("a = 2 + 3 * 4")
>>> imprima_tokens(tokens)
[V('a'), O('='), N(2), O('+'), N(3), O('*'), N(4)]
>>> posfixa = infixa_para_posfixa(tokens)
>>> imprima_tokens(posfixa)
[V('a'), N(2), N(3), N(4), O('*'), O('+'), O('=')]
>>>
>>> tokens = tokeniza("a = b = c = 0")
>>> imprima_tokens(tokens)
[V('a'), O('='), V('b'), O('='), V('c'), O('='), N(0)]
>>> posfixa = infixa_para_posfixa(tokens)
>>> imprima_tokens(posfixa)
[V('a'), V('b'), V('c'), N(0), O('='), O('='), O('=')]
>>> tokens = tokeniza("a = b = c = a + b * c")
>>> imprima_tokens(tokens)
[V('a'), O('='), V('b'), O('='), V('c'), O('='), V('a'), O('+'), V('b'), O('*'), V('c')]
>>> posfixa = infixa_para_posfixa(tokens)
>>> imprima_tokens(posfixa)
[V('a'), V('b'), V('c'), V('a'), V('b'), V('c'), O('*'), O('+'), O('='), O('='), O('=')]
>>>
Se você não fez o EP8, então entregue o módulo calculadora.py apenas com a função infixa_para_posfixa() que você implementou, além do resto do esqueleto que está no módulo que você baixou.
Para terminar este EP só falta agora você fazer algumas pequenas alteração no método eval() da classe Calculadora que você fez para o EP8.
Abaixo está a especificação do método eval() que você implementou para o EP8.
def eval(self, exp = ''):
''' (str) -> float ou None
Recebe um string representando uma expressão em
notação posfixa e retorna o valor da expressão.
Se algum erro for detectado na expressão a função
retorna None.
'''
A seguir está a documentação do novo método eval() para o EP9. Verifique qual a difereça.
def eval(self, exp = ''):
''' (str) -> float ou None
Recebe um string representando uma expressão em
NOTAÇÃO INFIXA e retorna o valor da expressão.
Se algum erro for detectado na expressão a função
retorna None.
'''
Depois das alterações, carregue o módulo calculadora.py execute-o (= Run -> Run Module). Veja abaixo alguns testes do novo método eval()
Python 3.4.3 (default, Mar 26 2015, 22:03:40)
[GCC 4.9.2] on linux
Type "copyright", "credits" or "license()" for more information.
>>> ================================ RESTART ================================
>>>
>>> hp = Calculadora()
>>> hp.eval("1 + 2")
3.0
>>> hp.eval("1+2 *3")
7.0
>>> hp.eval("(1+2) *3")
9.0
>>> hp.eval("a = 1 + 2")
3.0
>>> hp.mostre_variaveis()
{'a': 3}
>>> hp.eval("a = a + 2")
5.0
>>> hp.mostre_variaveis()
{'a': 5}
>>> hp.eval("d = a")
5.0
>>> hp.mostre_variaveis()
{'d': 5, 'a': 5}
>>> hp.eval("c = e = f = d = a = 1")
1.0
>>> hp.mostre_variaveis()
{'c': 1, 'd': 1, 'e': 1, 'f': 1, 'a': 1}
>>> hp.troca_modo_verboso()
AVISO: modo verboso ativado.
>>> hp.eval("1 + 2 - 3")
eval(): string expr = '1 + 2 - 3'
eval(): lista tokens = [N(1), O('+'), N(2), O('-'), N(3)]
lista de tokens: [N(1), N(2), O('+'), N(3), O('-')]
pilha de execução: []
dicionário de variáveis: {'c': 1.0, 'd': 1.0, 'e': 1.0, 'f': 1.0, 'a': 1.0}
modo verboso: ativado
lista de tokens: [N(2), O('+'), N(3), O('-')]
pilha de execução: [N(1)]
dicionário de variáveis: {'c': 1.0, 'd': 1.0, 'e': 1.0, 'f': 1.0, 'a': 1.0}
modo verboso: ativado
lista de tokens: [O('+'), N(3), O('-')]
pilha de execução: [N(1), N(2)]
dicionário de variáveis: {'c': 1.0, 'd': 1.0, 'e': 1.0, 'f': 1.0, 'a': 1.0}
modo verboso: ativado
lista de tokens: [N(3), O('-')]
pilha de execução: [N(3)]
dicionário de variáveis: {'c': 1.0, 'd': 1.0, 'e': 1.0, 'f': 1.0, 'a': 1.0}
modo verboso: ativado
lista de tokens: [O('-')]
pilha de execução: [N(3), N(3)]
dicionário de variáveis: {'c': 1.0, 'd': 1.0, 'e': 1.0, 'f': 1.0, 'a': 1.0}
modo verboso: ativado
lista de tokens: []
pilha de execução: [N(0)]
dicionário de variáveis: {'c': 1.0, 'd': 1.0, 'e': 1.0, 'f': 1.0, 'a': 1.0}
modo verboso: ativado
0.0
>>> hp.eval("(1+2)*3/4")
eval(): string expr = '(1+2)*3/4'
eval(): lista tokens = [P('('), N(1), O('+'), N(2), P(')'), O('*'), N(3), O('/'), N(4)]
lista de tokens: [N(1), N(2), O('+'), N(3), O('*'), N(4), O('/')]
pilha de execução: []
dicionário de variáveis: {'c': 1.0, 'd': 1.0, 'e': 1.0, 'f': 1.0, 'a': 1.0}
modo verboso: ativado
lista de tokens: [N(2), O('+'), N(3), O('*'), N(4), O('/')]
pilha de execução: [N(1)]
dicionário de variáveis: {'c': 1.0, 'd': 1.0, 'e': 1.0, 'f': 1.0, 'a': 1.0}
modo verboso: ativado
lista de tokens: [O('+'), N(3), O('*'), N(4), O('/')]
pilha de execução: [N(1), N(2)]
dicionário de variáveis: {'c': 1.0, 'd': 1.0, 'e': 1.0, 'f': 1.0, 'a': 1.0}
modo verboso: ativado
lista de tokens: [N(3), O('*'), N(4), O('/')]
pilha de execução: [N(3)]
dicionário de variáveis: {'c': 1.0, 'd': 1.0, 'e': 1.0, 'f': 1.0, 'a': 1.0}
modo verboso: ativado
lista de tokens: [O('*'), N(4), O('/')]
pilha de execução: [N(3), N(3)]
dicionário de variáveis: {'c': 1.0, 'd': 1.0, 'e': 1.0, 'f': 1.0, 'a': 1.0}
modo verboso: ativado
lista de tokens: [N(4), O('/')]
pilha de execução: [N(9)]
dicionário de variáveis: {'c': 1.0, 'd': 1.0, 'e': 1.0, 'f': 1.0, 'a': 1.0}
modo verboso: ativado
lista de tokens: [O('/')]
pilha de execução: [N(9), N(4)]
dicionário de variáveis: {'c': 1.0, 'd': 1.0, 'e': 1.0, 'f': 1.0, 'a': 1.0}
modo verboso: ativado
lista de tokens: []
pilha de execução: [N(2.25)]
dicionário de variáveis: {'c': 1.0, 'd': 1.0, 'e': 1.0, 'f': 1.0, 'a': 1.0}
modo verboso: ativado
2.25
>>> hp.eval("2 ^ 2 ^ 3")
eval(): string expr = '2 ^ 2 ^ 3'
eval(): lista tokens = [N(2), O('^'), N(2), O('^'), N(3)]
lista de tokens: [N(2), N(2), N(3), O('^'), O('^')]
pilha de execução: []
dicionário de variáveis: {'c': 1.0, 'd': 1.0, 'e': 1.0, 'f': 1.0, 'a': 1.0}
modo verboso: ativado
lista de tokens: [N(2), N(3), O('^'), O('^')]
pilha de execução: [N(2)]
dicionário de variáveis: {'c': 1.0, 'd': 1.0, 'e': 1.0, 'f': 1.0, 'a': 1.0}
modo verboso: ativado
lista de tokens: [N(3), O('^'), O('^')]
pilha de execução: [N(2), N(2)]
dicionário de variáveis: {'c': 1.0, 'd': 1.0, 'e': 1.0, 'f': 1.0, 'a': 1.0}
modo verboso: ativado
lista de tokens: [O('^'), O('^')]
pilha de execução: [N(2), N(2), N(3)]
dicionário de variáveis: {'c': 1.0, 'd': 1.0, 'e': 1.0, 'f': 1.0, 'a': 1.0}
modo verboso: ativado
lista de tokens: [O('^')]
pilha de execução: [N(2), N(8)]
dicionário de variáveis: {'c': 1.0, 'd': 1.0, 'e': 1.0, 'f': 1.0, 'a': 1.0}
modo verboso: ativado
lista de tokens: []
pilha de execução: [N(256)]
dicionário de variáveis: {'c': 1.0, 'd': 1.0, 'e': 1.0, 'f': 1.0, 'a': 1.0}
modo verboso: ativado
256.0
>>> hp.eval("(2 ^ 2) ^ 3")
eval(): string expr = '(2 ^ 2) ^ 3'
eval(): lista tokens = [P('('), N(2), O('^'), N(2), P(')'), O('^'), N(3)]
lista de tokens: [N(2), N(2), O('^'), N(3), O('^')]
pilha de execução: []
dicionário de variáveis: {'c': 1.0, 'd': 1.0, 'e': 1.0, 'f': 1.0, 'a': 1.0}
modo verboso: ativado
lista de tokens: [N(2), O('^'), N(3), O('^')]
pilha de execução: [N(2)]
dicionário de variáveis: {'c': 1.0, 'd': 1.0, 'e': 1.0, 'f': 1.0, 'a': 1.0}
modo verboso: ativado
lista de tokens: [O('^'), N(3), O('^')]
pilha de execução: [N(2), N(2)]
dicionário de variáveis: {'c': 1.0, 'd': 1.0, 'e': 1.0, 'f': 1.0, 'a': 1.0}
modo verboso: ativado
lista de tokens: [N(3), O('^')]
pilha de execução: [N(4)]
dicionário de variáveis: {'c': 1.0, 'd': 1.0, 'e': 1.0, 'f': 1.0, 'a': 1.0}
modo verboso: ativado
lista de tokens: [O('^')]
pilha de execução: [N(4), N(3)]
dicionário de variáveis: {'c': 1.0, 'd': 1.0, 'e': 1.0, 'f': 1.0, 'a': 1.0}
modo verboso: ativado
lista de tokens: []
pilha de execução: [N(64)]
dicionário de variáveis: {'c': 1.0, 'd': 1.0, 'e': 1.0, 'f': 1.0, 'a': 1.0}
modo verboso: ativado
64.0
>>> hp.mostre_variaveis()
{'c': 1, 'd': 1, 'e': 1, 'f': 1, 'a': 1}
>>> hp.troca_modo_verboso()
AVISO: modo verboso desativado.
>>> hp.eval("2 ^ 2 ^ 3")
256.0
>>> hp.eval("(2 ^ 2) ^ 3")
64.0
>>> hp.eval("3 + !3")
0.0
>>> hp.eval("3 + !!3")
6.0
>>> hp.eval("3 + !!!3")
0.0
>>> hp.eval("3 + !!!!3") # :-)
6.0
>>> print(hp)
lista de tokens: []
pilha de execução: []
dicionário de variáveis: {'c': 1.0, 'd': 1.0, 'e': 1.0, 'f': 1.0, 'a': 1.0}
modo verboso: desativado
>>> hp = Calculadora()
>>> print(hp)
lista de tokens: []
pilha de execução: []
dicionário de variáveis: {}
modo verboso: desativado
>>> hp.eval("a = 1")
1.0
>>> hp.eval("b = 2")
2.0
>>> hp.eval("c = 3")
3.0
>>> hp.mostre_variaveis()
{'b': 2, 'c': 3, 'a': 1}
>>> hp.eval("c = a = b = a + b * c")
7.0
>>> hp.mostre_variaveis()
{'b': 7, 'c': 7, 'a': 7}
>>>
Finalmente, depois que as suas implementações acima estiverem funcionando, você pode testar a sua calculadora por completo. Para isso basta executar o módulo main.py.