diff --git a/DIRECTORY.md b/DIRECTORY.md index ea5e01add..7c6958921 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -674,6 +674,8 @@ * [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_056/sol1.py) * Problem 057 * [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_057/sol1.py) + * Problem 058 + * [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_058/sol1.py) * Problem 062 * [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_062/sol1.py) * Problem 063 @@ -699,6 +701,8 @@ * [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_080/sol1.py) * Problem 081 * [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_081/sol1.py) + * Problem 087 + * [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_087/sol1.py) * Problem 091 * [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_091/sol1.py) * Problem 097 @@ -817,6 +821,7 @@ * [Prefix Function](https://github.com/TheAlgorithms/Python/blob/master/strings/prefix_function.py) * [Rabin Karp](https://github.com/TheAlgorithms/Python/blob/master/strings/rabin_karp.py) * [Remove Duplicate](https://github.com/TheAlgorithms/Python/blob/master/strings/remove_duplicate.py) + * [Reverse Letters](https://github.com/TheAlgorithms/Python/blob/master/strings/reverse_letters.py) * [Reverse Words](https://github.com/TheAlgorithms/Python/blob/master/strings/reverse_words.py) * [Split](https://github.com/TheAlgorithms/Python/blob/master/strings/split.py) * [Swap Case](https://github.com/TheAlgorithms/Python/blob/master/strings/swap_case.py) diff --git a/data_structures/stacks/__init__.py b/data_structures/stacks/__init__.py index f6995cf98..e69de29bb 100644 --- a/data_structures/stacks/__init__.py +++ b/data_structures/stacks/__init__.py @@ -1,22 +0,0 @@ -class Stack: - def __init__(self): - self.stack = [] - self.top = 0 - - def is_empty(self): - return self.top == 0 - - def push(self, item): - if self.top < len(self.stack): - self.stack[self.top] = item - else: - self.stack.append(item) - - self.top += 1 - - def pop(self): - if self.is_empty(): - return None - else: - self.top -= 1 - return self.stack[self.top] diff --git a/data_structures/stacks/infix_to_postfix_conversion.py b/data_structures/stacks/infix_to_postfix_conversion.py index 4a1180c9d..dedba8479 100644 --- a/data_structures/stacks/infix_to_postfix_conversion.py +++ b/data_structures/stacks/infix_to_postfix_conversion.py @@ -1,57 +1,67 @@ -import string +""" +https://en.wikipedia.org/wiki/Infix_notation +https://en.wikipedia.org/wiki/Reverse_Polish_notation +https://en.wikipedia.org/wiki/Shunting-yard_algorithm +""" +from .balanced_parentheses import balanced_parentheses from .stack import Stack -__author__ = "Omkar Pathak" - -def is_operand(char): - return char in string.ascii_letters or char in string.digits - - -def precedence(char): - """Return integer value representing an operator's precedence, or +def precedence(char: str) -> int: + """ + Return integer value representing an operator's precedence, or order of operation. - https://en.wikipedia.org/wiki/Order_of_operations """ - dictionary = {"+": 1, "-": 1, "*": 2, "/": 2, "^": 3} - return dictionary.get(char, -1) + return {"+": 1, "-": 1, "*": 2, "/": 2, "^": 3}.get(char, -1) -def infix_to_postfix(expression): - """Convert infix notation to postfix notation using the Shunting-yard - algorithm. - - https://en.wikipedia.org/wiki/Shunting-yard_algorithm - https://en.wikipedia.org/wiki/Infix_notation - https://en.wikipedia.org/wiki/Reverse_Polish_notation +def infix_to_postfix(expression_str: str) -> str: """ - stack = Stack(len(expression)) + >>> infix_to_postfix("(1*(2+3)+4))") + Traceback (most recent call last): + ... + ValueError: Mismatched parentheses + >>> infix_to_postfix("") + '' + >>> infix_to_postfix("3+2") + '3 2 +' + >>> infix_to_postfix("(3+4)*5-6") + '3 4 + 5 * 6 -' + >>> infix_to_postfix("(1+2)*3/4-5") + '1 2 + 3 * 4 / 5 -' + >>> infix_to_postfix("a+b*c+(d*e+f)*g") + 'a b c * + d e * f + g * +' + >>> infix_to_postfix("x^y/(5*z)+2") + 'x y ^ 5 z * / 2 +' + """ + if not balanced_parentheses(expression_str): + raise ValueError("Mismatched parentheses") + stack = Stack() postfix = [] - for char in expression: - if is_operand(char): + for char in expression_str: + if char.isalpha() or char.isdigit(): postfix.append(char) - elif char not in {"(", ")"}: - while not stack.is_empty() and precedence(char) <= precedence(stack.peek()): - postfix.append(stack.pop()) - stack.push(char) elif char == "(": stack.push(char) elif char == ")": while not stack.is_empty() and stack.peek() != "(": postfix.append(stack.pop()) - # Pop '(' from stack. If there is no '(', there is a mismatched - # parentheses. - if stack.peek() != "(": - raise ValueError("Mismatched parentheses") stack.pop() + else: + while not stack.is_empty() and precedence(char) <= precedence(stack.peek()): + postfix.append(stack.pop()) + stack.push(char) while not stack.is_empty(): postfix.append(stack.pop()) return " ".join(postfix) if __name__ == "__main__": + from doctest import testmod + + testmod() expression = "a+b*(c^d-e)^(f+g*h)-i" print("Infix to Postfix Notation demonstration:\n")