2025-08-30 11:06:09 +01:00
|
|
|
import operator
|
|
|
|
|
import readline
|
2025-08-30 11:33:20 +01:00
|
|
|
from typing import Callable
|
|
|
|
|
|
2025-08-30 11:06:09 +01:00
|
|
|
|
|
|
|
|
class FifthStack:
|
|
|
|
|
def __init__(self):
|
2025-08-30 11:33:20 +01:00
|
|
|
self.stack: list[int] = []
|
|
|
|
|
self.commands: dict[str, Callable] = {
|
|
|
|
|
"push": self.push,
|
|
|
|
|
"pop": self.pop,
|
|
|
|
|
"swap": self.swap,
|
|
|
|
|
"dup": self.dup,
|
2025-08-30 11:06:09 +01:00
|
|
|
}
|
2025-08-30 11:33:20 +01:00
|
|
|
self.binary_ops: dict[str, Callable[[int, int], int]] = {
|
|
|
|
|
"+": operator.add,
|
|
|
|
|
"-": operator.sub,
|
|
|
|
|
"*": operator.mul,
|
|
|
|
|
"/": operator.floordiv,
|
2025-08-30 11:06:09 +01:00
|
|
|
}
|
2025-08-30 11:33:20 +01:00
|
|
|
|
2025-08-30 11:06:09 +01:00
|
|
|
def _require(self, number, message):
|
|
|
|
|
if len(self.stack) < number:
|
2025-08-30 11:33:20 +01:00
|
|
|
print(f"ERROR: {message}")
|
2025-08-30 11:06:09 +01:00
|
|
|
return False
|
|
|
|
|
return True
|
2025-08-30 11:33:20 +01:00
|
|
|
|
2025-08-30 11:06:09 +01:00
|
|
|
def _get_binary_op(self, command):
|
|
|
|
|
return self.binary_ops.get(command)
|
2025-08-30 11:33:20 +01:00
|
|
|
|
2025-08-30 11:06:09 +01:00
|
|
|
def _binary_op(self, operator):
|
|
|
|
|
if not self._require(2, "two numbers required"):
|
|
|
|
|
return
|
2025-08-30 11:33:20 +01:00
|
|
|
b, a = self.stack.pop(), self.stack.pop()
|
2025-08-30 11:06:09 +01:00
|
|
|
try:
|
|
|
|
|
self.stack.append(operator(a, b))
|
2025-08-30 11:33:20 +01:00
|
|
|
except ZeroDivisionError as e:
|
|
|
|
|
print(f"ERROR: division by zero")
|
2025-08-30 11:06:09 +01:00
|
|
|
self.stack.extend([a, b])
|
2025-08-30 11:33:20 +01:00
|
|
|
|
2025-08-30 11:06:09 +01:00
|
|
|
def push(self, value):
|
|
|
|
|
try:
|
|
|
|
|
self.stack.append(int(value))
|
|
|
|
|
except ValueError:
|
|
|
|
|
print("ERROR: integer required")
|
|
|
|
|
|
2025-08-30 11:33:20 +01:00
|
|
|
def pop(self):
|
2025-08-30 11:06:09 +01:00
|
|
|
if not self.stack:
|
|
|
|
|
print("ERROR: stack empty")
|
|
|
|
|
return
|
|
|
|
|
self.stack.pop()
|
|
|
|
|
|
2025-08-30 11:33:20 +01:00
|
|
|
def swap(self):
|
|
|
|
|
if not self._require(2, "two numbers required"):
|
2025-08-30 11:06:09 +01:00
|
|
|
return
|
|
|
|
|
self.stack[-1], self.stack[-2] = self.stack[-2], self.stack[-1]
|
|
|
|
|
|
2025-08-30 11:33:20 +01:00
|
|
|
def dup(self):
|
|
|
|
|
if self._require(1, "stack empty"):
|
2025-08-30 11:06:09 +01:00
|
|
|
self.stack.append(self.stack[-1])
|
|
|
|
|
|
2025-08-30 11:33:20 +01:00
|
|
|
def execute(self, command: str):
|
2025-08-30 11:06:09 +01:00
|
|
|
tokens = command.lower().strip().split()
|
|
|
|
|
if not tokens:
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
command, argument = tokens[0], tokens[1] if len(tokens) > 1 else None
|
|
|
|
|
function = self.commands.get(command)
|
|
|
|
|
|
2025-08-30 11:33:20 +01:00
|
|
|
if function:
|
|
|
|
|
if command == "push":
|
|
|
|
|
function(argument)
|
|
|
|
|
else:
|
|
|
|
|
function()
|
|
|
|
|
elif command in self.binary_ops:
|
|
|
|
|
self._binary_op(self._get_binary_op(command))
|
|
|
|
|
else:
|
|
|
|
|
print("ERROR: unknown command")
|
|
|
|
|
|
2025-08-30 11:06:09 +01:00
|
|
|
|
|
|
|
|
def main():
|
|
|
|
|
fifth = FifthStack()
|
2025-08-30 11:33:20 +01:00
|
|
|
|
2025-08-30 11:06:09 +01:00
|
|
|
while True:
|
2025-08-30 11:58:19 +01:00
|
|
|
print(f"stack is {fifth.stack}")
|
2025-08-30 11:33:20 +01:00
|
|
|
try:
|
2025-08-30 11:58:19 +01:00
|
|
|
if (command := input().strip().lower()) == "exit":
|
2025-08-30 11:33:20 +01:00
|
|
|
break
|
|
|
|
|
if command:
|
|
|
|
|
fifth.execute(command)
|
|
|
|
|
except (EOFError, KeyboardInterrupt):
|
2025-08-30 11:06:09 +01:00
|
|
|
break
|
|
|
|
|
|
2025-08-30 11:33:20 +01:00
|
|
|
|
|
|
|
|
if __name__ == "__main__":
|
2025-08-30 11:06:09 +01:00
|
|
|
main()
|