Cuando vi el título de esta pregunta cerrada , pensé que parecía un interesante desafío de código de golf. Así que permítanme presentarlo como tal:
Reto:
Escriba un programa, expresión o subrutina que, dada una expresión aritmética en notación infija , como 1 + 2
, genera la misma expresión en notación postfix , es decir 1 2 +
.
(Nota: se publicó un desafío similar a principios de enero. Sin embargo, creo que las dos tareas son lo suficientemente diferentes en detalle para justificar este desafío por separado. Además, solo noté el otro hilo después de escribir todo lo siguiente, y prefiero no solo tirarlo todo)
Entrada:
La entrada consiste en una expresión aritmética infija válido que consta de números (números enteros no negativos representan como secuencias de uno o más dígitos decimales), equilibrado de paréntesis para indicar una subexpresión agrupados, y los cuatro infija binarios operadores +
, -
, *
y /
. Cualquiera de estos puede estar separado (y toda la expresión rodeada) por un número arbitrario de caracteres de espacio, que deben ignorarse. 1
Para aquellos a quienes les gustan las gramáticas formales, aquí hay una gramática simple similar a BNF que define entradas válidas. Por brevedad y claridad, la gramática no incluye los espacios opcionales, que pueden ocurrir entre dos tokens (que no sean dígitos dentro de un 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 El único caso donde la presencia de espacios puede afectar el análisis es cuando separan dos números consecutivos; sin embargo, dado que dos números no separados por un operador no pueden aparecer en una expresión infija válida, este caso nunca puede ocurrir en una entrada válida.
Salida:
La salida debe ser una expresión postfix equivalente a la entrada. La expresión de salida debe consistir solamente de números y los operadores, con un solo carácter de espacio entre cada par de fichas adyacentes, como en el siguiente gramática (que no incluye los espacios) 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 Nuevamente, por simplicidad, la number
producción en esta gramática admite números con ceros a la izquierda, a pesar de que están prohibidos en la salida por las siguientes reglas.
Precedencia del operador:
En ausencia de paréntesis, se aplican las siguientes reglas de precedencia:
- Los operadores
*
y/
tienen mayor prioridad que+
y-
. - Los operadores
*
y/
tienen la misma precedencia entre sí. - Los operadores
+
y-
tienen la misma precedencia entre sí. - Todos los operadores son asociativos a la izquierda.
Por ejemplo, las siguientes dos expresiones son equivalentes:
1 + 2 / 3 * 4 - 5 + 6 * 7
((1 + ((2 / 3) * 4)) - 5) + (6 * 7)
y ambos deberían producir el siguiente resultado:
1 2 3 / 4 * + 5 - 6 7 * +
(Estas son las mismas reglas de precedencia que en el lenguaje C y en la mayoría de los lenguajes derivados de él. Probablemente se parecen a las reglas que le enseñaron en la escuela primaria, excepto posiblemente por la precedencia relativa de *
y /
.)
Reglas misceláneas:
Si la solución dada es una expresión o una subrutina, la entrada debe proporcionarse y la salida debe devolverse como una sola cadena. Si la solución es un programa completo, debería leer una línea que contenga la expresión infija de la entrada estándar e imprimir una línea que contenga la versión postfix en la salida estándar.
Los números en la entrada pueden incluir ceros a la izquierda. Los números en la salida no deben tener ceros a la izquierda (excepto el número 0, que se emitirá como
0
).No se espera que evalúe u optimice la expresión de ninguna manera. En particular, no debe suponer que los operadores necesariamente satisfacen cualquier identidad asociativa, conmutativa u otra identidad algebraica. Es decir, no debe suponer que, por ejemplo,
1 + 2
es igual2 + 1
o que1 + (2 + 3)
es igual(1 + 2) + 3
.Puede suponer que los números en la entrada no exceden 2 31 - 1 = 2147483647.
El objetivo de estas reglas es garantizar que la entrada defina de forma exclusiva la salida correcta.
Ejemplos:
Aquí hay algunas expresiones de entrada válidas y las salidas correspondientes, presentadas en la forma "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 + * -"
(Al menos, espero que todo esto sea correcto; hice la conversión a mano, por lo que los errores podrían haber aparecido).
Para ser claros, las siguientes entradas no son válidas; sí no importa lo que su solución no si les da (aunque, por supuesto, por ejemplo, devuelve un mensaje de error es más agradable que, por ejemplo, el consumo de una cantidad infinita de memoria):
""
"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`.