Als ich den Titel dieser geschlossenen Frage sah , fand ich, dass es sich um eine interessante Code-Golf-Herausforderung handelte. Lassen Sie es mich als solches darstellen:
Herausforderung:
Ein Programm schreiben, Expression oder Unterprogramm , das, ein arithmetischer Ausdruck in gegebenem Infix - Schreibweise , wie 1 + 2
gibt den gleichen Ausdruck in Postfix - Schreibweise , dh 1 2 +
.
(Hinweis: Eine ähnliche Herausforderung wurde Anfang Januar veröffentlicht. Ich bin jedoch der Meinung, dass die beiden Aufgaben im Detail ausreichend unterschiedlich sind, um diese separate Herausforderung zu rechtfertigen. Außerdem habe ich den anderen Thread erst bemerkt, nachdem ich alles unten eingegeben habe, und ich würde es vorziehen nicht einfach alles wegwerfen.)
Eingang:
Die Eingabe besteht aus einem gültigen Infix arithmetischen Ausdruck , der aus Zahlen (nicht negative ganzen Zahlen als Sequenzen von einem oder mehreren Dezimalziffern dargestellt) ausgeglichen Klammern einen gruppierte Teilausdruck , um anzuzeigen, und die vier Infix binären Operatoren +
, -
, *
und /
. Jedes dieser Zeichen kann von einer beliebigen Anzahl von Leerzeichen getrennt (und der gesamte Ausdruck von einem Leerzeichen umgeben) werden, die ignoriert werden sollten. 1
Für diejenigen, die formale Grammatiken mögen, ist hier eine einfache BNF-ähnliche Grammatik, die gültige Eingaben definiert. Der Kürze und Klarheit halber enthält die Grammatik keine optionalen Leerzeichen, die zwischen zwei beliebigen Token (außer Ziffern innerhalb einer Zahl) auftreten können:
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 Der einzige Fall, in dem das Vorhandensein von Leerzeichen die Syntaxanalyse beeinflussen kann, besteht darin, dass zwei aufeinanderfolgende Zahlen voneinander getrennt werden. Da jedoch zwei nicht durch einen Operator getrennte Zahlen in einem gültigen Infix-Ausdruck nicht vorkommen können, kann dieser Fall bei einer gültigen Eingabe niemals auftreten.
Ausgabe:
Die Ausgabe sollte ein Postfix-Ausdruck sein, der der Eingabe entspricht. Der Ausgang Ausdruck sollte nur aus Zahlen und Operatoren besteht, mit einem einzigen Leerzeichen zwischen jedem Paar von benachbartem Tokens, wie in der folgenden Grammatik (die nicht die Räume umfasst) 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 Wiederum der Einfachheit halber lässt die number
Produktion in dieser Grammatik Zahlen mit führenden Nullen zu, obwohl sie in der Ausgabe nach den folgenden Regeln verboten sind.
Operator-Rangfolge:
In Abwesenheit von Klammern gelten die folgenden Vorrangregeln:
- Die Operatoren
*
und/
haben eine höhere Priorität als+
und-
. - Die Operatoren
*
und/
haben untereinander den gleichen Vorrang. - Die Operatoren
+
und-
haben untereinander den gleichen Vorrang. - Alle Operatoren sind linksassoziativ.
Die folgenden zwei Ausdrücke sind beispielsweise äquivalent:
1 + 2 / 3 * 4 - 5 + 6 * 7
((1 + ((2 / 3) * 4)) - 5) + (6 * 7)
und sie sollten beide die folgende Ausgabe ergeben:
1 2 3 / 4 * + 5 - 6 7 * +
(Dies sind die gleichen Prioritätsregeln wie in der C-Sprache und in den meisten davon abgeleiteten Sprachen. Sie ähneln wahrscheinlich den Regeln, die Sie in der Grundschule unterrichtet haben, außer möglicherweise der relativen Priorität von *
und /
.)
Verschiedene Regeln:
Wenn die angegebene Lösung ein Ausdruck oder eine Unterroutine ist, sollte die Eingabe geliefert und die Ausgabe als einzelne Zeichenfolge zurückgegeben werden. Wenn die Lösung ein vollständiges Programm ist, sollte sie eine Zeile mit dem Infix-Ausdruck von der Standardeingabe lesen und eine Zeile mit der Postfix-Version in der Standardausgabe ausgeben.
Zahlen in der Eingabe können führende Nullen enthalten. Zahlen in der Ausgabe dürfen keine führenden Nullen haben (mit Ausnahme der Zahl 0, die als ausgegeben werden soll
0
).Es wird nicht erwartet, dass Sie den Ausdruck in irgendeiner Weise bewerten oder optimieren. Insbesondere sollten Sie nicht davon ausgehen, dass die Operatoren notwendigerweise assoziative, kommutative oder andere algebraische Identitäten erfüllen. Das heißt, Sie sollten nicht davon ausgehen, dass zB
1 + 2
gleich2 + 1
oder1 + (2 + 3)
gleich ist(1 + 2) + 3
.Sie können davon ausgehen, dass die Zahlen in der Eingabe 2 31 - 1 = 2147483647 nicht überschreiten .
Diese Regeln sollen sicherstellen, dass die korrekte Ausgabe durch die Eingabe eindeutig definiert wird.
Beispiele:
Hier sind einige gültige Eingabeausdrücke und die entsprechenden Ausgaben, dargestellt in der Form "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 + * -"
(Zumindest hoffe ich, dass all dies richtig ist. Ich habe die Konvertierung von Hand durchgeführt, sodass sich Fehler eingeschlichen haben könnten.)
Die folgenden Eingaben sind alle ungültig. Es spielt keine Rolle, was Ihre Lösung tut, wenn sie angegeben wird (obwohl es natürlich sinnvoller ist, z. B. eine Fehlermeldung zurückzugeben, als beispielsweise unendlich viel Speicherplatz zu verbrauchen):
""
"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 +
"1 + 2 + 3 + 4".