Skip to main content

Calculator

class Stack:
def __init__(self):
self.data = []

def peek(self):
if len(self.data) == 0:
return None
return self.data[-1]

def push(self, value):
self.data.append(value)

def isempty(self):
return len(self) == 0

def pop(self):
if len(self.data) > 0:
return self.data.pop()
return None

def __len__(self):
return len(self.data)

def __str__(self):
return f"Stack({self.data})"

def __repr__(self):
return str(self)


class Operator:
Add = "+"
Subtract = "-"
Divide = "/"
Multiply = "*"

def __init__(self):
self.operation = {
Operator.Add: lambda left, right: left + right,
Operator.Subtract: lambda left, right: left - right,
Operator.Divide: lambda left, right: left / right,
Operator.Multiply: lambda left, right: left * right
}
self.priority = {
Operator.Add: 10,
Operator.Subtract: 10,
Operator.Divide: 1000,
Operator.Multiply: 1000
}

def get(self, opr: str):
return self.operation[opr]


class Calculator:
def __init__(self, equation: str):
self.equation: str = equation.strip().replace(" ", "")

self.operator_stack: Stack = Stack()
self.operand_stack: Stack = Stack()
self.operator = Operator()

def process(self):
operand = ''
current_index = 0
digit = ''
for i in range(0, len(self.equation)):
if current_index >= len(self.equation):
break
if self.equation[current_index].isdigit():
while current_index < len(self.equation) and self.equation[current_index].isdigit():
digit += self.equation[current_index]
current_index += 1
self.add_operand(float(digit))
digit = ''

elif self.equation[current_index] == '-':
if current_index == 0:
digit += '-'
else:
# if previous character is digit, then it is an operand
if self.equation[current_index - 1].isdigit():
self.add_operator(self.equation[current_index])
digit = ''
# else it could be a negative value
else:
digit += '-'
current_index += 1

else:
self.add_operator(self.equation[current_index])
current_index += 1
digit = ''

while not self.operator_stack.isempty():
right = self.operand_stack.pop()
left = self.operand_stack.pop()
opr = self.operator_stack.pop()
result = self.operator.operation[opr](left, right)
self.operand_stack.push(result)
final = self.operand_stack.pop()
print(self.equation, '=', final)
return final

def add_operator(self, operator: str):
current_priority = self.operator.priority[operator]

prev_operator = self.operator_stack.peek()
if prev_operator is None:
self.operator_stack.push(operator)
else:
previous_priority = self.operator.priority[prev_operator]
if current_priority <= previous_priority:
right = self.operand_stack.pop()
left = self.operand_stack.pop()
prev_operator = self.operator_stack.pop()
result = self.operator.operation[prev_operator](left, right)
self.operand_stack.push(result)
self.operator_stack.push(operator)
else:
self.operator_stack.push(operator)

def add_operand(self, operand):
self.operand_stack.push(operand)


if __name__ == "__main__":
Calculator("100-10+5").process()
Calculator("100*10+5").process()
Calculator("100-10*5").process()
Calculator("100-10/5").process()
Calculator("100--10/5").process()
Calculator("-100--10/5").process()


Updated on 2020-11-16