From 55a8fae7b2eb2c4f68cf785bb8b87d95cb1d500b Mon Sep 17 00:00:00 2001 From: Amirsoroush Date: Thu, 20 Apr 2023 00:03:10 +0300 Subject: [PATCH 1/4] fixes #8673; Add operator's associativity check for stacks/infix_to_postfix_conversion.py --- .../stacks/infix_to_postfix_conversion.py | 52 +++++++++++++++++-- 1 file changed, 48 insertions(+), 4 deletions(-) diff --git a/data_structures/stacks/infix_to_postfix_conversion.py b/data_structures/stacks/infix_to_postfix_conversion.py index 9017443091cf..46da13ae507c 100644 --- a/data_structures/stacks/infix_to_postfix_conversion.py +++ b/data_structures/stacks/infix_to_postfix_conversion.py @@ -4,9 +4,26 @@ https://en.wikipedia.org/wiki/Shunting-yard_algorithm """ +from typing import Literal + from .balanced_parentheses import balanced_parentheses from .stack import Stack +PRECEDENCES: dict[str, int] = { + "+": 1, + "-": 1, + "*": 2, + "/": 2, + "^": 3, +} +ASSOCIATIVITIES: dict[str, Literal["LR", "RL"]] = { + "+": "LR", + "-": "LR", + "*": "LR", + "/": "LR", + "^": "RL", +} + def precedence(char: str) -> int: """ @@ -14,7 +31,15 @@ def precedence(char: str) -> int: order of operation. https://en.wikipedia.org/wiki/Order_of_operations """ - return {"+": 1, "-": 1, "*": 2, "/": 2, "^": 3}.get(char, -1) + return PRECEDENCES.get(char, -1) + + +def associativity(char: str) -> Literal["LR", "RL"]: + """ + Return the associativity of the operator `char`. + https://en.wikipedia.org/wiki/Operator_associativity + """ + return ASSOCIATIVITIES[char] def infix_to_postfix(expression_str: str) -> str: @@ -35,6 +60,8 @@ def infix_to_postfix(expression_str: str) -> str: 'a b c * + d e * f + g * +' >>> infix_to_postfix("x^y/(5*z)+2") 'x y ^ 5 z * / 2 +' + >>> infix_to_postfix("2^3^2") + '2 3 2 ^ ^' """ if not balanced_parentheses(expression_str): raise ValueError("Mismatched parentheses") @@ -50,9 +77,26 @@ def infix_to_postfix(expression_str: str) -> str: postfix.append(stack.pop()) stack.pop() else: - while not stack.is_empty() and precedence(char) <= precedence(stack.peek()): - postfix.append(stack.pop()) - stack.push(char) + while True: + if stack.is_empty(): + stack.push(char) + break + + char_precedence = precedence(char) + TOS_precedence = precedence(stack.peek()) + + if char_precedence > TOS_precedence: + stack.push(char) + break + elif char_precedence == TOS_precedence: + if associativity(char) == "RL": + stack.push(char) + break + else: + postfix.append(stack.pop()) + else: + postfix.append(stack.pop()) + while not stack.is_empty(): postfix.append(stack.pop()) return " ".join(postfix) From b82f40259dcca04572e9f7d7d389e3210c366a9f Mon Sep 17 00:00:00 2001 From: Amirsoroush Date: Thu, 20 Apr 2023 00:10:00 +0300 Subject: [PATCH 2/4] fix ruff N806 in stacks/infix_to_postfix_conversion.py --- data_structures/stacks/infix_to_postfix_conversion.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/data_structures/stacks/infix_to_postfix_conversion.py b/data_structures/stacks/infix_to_postfix_conversion.py index 46da13ae507c..9db38e2983ad 100644 --- a/data_structures/stacks/infix_to_postfix_conversion.py +++ b/data_structures/stacks/infix_to_postfix_conversion.py @@ -83,12 +83,12 @@ def infix_to_postfix(expression_str: str) -> str: break char_precedence = precedence(char) - TOS_precedence = precedence(stack.peek()) + tos_precedence = precedence(stack.peek()) - if char_precedence > TOS_precedence: + if char_precedence > tos_precedence: stack.push(char) break - elif char_precedence == TOS_precedence: + elif char_precedence == tos_precedence: if associativity(char) == "RL": stack.push(char) break From 78e9dc4c7ab328bceae0b6126183f06621308371 Mon Sep 17 00:00:00 2001 From: AmirSoroush Date: Mon, 31 Jul 2023 22:53:42 +0300 Subject: [PATCH 3/4] Update data_structures/stacks/infix_to_postfix_conversion.py Co-authored-by: Tianyi Zheng --- .../stacks/infix_to_postfix_conversion.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/data_structures/stacks/infix_to_postfix_conversion.py b/data_structures/stacks/infix_to_postfix_conversion.py index 9db38e2983ad..cd1840f912a5 100644 --- a/data_structures/stacks/infix_to_postfix_conversion.py +++ b/data_structures/stacks/infix_to_postfix_conversion.py @@ -88,14 +88,14 @@ def infix_to_postfix(expression_str: str) -> str: if char_precedence > tos_precedence: stack.push(char) break - elif char_precedence == tos_precedence: - if associativity(char) == "RL": - stack.push(char) - break - else: - postfix.append(stack.pop()) - else: + if char_precedence < tos_precedence: postfix.append(stack.pop()) + break + # Precedences are equal + if associativity(char) == "RL": + stack.push(char) + break + postfix.append(stack.pop()) while not stack.is_empty(): postfix.append(stack.pop()) From 5b760f06f846148f19679460dc14a7c7922da9e8 Mon Sep 17 00:00:00 2001 From: AmirSoroush Date: Mon, 31 Jul 2023 23:07:22 +0300 Subject: [PATCH 4/4] Update data_structures/stacks/infix_to_postfix_conversion.py Co-authored-by: Tianyi Zheng --- data_structures/stacks/infix_to_postfix_conversion.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data_structures/stacks/infix_to_postfix_conversion.py b/data_structures/stacks/infix_to_postfix_conversion.py index cd1840f912a5..e697061937c9 100644 --- a/data_structures/stacks/infix_to_postfix_conversion.py +++ b/data_structures/stacks/infix_to_postfix_conversion.py @@ -90,7 +90,7 @@ def infix_to_postfix(expression_str: str) -> str: break if char_precedence < tos_precedence: postfix.append(stack.pop()) - break + continue # Precedences are equal if associativity(char) == "RL": stack.push(char)