Skip to content

Commit ce218c5

Browse files
fixes #8673; Add operator's associativity check for stacks/infix_to_p… (#8674)
* fixes #8673; Add operator's associativity check for stacks/infix_to_postfix_conversion.py * fix ruff N806 in stacks/infix_to_postfix_conversion.py * Update data_structures/stacks/infix_to_postfix_conversion.py Co-authored-by: Tianyi Zheng <tianyizheng02@gmail.com> * Update data_structures/stacks/infix_to_postfix_conversion.py Co-authored-by: Tianyi Zheng <tianyizheng02@gmail.com> --------- Co-authored-by: Tianyi Zheng <tianyizheng02@gmail.com>
1 parent c9a7234 commit ce218c5

File tree

1 file changed

+47
-3
lines changed

1 file changed

+47
-3
lines changed

data_structures/stacks/infix_to_postfix_conversion.py

+47-3
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,42 @@
44
https://en.wikipedia.org/wiki/Shunting-yard_algorithm
55
"""
66

7+
from typing import Literal
8+
79
from .balanced_parentheses import balanced_parentheses
810
from .stack import Stack
911

12+
PRECEDENCES: dict[str, int] = {
13+
"+": 1,
14+
"-": 1,
15+
"*": 2,
16+
"/": 2,
17+
"^": 3,
18+
}
19+
ASSOCIATIVITIES: dict[str, Literal["LR", "RL"]] = {
20+
"+": "LR",
21+
"-": "LR",
22+
"*": "LR",
23+
"/": "LR",
24+
"^": "RL",
25+
}
26+
1027

1128
def precedence(char: str) -> int:
1229
"""
1330
Return integer value representing an operator's precedence, or
1431
order of operation.
1532
https://en.wikipedia.org/wiki/Order_of_operations
1633
"""
17-
return {"+": 1, "-": 1, "*": 2, "/": 2, "^": 3}.get(char, -1)
34+
return PRECEDENCES.get(char, -1)
35+
36+
37+
def associativity(char: str) -> Literal["LR", "RL"]:
38+
"""
39+
Return the associativity of the operator `char`.
40+
https://en.wikipedia.org/wiki/Operator_associativity
41+
"""
42+
return ASSOCIATIVITIES[char]
1843

1944

2045
def infix_to_postfix(expression_str: str) -> str:
@@ -35,6 +60,8 @@ def infix_to_postfix(expression_str: str) -> str:
3560
'a b c * + d e * f + g * +'
3661
>>> infix_to_postfix("x^y/(5*z)+2")
3762
'x y ^ 5 z * / 2 +'
63+
>>> infix_to_postfix("2^3^2")
64+
'2 3 2 ^ ^'
3865
"""
3966
if not balanced_parentheses(expression_str):
4067
raise ValueError("Mismatched parentheses")
@@ -50,9 +77,26 @@ def infix_to_postfix(expression_str: str) -> str:
5077
postfix.append(stack.pop())
5178
stack.pop()
5279
else:
53-
while not stack.is_empty() and precedence(char) <= precedence(stack.peek()):
80+
while True:
81+
if stack.is_empty():
82+
stack.push(char)
83+
break
84+
85+
char_precedence = precedence(char)
86+
tos_precedence = precedence(stack.peek())
87+
88+
if char_precedence > tos_precedence:
89+
stack.push(char)
90+
break
91+
if char_precedence < tos_precedence:
92+
postfix.append(stack.pop())
93+
continue
94+
# Precedences are equal
95+
if associativity(char) == "RL":
96+
stack.push(char)
97+
break
5498
postfix.append(stack.pop())
55-
stack.push(char)
99+
56100
while not stack.is_empty():
57101
postfix.append(stack.pop())
58102
return " ".join(postfix)

0 commit comments

Comments
 (0)