Quando ho visto il titolo di questa domanda chiusa , ho pensato che sembrava un'interessante sfida per il golf del codice. Vorrei quindi presentarlo come tale:
Sfida:
Scrivi un programma, un'espressione o una subroutine che, data un'espressione aritmetica nella notazione infix , come 1 + 2, genera la stessa espressione nella notazione postfix , cioè 1 2 +.
(Nota: una sfida simile è stata pubblicata all'inizio di gennaio. Tuttavia, ritengo che i due compiti siano sufficientemente diversi nei dettagli per giustificare questa sfida separata. Inoltre, ho notato l'altro thread solo dopo aver digitato tutto di seguito, e preferirei non buttare via tutto.)
Ingresso:
L'ingresso è costituito da un infisso espressione aritmetica valida rappresentati da numeri (numeri interi non negativi rappresentati come sequenze di una o più cifre decimali), bilanciati parentesi per indicare una sottoespressione raggruppato, e le quattro infisso binari operatori + , -, *e /. Ognuno di questi può essere separato (e l'intera espressione circondata) da un numero arbitrario di caratteri spaziali, che dovrebbe essere ignorato. 1
Per coloro a cui piacciono le grammatiche formali, ecco una semplice grammatica simile a BNF che definisce input validi. Per brevità e chiarezza, la grammatica non include gli spazi opzionali, che possono verificarsi tra due token (diversi dalle cifre all'interno di un numero):
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 L'unico caso in cui la presenza di spazi può influenzare l'analisi è quando separano due numeri consecutivi; tuttavia, poiché due numeri non separati da un operatore non possono verificarsi in un'espressione infix valida, questo caso non può mai verificarsi in un input valido.
Produzione:
L'output dovrebbe essere un'espressione postfix equivalente all'input. L'espressione output dovrebbe consistere solo di numeri e operatori, con un singolo carattere spazio tra ogni coppia di token adiacenti, come nel seguente grammatica (che non includono gli spazi) 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 Ancora per semplicità, la numberproduzione in questa grammatica ammette numeri con zeri iniziali, anche se sono vietati nell'output dalle regole seguenti.
Precedenza dell'operatore:
In assenza di parentesi, si applicano le seguenti regole di precedenza:
- Gli operatori
*e/hanno una precedenza maggiore rispetto a+e-. - Gli operatori
*e/hanno uguale precedenza l'uno con l'altro. - Gli operatori
+e-hanno uguale precedenza l'uno con l'altro. - Tutti gli operatori sono associativi di sinistra.
Ad esempio, le seguenti due espressioni sono equivalenti:
1 + 2 / 3 * 4 - 5 + 6 * 7
((1 + ((2 / 3) * 4)) - 5) + (6 * 7)
e dovrebbero entrambi produrre il seguente output:
1 2 3 / 4 * + 5 - 6 7 * +
(Queste sono le stesse regole di precedenza come nel linguaggio C e nella maggior parte delle lingue che ne derivano. Probabilmente assomigliano alle regole che ti sono state insegnate nella scuola elementare, tranne forse per la relativa precedenza di *e /.)
Regole varie:
Se la soluzione fornita è un'espressione o una subroutine, è necessario fornire l'input e restituire l'output come singola stringa. Se la soluzione è un programma completo, dovrebbe leggere una riga contenente l'espressione infix dall'input standard e stampare una riga contenente la versione postfix sull'output standard.
I numeri nell'input possono includere zeri iniziali. I numeri nell'output non devono avere zeri iniziali (ad eccezione del numero 0, che deve essere emesso come
0).Non devi valutare o ottimizzare l'espressione in alcun modo. In particolare, non si deve presumere che gli operatori soddisfino necessariamente qualsiasi identità associativa, commutativa o algebrica. Cioè, non dovresti assumere che eg
1 + 2eguaglia2 + 1o che sia1 + (2 + 3)uguale(1 + 2) + 3.Si può presumere che i numeri nell'input non superino 2 31 - 1 = 2147483647.
Queste regole hanno lo scopo di garantire che l'output corretto sia definito in modo univoco dall'input.
Esempi:
Ecco alcune espressioni di input valide e gli output corrispondenti, presentati nel modulo "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 + * -"
(Almeno, spero che tutti questi siano corretti; ho fatto la conversione a mano, quindi gli errori potrebbero essere insorti.)
Per essere chiari, i seguenti input sono tutti non validi; esso non importa che cosa il vostro soluzione non se li dato (anche se, naturalmente, ad esempio, restituisce un messaggio di errore è più bello rispetto, ad esempio, consumando una quantità infinita di 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".