turner-townsend-backend-ass.../fifth_stack/fifth_stack.py

103 lines
2.8 KiB
Python
Raw Normal View History

2025-08-30 11:06:09 +01:00
import operator
import readline
from typing import Callable
2025-08-30 11:06:09 +01:00
class FifthStack:
def __init__(self):
self.stack: list[int] = []
self.commands: dict[str, Callable] = {
2025-08-30 12:08:07 +01:00
"help": self.help,
"push": self.push,
"pop": self.pop,
"swap": self.swap,
"dup": self.dup,
2025-08-30 11:06:09 +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:06:09 +01:00
def _require(self, number, message):
if len(self.stack) < number:
print(f"ERROR: {message}")
2025-08-30 11:06:09 +01:00
return False
return True
2025-08-30 11:06:09 +01:00
def _get_binary_op(self, command):
return self.binary_ops.get(command)
2025-08-30 11:06:09 +01:00
def _binary_op(self, operator):
if not self._require(2, "two numbers required"):
return
b, a = self.stack.pop(), self.stack.pop()
2025-08-30 11:06:09 +01:00
try:
self.stack.append(operator(a, b))
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 12:08:07 +01:00
def help(self):
print("Available commands:", ", ".join(cmd.upper() for cmd in self.commands.keys()))
print("Available operations:", ", ".join(self.binary_ops.keys()))
2025-08-30 11:06:09 +01:00
def push(self, value):
try:
self.stack.append(int(value))
except ValueError:
print("ERROR: integer required")
def pop(self):
2025-08-30 11:06:09 +01:00
if not self.stack:
print("ERROR: stack empty")
return
self.stack.pop()
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]
def dup(self):
if self._require(1, "stack empty"):
2025-08-30 11:06:09 +01:00
self.stack.append(self.stack[-1])
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)
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 12:08:07 +01:00
fifth.help()
2025-08-30 11:06:09 +01:00
while True:
print(f"stack is {fifth.stack}")
try:
if (command := input().strip().lower()) == "exit":
break
if command:
fifth.execute(command)
except (EOFError, KeyboardInterrupt):
2025-08-30 11:06:09 +01:00
break
if __name__ == "__main__":
2025-08-30 11:06:09 +01:00
main()