Потренируемся в ОПН дальше. Операции, которые выполняются с одним значением, называются унарными, с двумя — бинарными, с тремя — тернарными. Давайте улучшим наш калькулятор, добавив поддержку следующих операций:
- бинарные:
+
(сложение),-
(вычитание),*
(умножение),/
(деление нацело; для отрицательных чисел работает по тем же правилам, что и в Python);
- унарные:
~
(унарный минус — меняет знак),!
(факториал),#
(клонирование — вернуть в стек значение дважды);
- тернарные:
@
(возвращает в стек те же три значения, но в ином порядке: второе, третье, первое).
Формат ввода
Вводится одна строка, содержащая разделённые пробелами целые числа и знаки операций. Вместе они составляют корректное выражение в обратной польской нотации, не содержащее деления на ноль и взятия факториала от отрицательного числа.
Формат вывода:
Выводится одно целое число — результат вычисления выражения.
Примечание
В первом примере стек по мере прочтения строки выглядит так:
- 7
- 7 1
- 7 1 10
- 7 1 10 100
- 7 1 10 100 100
- 7 1 10 10000
- 7 10 10000 1
- 7 10 9999
- 7 10009
- 10016
- -10016
Пример
Ввод
7 1 10 100 # * @ - + + ~
Вывод
-10016
Ввод
10 15 - 7 *
Вывод
-35
Решение
Задача усложнилась не слишком сильно. Надо разбить операции на группы, так же как они описаны выше и реализовать единый подход к чтению токенов на основе типа операции. В остальном алгоритм остался прежним.
Посмотреть код
Решение
expression = input()
tokens = expression.split()
uno = ['~', '#', '!']
duo = ['+', '-', '*', '/']
trio = ['@']
operators = uno + duo + trio
stack = []
while tokens != []:
token = tokens.pop(0)
if token in uno:
a = stack.pop()
match token:
case '~':
stack.append(-a)
case '!':
res = 1
for i in range(1, a + 1):
res *= i
stack.append(res)
case '#':
stack.append(a)
stack.append(a)
elif token in duo:
a = stack.pop()
b = stack.pop()
match token:
case '+':
stack.append(b + a)
case '-':
stack.append(b - a)
case '*':
stack.append(b * a)
case '/':
stack.append(b // a)
elif token in trio:
a = stack.pop()
b = stack.pop()
c = stack.pop()
match token:
case '@':
stack.append(b)
stack.append(a)
stack.append(c)
else:
stack.append(int(token))
print(int(stack[-1]))
while tokens != []: равно while tokens:
Спасибо за комментарий, об этом я рассказываю в этой статье.
А тут, я предполагаю, что еще не все освоились с такой особенностью языка и поэтому показываю неправильный с точки зрения PEP8, но более понятный для людей изучавших другой язык программирования, способ.