Kiedy zobaczyłem tytuł tego zamkniętego pytania , pomyślałem, że to wygląda na ciekawe wyzwanie w golfa. Pozwólcie, że przedstawię to w ten sposób:
Wyzwanie:
Napisz program, wyrażenie lub podprogram, który, biorąc pod uwagę wyrażenie arytmetyczne w notacji infiksowej , podobnie 1 + 2
, wyprowadza to samo wyrażenie w notacji postfiksowej , tj 1 2 +
.
(Uwaga: podobne wyzwanie zostało opublikowane wcześniej w styczniu. Wydaje mi się jednak, że dwa zadania są wystarczająco różne w szczegółach, aby uzasadnić to oddzielne wyzwanie. Zwróciłem też uwagę na inny wątek po wpisaniu wszystkiego poniżej i wolałbym nie tylko wyrzucaj to wszystko).
Wkład:
Sygnał wejściowy składa się z ważnym Infix wyrażenia arytmetycznego obejmującej liczb (nieujemne liczby całkowite reprezentowane sekwencji jednego lub więcej cyfr dziesiętnych), zrównoważonego nawiasach wskazuje zgrupowanego podwyrażenie i cztery binarne wrostek operatorów +
, -
, *
i /
. Każde z nich może być oddzielone (a całe wyrażenie otoczone) dowolną liczbą spacji, które należy zignorować. 1
Dla tych, którzy lubią gramatyki formalne, oto prosta gramatyka podobna do BNF, która definiuje prawidłowe dane wejściowe. Dla zwięzłości i przejrzystości gramatyka nie obejmuje opcjonalnych spacji, które mogą wystąpić między dowolnymi dwoma znakami (innymi niż cyfry w obrębie liczby):
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 Jedynym przypadkiem, w którym obecność spacji może wpływać na parsowanie, jest rozdzielenie dwóch kolejnych liczb; jednak ponieważ dwie liczby nie oddzielone przez operatora nie mogą wystąpić w prawidłowym wyrażeniu infiksowym, taki przypadek nigdy nie może się zdarzyć przy prawidłowym wprowadzeniu.
Wydajność:
Wynik powinien być wyrażeniem postfiksowym równoważnym z danymi wejściowymi. Wyrażenie wyjściowy powinien się składać wyłącznie z numerami i operatorów, z jednym znaku spacji pomiędzy każdą parą sąsiadujących ze sobą elementów, z, jak w poniższej gramatyki (który nie obejmuje miejsca) 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 Ponownie dla uproszczenia, number
produkcja w tej gramatyce przyjmuje liczby z wiodącymi zerami, nawet jeśli są one zabronione w danych wyjściowych zgodnie z poniższymi regułami.
Pierwszeństwo operatora:
W przypadku braku nawiasów obowiązują następujące zasady pierwszeństwa:
- Operatorzy
*
i/
mają wyższy priorytet niż+
i-
. - Operatorzy
*
i/
mają takie same pierwszeństwo. - Operatorzy
+
i-
mają takie same pierwszeństwo. - Wszyscy operatorzy są lewostronni.
Na przykład następujące dwa wyrażenia są równoważne:
1 + 2 / 3 * 4 - 5 + 6 * 7
((1 + ((2 / 3) * 4)) - 5) + (6 * 7)
i oba powinny dać następujące wyniki:
1 2 3 / 4 * + 5 - 6 7 * +
(Są to te same zasady pierwszeństwa, co w języku C i w większości języków z niego wywodzących się. Prawdopodobnie przypominają one zasady, których uczyłeś w szkole podstawowej, z wyjątkiem ewentualnie względnego pierwszeństwa *
i /
.)
Różne zasady:
Jeśli podanym rozwiązaniem jest wyrażenie lub podprogram, dane wejściowe należy podać, a dane wyjściowe zwrócić jako pojedynczy ciąg. Jeśli rozwiązaniem jest kompletny program, powinien odczytać wiersz zawierający wyrażenie infix ze standardowego wejścia i wydrukować wiersz zawierający wersję Postfiksa na standardowe wyjście.
Liczby na wejściu mogą zawierać początkowe zera. Liczby na wyjściu nie mogą mieć wiodących zer (z wyjątkiem liczby 0, która powinna być wyprowadzona jako
0
).Nie należy oceniać ani optymalizować wyrażenia w żaden sposób. W szczególności nie należy zakładać, że operatory koniecznie spełniają wszelkie tożsamości asocjacyjne, przemienne lub inne algebraiczne. Oznacza to, że nie należy zakładać, że np. Jest
1 + 2
równy2 + 1
lub że1 + (2 + 3)
jest równy(1 + 2) + 3
.Można zakładać, że numery w wejściu nie przekracza 2 31 - 1 = 2147483647.
Reguły te mają na celu zapewnienie, że prawidłowe dane wyjściowe są jednoznacznie zdefiniowane przez dane wejściowe.
Przykłady:
Oto niektóre prawidłowe wyrażenia wejściowe i odpowiadające im dane wyjściowe, przedstawione w formie "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 + * -"
(Przynajmniej mam nadzieję , że wszystkie są poprawne; dokonałem konwersji ręcznie, aby błędy mogły się wkraść).
Dla jasności wszystkie poniższe dane wejściowe są nieprawidłowe; nie ma znaczenia, co zrobi twoje rozwiązanie, jeśli je otrzymasz (chociaż oczywiście np. zwrócenie komunikatu o błędzie jest ładniejsze niż, powiedzmy, zużycie nieskończonej ilości pamięci):
""
"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 +
oznacza „1 + 2 + 3 + 4”.