-
Notifications
You must be signed in to change notification settings - Fork 8
/
Copy pathcalculator.py
133 lines (110 loc) · 4.07 KB
/
calculator.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
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()