Quando vi o título dessa pergunta encerrada , pensei que parecia um desafio interessante para o código de golfe. Então deixe-me apresentá-lo como tal:
Desafio:
Escreva um programa, expressão ou sub-rotina que, dada uma expressão aritmética na notação infix , como 1 + 2
, emita a mesma expressão na notação postfix , ie 1 2 +
.
(Observação: um desafio semelhante foi postado no início de janeiro. No entanto, acho que as duas tarefas são suficientemente diferentes em detalhes para justificar esse desafio separado. Além disso, só notei o outro segmento depois de digitar tudo abaixo, e prefiro não apenas jogue tudo fora.)
Entrada:
A entrada é constituído por uma expressão aritmética infixa válido que consiste em números (números inteiros não negativos representada como sequências de um ou mais dígitos decimais), equilibrado parênteses para indicar uma subexpressão agrupados, e os quatro infixa binários operadores +
, -
, *
e /
. Qualquer um deles pode ser separado (e toda a expressão envolvida) por um número arbitrário de caracteres de espaço, que deve ser ignorado. 1 1
Para quem gosta de gramáticas formais, aqui está uma gramática simples, semelhante a BNF, que define entradas válidas. Por questões de clareza e clareza, a gramática não inclui os espaços opcionais, que podem ocorrer entre dois tokens (exceto dígitos dentro de um número):
expression := number | subexpression | expression operator expression
subexpression := "(" expression ")"
operator := "+" | "-" | "*" | "/"
number := digit | digit number
digit := "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9"
1 O único caso em que a presença de espaços pode afetar a análise é quando eles separam dois números consecutivos; no entanto, como dois números não separados por um operador não podem ocorrer em uma expressão de infixo válida, esse caso nunca pode ocorrer em entrada válida.
Saída:
A saída deve ser uma expressão postfix equivalente à entrada. A expressão de saída deve consistir apenas de números e operadores, com um único carácter de espaço entre cada par de símbolos adjacentes, como na seguinte gramática (que não incluem os espaços) 2 :
expression := number | expression sp expression sp operator
operator := "+" | "-" | "*" | "/"
number := digit | digit number
digit := "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9"
sp := " "
2 Novamente, por simplicidade, a number
produção nesta gramática admite números com zeros à esquerda, mesmo que sejam proibidos na saída pelas regras abaixo.
Operador precedente:
Na ausência de parênteses, as seguintes regras de precedência se aplicam:
- Os operadores
*
e/
têm maior precedência que+
e-
. - Os operadores
*
e/
têm precedência igual entre si. - Os operadores
+
e-
têm precedência igual entre si. - Todos os operadores são associativos à esquerda.
Por exemplo, as duas expressões a seguir são equivalentes:
1 + 2 / 3 * 4 - 5 + 6 * 7
((1 + ((2 / 3) * 4)) - 5) + (6 * 7)
e ambos devem produzir a seguinte saída:
1 2 3 / 4 * + 5 - 6 7 * +
(Essas são as mesmas regras de precedência que no idioma C e na maioria dos idiomas dele derivados. Provavelmente se assemelham às regras que você aprendeu no ensino fundamental, exceto, possivelmente, pela relativa precedência de *
e /
.)
Regras diversas:
Se a solução fornecida for uma expressão ou sub-rotina, a entrada deve ser fornecida e a saída retornada como uma única sequência. Se a solução for um programa completo, ele deve ler uma linha contendo a expressão infix da entrada padrão e imprimir uma linha contendo a versão do postfix na saída padrão.
Os números na entrada podem incluir zeros à esquerda. Os números na saída não devem ter zeros à esquerda (exceto o número 0, que deve ser exibido como
0
).Não é esperado que você avalie ou otimize a expressão de forma alguma. Em particular, você não deve assumir que os operadores necessariamente satisfazem qualquer identidade associativa, comutativa ou outras identidades algébricas. Ou seja, você não deve assumir que, por exemplo,
1 + 2
igual2 + 1
ou1 + (2 + 3)
igual a(1 + 2) + 3
.Você pode supor que os números na entrada não excedam 2 31 - 1 = 2147483647.
Essas regras visam garantir que a saída correta seja definida exclusivamente pela entrada.
Exemplos:
Aqui estão algumas expressões de entrada válidas e as saídas correspondentes, apresentadas no formulário "input" -> "output"
:
"1" -> "1"
"1 + 2" -> "1 2 +"
" 001 + 02 " -> "1 2 +"
"(((((1))) + (2)))" -> "1 2 +"
"1+2" -> "1 2 +"
"1 + 2 + 3" -> "1 2 + 3 +"
"1 + (2 + 3)" -> "1 2 3 + +"
"1 + 2 * 3" -> "1 2 3 * +"
"1 / 2 * 3" -> "1 2 / 3 *"
"0102 + 0000" -> "102 0 +"
"0-1+(2-3)*4-5*(6-(7+8)/9+10)" -> "0 1 - 2 3 - 4 * + 5 6 7 8 + 9 / - 10 + * -"
(Pelo menos, espero que tudo isso esteja correto; fiz a conversão manualmente, para que erros possam ter surgido.)
Só para esclarecer, as seguintes entradas são todas inválidas; ele não importa o que sua solução não se lhes deu (embora, é claro, por exemplo, retornando uma mensagem de erro é mais agradável do que, digamos, consumindo uma quantidade infinita de memória):
""
"x"
"1 2"
"1 + + 2"
"-1"
"3.141592653589793"
"10,000,000,001"
"(1 + 2"
"(1 + 2)) * (3 / (4)"
1 2 3 4 + *
?
1 2 3 4 +
significa `1 + 2 + 3 + 4`.