Коли я побачив назву цього закритого питання , я подумав, що це виглядає як цікавий виклик коду для гольфу. Тож дозвольте представити його як таке:
Виклик:
Напишіть програму, вираз чи підпрограму, яка, даючи арифметичний вираз у позначенні інфіксу , як 1 + 2
, видає той самий вираз у позначенні постфіксу , тобто 1 2 +
.
(Примітка . Аналогічний виклик був опублікований раніше в січні. Однак я вважаю, що ці два завдання досить детально відрізняються детально, щоб виправдати це окреме завдання. Крім того, я помітив лише інший потік після введення всього нижче, і я вважаю за краще а не просто викинути все це.)
Вхід:
Введення складається з дійсного інфіксне арифметичного виразу , що складається з чисел (невід'ємні цілі числа представлені в вигляді послідовностей одного або більше десяткових цифр), збалансовані дужки , щоб вказати , згрупований подвираженія, і чотири інфіксне бінарних операторів +
, -
, *
і /
. Будь-який з них може бути відокремлений (і весь вираз оточений) довільною кількістю пробілів, які слід ігнорувати. 1
Для тих, хто любить формальні граматики, ось проста граматика, схожа на BNF, яка визначає дійсні введення. Для стислості та ясності граматика не включає необов'язкові пробіли, які можуть виникати між будь-якими двома лексемами (крім цифр у межах числа):
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 Єдиний випадок, коли наявність пробілів може вплинути на розбір, це коли вони розділяють два послідовних числа; однак, оскільки два числа, не розділені оператором, не можуть зустрічатися у дійсному виразі інфіксації, цей випадок ніколи не може відбутися при дійсному введенні.
Вихід:
Вихід повинен бути постфіксним виразом, еквівалентним вхідному. Вираз вихід повинен складатися тільки з цифр і операторів, з одним пропуском між кожною парою суміжних маркерів, як показано в наступній граматиці (який робить включати пробіли) 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 Знову для простоти, number
виробництво в цій граматиці допускає числа з провідними нулями, навіть якщо вони заборонені у виведенні правилами нижче.
Пріоритет оператора:
За відсутності дужок застосовуються такі правила пріоритету:
- Оператори
*
і/
мають вищий пріоритет перед+
та-
. - Оператори
*
і/
мають однаковий пріоритет один перед одним. - Оператори
+
і-
мають однаковий пріоритет один перед одним. - Усі оператори ліво-асоціативні.
Наприклад, наступні два вирази еквівалентні:
1 + 2 / 3 * 4 - 5 + 6 * 7
((1 + ((2 / 3) * 4)) - 5) + (6 * 7)
і вони повинні отримати наступний результат:
1 2 3 / 4 * + 5 - 6 7 * +
(Це ті самі правила пріоритету, що і в мові С та в більшості похідних з неї мов. Вони, ймовірно, нагадують правила, яких ви навчали в початковій школі, за винятком, можливо, відносного переваги *
та /
.)
Різні правила:
Якщо задане рішення є виразом або підпрограмою, вхід повинен бути наданий, а вихід повернутись як один рядок. Якщо рішення є повною програмою, він повинен прочитати рядок, що містить вираз інфіксації зі стандартного введення, та надрукувати рядок, що містить версію постфіксу, до стандартного виводу.
Числа у введенні можуть включати провідні нулі. Числа у висновку не повинні мати провідних нулів (за винятком числа 0, яке виводиться як
0
).Від вас не очікується будь-яким чином оцінювати або оптимізувати вираз. Зокрема, не слід вважати, що оператори обов'язково задовольняють будь-які асоціативні, комутативні чи інші алгебраїчні тотожності. Тобто, ви не повинні вважати, що, наприклад,
1 + 2
дорівнює2 + 1
або що1 + (2 + 3)
дорівнює(1 + 2) + 3
.Ви можете припустити, що числа на вході не перевищують 2 31 - 1 = 2147483647.
Ці правила покликані гарантувати, що правильний вихід однозначно визначається вводом.
Приклади:
Ось деякі дійсні вхідні вирази та відповідні виходи, представлені у формі "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 + * -"
(Принаймні, я сподіваюся, що все це правильно; перетворення я зробив вручну, тому помилки могли виникнути.)
Щоб було зрозуміло, наведені нижче дані є недійсними; не має значення, що робить ваше рішення, якщо їм надано (хоча, звичайно, наприклад, повернення повідомлення про помилку приємніше, ніж, скажімо, споживання нескінченної кількості пам'яті):
""
"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".