From 447f1192ff1c857b7c49b1ff8b3c96cdabaeffa4 Mon Sep 17 00:00:00 2001 From: echoaj Date: Sun, 16 Aug 2020 08:53:50 -0700 Subject: [PATCH 1/9] created dijkstra's two stack algorithm --- .../stacks/dijkstras_two_stack_algorithm.py | 100 ++++++++++++++++++ 1 file changed, 100 insertions(+) create mode 100644 data_structures/stacks/dijkstras_two_stack_algorithm.py diff --git a/data_structures/stacks/dijkstras_two_stack_algorithm.py b/data_structures/stacks/dijkstras_two_stack_algorithm.py new file mode 100644 index 000000000000..05676d42f4a8 --- /dev/null +++ b/data_structures/stacks/dijkstras_two_stack_algorithm.py @@ -0,0 +1,100 @@ +""" +Author: Alexander Joslin +GitHub: github.com/echoaj + +We can use Dijkstra's two stack algorithm to solve an equation +such as: (5 + ((4 * 2) * (2 + 3))) + +These are the algorithm's rules: +RULE 1: Scan the expression from left to right. When an operand is encountered, push it onto the the operand stack. +RULE 2: When an operator is encountered in the expression, push it onto the operator stack. +RULE 3: When a left parenthesis is encountered in teh expression, ignore it. +RULE 4: When a right parenthesis is encountered in the expression, pop an operator off the operator stack. + The two operands it must operate on must be the last two operands pushed onto the operand stack. + We therefore pop the operand stack twice, perform the operation, and push the result back onto the + operand stack so it will be available for use as an operand of the next operator popped off the + operator stack. +RULE 5: When the entire infix expression has been scanned, the value left on the operand stack represents + the value of the expression. +""" + + +class Stack: + def __init__(self): + self.__array = [] + self.__len = 0 + self.underflow_error = False + + def is_empty(self): + if self.__len == 0: + return True + else: + return False + + def push(self, x): + self.__array.append(x) + self.__len += 1 + + def pop(self): + if not self.is_empty(): # if empty + self.__array.pop() + self.__len -= 1 + self.underflow_error = False + else: # if not empty + self.underflow_error = True + + def peek(self): + return self.__array[-1] if not self.is_empty() else None + + def length(self): + return self.__len + + def print_stack(self): + print(self.__array) + + +def main(): + equation = "(5 + ((4 * 2) * (2 + 3)))" + operand_stack = Stack() + operator_stack = Stack() + + for i in equation: + if i.isdigit(): + # Rule 1 + operand_stack.push(int(i)) + elif i in ['+', '*', '-', '/', '%']: + # Rule 2 + operator_stack.push(i) + elif i == ')': + # Rule 4 + opr1 = operator_stack.peek() + operator_stack.pop() + num1 = operand_stack.peek() + operand_stack.pop() + num2 = operand_stack.peek() + operand_stack.pop() + + total = 0 + if opr1 == '+': + total = num2 + num1 + elif opr1 == '-': + total = num2 - num1 + elif opr1 == '*': + total = num2 * num1 + elif opr1 == '/': + total = num2 / num1 + elif opr1 == '%': + total = num2 % num1 + + operand_stack.push(total) + else: + # Rule 3 + pass + + # Rule 5 + print(operand_stack.peek()) # Result -> 45 + + + +if __name__ == "__main__": + main() \ No newline at end of file From b605ea75b357c7276d5be91c048a333bc74dbab2 Mon Sep 17 00:00:00 2001 From: echoaj Date: Sun, 16 Aug 2020 21:32:30 -0700 Subject: [PATCH 2/9] Made changes to dijkstras two stack algorithm for documentation and testing purposes. --- .../stacks/dijkstras_two_stack_algorithm.py | 85 +++++++++++++------ 1 file changed, 57 insertions(+), 28 deletions(-) diff --git a/data_structures/stacks/dijkstras_two_stack_algorithm.py b/data_structures/stacks/dijkstras_two_stack_algorithm.py index 05676d42f4a8..6518ea502c7f 100644 --- a/data_structures/stacks/dijkstras_two_stack_algorithm.py +++ b/data_structures/stacks/dijkstras_two_stack_algorithm.py @@ -5,21 +5,32 @@ We can use Dijkstra's two stack algorithm to solve an equation such as: (5 + ((4 * 2) * (2 + 3))) -These are the algorithm's rules: -RULE 1: Scan the expression from left to right. When an operand is encountered, push it onto the the operand stack. -RULE 2: When an operator is encountered in the expression, push it onto the operator stack. +THESE ARE THE ALGORITHM'S RULES: +RULE 1: Scan the expression from left to right. When an operand is encountered, + push it onto the the operand stack. + +RULE 2: When an operator is encountered in the expression, + push it onto the operator stack. + RULE 3: When a left parenthesis is encountered in teh expression, ignore it. -RULE 4: When a right parenthesis is encountered in the expression, pop an operator off the operator stack. - The two operands it must operate on must be the last two operands pushed onto the operand stack. - We therefore pop the operand stack twice, perform the operation, and push the result back onto the - operand stack so it will be available for use as an operand of the next operator popped off the - operator stack. -RULE 5: When the entire infix expression has been scanned, the value left on the operand stack represents - the value of the expression. + +RULE 4: When a right parenthesis is encountered in the expression, + pop an operator off the operator stack. The two operands it must + operate on must be the last two operands pushed onto the operand stack. + We therefore pop the operand stack twice, perform the operation, + and push the result back onto the operand stack so it will be available + for use as an operand of the next operator popped off the operator stack. + +RULE 5: When the entire infix expression has been scanned, the value left on + the operand stack represents the value of the expression. + +NOTE: It only works with positive numbers. """ +__author__ = "Omkar Pathak" class Stack: + """ Stack Data Structure Used for the Algorithm""" def __init__(self): self.__array = [] self.__len = 0 @@ -36,11 +47,11 @@ def push(self, x): self.__len += 1 def pop(self): - if not self.is_empty(): # if empty + if not self.is_empty(): self.__array.pop() self.__len -= 1 self.underflow_error = False - else: # if not empty + else: self.underflow_error = True def peek(self): @@ -53,20 +64,31 @@ def print_stack(self): print(self.__array) -def main(): - equation = "(5 + ((4 * 2) * (2 + 3)))" +def dijkstras_two_stack_algorithm(equation): + """ + DocTests + >>> dijkstras_two_stack_algorithm("(5 + 3)") + 8 + >>> dijkstras_two_stack_algorithm("((9 - (2 + 9)) + (8 - 1))") + 5 + >>> dijkstras_two_stack_algorithm("((((3 - 2) - (2 + 3)) + (2 - 4)) + 3)") + -3 + + :param equation: a string + :return: result: an integer + """ operand_stack = Stack() operator_stack = Stack() for i in equation: if i.isdigit(): - # Rule 1 + # RULE 1 operand_stack.push(int(i)) - elif i in ['+', '*', '-', '/', '%']: - # Rule 2 + elif i in ["+", "*", "-", "/", "%"]: + # RULE 2 operator_stack.push(i) - elif i == ')': - # Rule 4 + elif i == ")": + # RULE 4 opr1 = operator_stack.peek() operator_stack.pop() num1 = operand_stack.peek() @@ -75,26 +97,33 @@ def main(): operand_stack.pop() total = 0 - if opr1 == '+': + if opr1 == "+": total = num2 + num1 - elif opr1 == '-': + elif opr1 == "-": total = num2 - num1 - elif opr1 == '*': + elif opr1 == "*": total = num2 * num1 - elif opr1 == '/': + elif opr1 == "/": total = num2 / num1 - elif opr1 == '%': + elif opr1 == "%": total = num2 % num1 operand_stack.push(total) else: - # Rule 3 + # RULE 3 pass - # Rule 5 - print(operand_stack.peek()) # Result -> 45 + # RULE 5 + result = operand_stack.peek() + return result +def main(): + equation = "(5 + ((4 * 2) * (2 + 3)))" + # answer = 45 + answer = dijkstras_two_stack_algorithm(equation) + print(answer) + if __name__ == "__main__": - main() \ No newline at end of file + main() From 3d1f981cbe31eb2a8752c4553b044c447e2abc68 Mon Sep 17 00:00:00 2001 From: echoaj Date: Sun, 16 Aug 2020 21:33:46 -0700 Subject: [PATCH 3/9] Made changes to dijkstras two stack algorithm for documentation and testing purposes. --- data_structures/stacks/dijkstras_two_stack_algorithm.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data_structures/stacks/dijkstras_two_stack_algorithm.py b/data_structures/stacks/dijkstras_two_stack_algorithm.py index 6518ea502c7f..b17ac9140d2f 100644 --- a/data_structures/stacks/dijkstras_two_stack_algorithm.py +++ b/data_structures/stacks/dijkstras_two_stack_algorithm.py @@ -26,7 +26,7 @@ NOTE: It only works with positive numbers. """ -__author__ = "Omkar Pathak" +__author__ = "Alexander Joslin" class Stack: From 88066da964c2d24e817754018e8a9c41cbad8586 Mon Sep 17 00:00:00 2001 From: echoaj Date: Sun, 16 Aug 2020 23:07:10 -0700 Subject: [PATCH 4/9] Fixed Grammar Mistake --- data_structures/stacks/dijkstras_two_stack_algorithm.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data_structures/stacks/dijkstras_two_stack_algorithm.py b/data_structures/stacks/dijkstras_two_stack_algorithm.py index b17ac9140d2f..6cf8d4184aaf 100644 --- a/data_structures/stacks/dijkstras_two_stack_algorithm.py +++ b/data_structures/stacks/dijkstras_two_stack_algorithm.py @@ -12,7 +12,7 @@ RULE 2: When an operator is encountered in the expression, push it onto the operator stack. -RULE 3: When a left parenthesis is encountered in teh expression, ignore it. +RULE 3: When a left parenthesis is encountered in the expression, ignore it. RULE 4: When a right parenthesis is encountered in the expression, pop an operator off the operator stack. The two operands it must From f4ed19e8a42ab3c23dc5d2b7df5bb9b8959ce918 Mon Sep 17 00:00:00 2001 From: echoaj Date: Sun, 16 Aug 2020 23:14:29 -0700 Subject: [PATCH 5/9] Added Explanation Reference --- data_structures/stacks/dijkstras_two_stack_algorithm.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/data_structures/stacks/dijkstras_two_stack_algorithm.py b/data_structures/stacks/dijkstras_two_stack_algorithm.py index 6cf8d4184aaf..c9c192335d69 100644 --- a/data_structures/stacks/dijkstras_two_stack_algorithm.py +++ b/data_structures/stacks/dijkstras_two_stack_algorithm.py @@ -2,6 +2,9 @@ Author: Alexander Joslin GitHub: github.com/echoaj +Explanation: https://medium.com/@haleesammar/implemented-in-js-dijkstras-2-stack- + algorithm-for-evaluating-mathematical-expressions-fc0837dae1ea + We can use Dijkstra's two stack algorithm to solve an equation such as: (5 + ((4 * 2) * (2 + 3))) From fc73824f2ad56fdc83645ed20f81eaccfa7dcbe9 Mon Sep 17 00:00:00 2001 From: echoaj Date: Tue, 18 Aug 2020 14:11:35 -0700 Subject: [PATCH 6/9] Imported stack instead of using my own Changed a few minor things. --- .../stacks/dijkstras_two_stack_algorithm.py | 45 +++---------------- 1 file changed, 5 insertions(+), 40 deletions(-) diff --git a/data_structures/stacks/dijkstras_two_stack_algorithm.py b/data_structures/stacks/dijkstras_two_stack_algorithm.py index c9c192335d69..388d149d20f8 100644 --- a/data_structures/stacks/dijkstras_two_stack_algorithm.py +++ b/data_structures/stacks/dijkstras_two_stack_algorithm.py @@ -27,47 +27,14 @@ RULE 5: When the entire infix expression has been scanned, the value left on the operand stack represents the value of the expression. -NOTE: It only works with positive numbers. +NOTE: It only works with whole numbers . """ __author__ = "Alexander Joslin" +from data_structures.stacks.stack import Stack -class Stack: - """ Stack Data Structure Used for the Algorithm""" - def __init__(self): - self.__array = [] - self.__len = 0 - self.underflow_error = False - def is_empty(self): - if self.__len == 0: - return True - else: - return False - - def push(self, x): - self.__array.append(x) - self.__len += 1 - - def pop(self): - if not self.is_empty(): - self.__array.pop() - self.__len -= 1 - self.underflow_error = False - else: - self.underflow_error = True - - def peek(self): - return self.__array[-1] if not self.is_empty() else None - - def length(self): - return self.__len - - def print_stack(self): - print(self.__array) - - -def dijkstras_two_stack_algorithm(equation): +def dijkstras_two_stack_algorithm(equation: str) -> int: """ DocTests >>> dijkstras_two_stack_algorithm("(5 + 3)") @@ -117,15 +84,13 @@ def dijkstras_two_stack_algorithm(equation): pass # RULE 5 - result = operand_stack.peek() - return result + return operand_stack.peek() def main(): equation = "(5 + ((4 * 2) * (2 + 3)))" # answer = 45 - answer = dijkstras_two_stack_algorithm(equation) - print(answer) + print(f'{equation} = {dijkstras_two_stack_algorithm(equation)}') if __name__ == "__main__": From 6467013d0a09bb7faf6ae4649ab2918d345c7a0b Mon Sep 17 00:00:00 2001 From: echoaj Date: Wed, 19 Aug 2020 13:23:23 -0700 Subject: [PATCH 7/9] Imported stack instead of using my own Changed a few minor things. --- .../stacks/dijkstras_two_stack_algorithm.py | 27 +++++++------------ 1 file changed, 10 insertions(+), 17 deletions(-) diff --git a/data_structures/stacks/dijkstras_two_stack_algorithm.py b/data_structures/stacks/dijkstras_two_stack_algorithm.py index 388d149d20f8..7f05c09379d6 100644 --- a/data_structures/stacks/dijkstras_two_stack_algorithm.py +++ b/data_structures/stacks/dijkstras_two_stack_algorithm.py @@ -27,11 +27,13 @@ RULE 5: When the entire infix expression has been scanned, the value left on the operand stack represents the value of the expression. -NOTE: It only works with whole numbers . +NOTE: It only works with whole numbers. """ __author__ = "Alexander Joslin" -from data_structures.stacks.stack import Stack +from stack import Stack + +import operator as op def dijkstras_two_stack_algorithm(equation: str) -> int: @@ -47,6 +49,8 @@ def dijkstras_two_stack_algorithm(equation: str) -> int: :param equation: a string :return: result: an integer """ + operators = {"*": op.mul, "/": op.truediv, "+": op.add, "-": op.sub} + operand_stack = Stack() operator_stack = Stack() @@ -54,30 +58,19 @@ def dijkstras_two_stack_algorithm(equation: str) -> int: if i.isdigit(): # RULE 1 operand_stack.push(int(i)) - elif i in ["+", "*", "-", "/", "%"]: + elif i in operators: # RULE 2 operator_stack.push(i) elif i == ")": # RULE 4 - opr1 = operator_stack.peek() + opr = operator_stack.peek() operator_stack.pop() num1 = operand_stack.peek() operand_stack.pop() num2 = operand_stack.peek() operand_stack.pop() - total = 0 - if opr1 == "+": - total = num2 + num1 - elif opr1 == "-": - total = num2 - num1 - elif opr1 == "*": - total = num2 * num1 - elif opr1 == "/": - total = num2 / num1 - elif opr1 == "%": - total = num2 % num1 - + total = operators[opr](num2, num1) operand_stack.push(total) else: # RULE 3 @@ -90,7 +83,7 @@ def dijkstras_two_stack_algorithm(equation: str) -> int: def main(): equation = "(5 + ((4 * 2) * (2 + 3)))" # answer = 45 - print(f'{equation} = {dijkstras_two_stack_algorithm(equation)}') + print(f"{equation} = {dijkstras_two_stack_algorithm(equation)}") if __name__ == "__main__": From 972a5a40ee7d29f4416665e3287d6b966b91dbef Mon Sep 17 00:00:00 2001 From: Alex Joslin Date: Wed, 19 Aug 2020 15:58:31 -0700 Subject: [PATCH 8/9] Update data_structures/stacks/dijkstras_two_stack_algorithm.py Co-authored-by: Christian Clauss --- data_structures/stacks/dijkstras_two_stack_algorithm.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data_structures/stacks/dijkstras_two_stack_algorithm.py b/data_structures/stacks/dijkstras_two_stack_algorithm.py index 7f05c09379d6..89a4d861b9ee 100644 --- a/data_structures/stacks/dijkstras_two_stack_algorithm.py +++ b/data_structures/stacks/dijkstras_two_stack_algorithm.py @@ -31,7 +31,7 @@ """ __author__ = "Alexander Joslin" -from stack import Stack +from .stack import Stack import operator as op From b30b5617ea6966504a92b1d721901eb2f18591b0 Mon Sep 17 00:00:00 2001 From: Christian Clauss Date: Thu, 20 Aug 2020 16:52:41 +0200 Subject: [PATCH 9/9] Update dijkstras_two_stack_algorithm.py --- data_structures/stacks/dijkstras_two_stack_algorithm.py | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/data_structures/stacks/dijkstras_two_stack_algorithm.py b/data_structures/stacks/dijkstras_two_stack_algorithm.py index 89a4d861b9ee..59d47085ada5 100644 --- a/data_structures/stacks/dijkstras_two_stack_algorithm.py +++ b/data_structures/stacks/dijkstras_two_stack_algorithm.py @@ -72,19 +72,12 @@ def dijkstras_two_stack_algorithm(equation: str) -> int: total = operators[opr](num2, num1) operand_stack.push(total) - else: - # RULE 3 - pass # RULE 5 return operand_stack.peek() -def main(): +if __name__ == "__main__": equation = "(5 + ((4 * 2) * (2 + 3)))" # answer = 45 print(f"{equation} = {dijkstras_two_stack_algorithm(equation)}") - - -if __name__ == "__main__": - main()