T. Польский калькулятор — 2

Потренируемся в ОПН дальше. Операции, которые выполняются с одним значением, называются унарными, с двумя — бинарными, с тремя — тернарными. Давайте улучшим наш калькулятор, добавив поддержку следующих операций:

  • бинарные:
    • + (сложение),
    • - (вычитание),
    • * (умножение),
    • / (деление нацело; для отрицательных чисел работает по тем же правилам, что и в 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

Решение

Задача усложнилась не слишком сильно. Надо разбить операции на группы, так же как они описаны выше и реализовать единый подход к чтению токенов на основе типа операции. В остальном алгоритм остался прежним.

Посмотреть код

Решение

Python
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]))
Подписаться
Уведомить о
guest
2 комментариев
Старые
Новые Популярные
Межтекстовые Отзывы
Посмотреть все комментарии