Skip to content

Commit 55a8fae

Browse files
committed
fixes TheAlgorithms#8673; Add operator's associativity check for stacks/infix_to_postfix_conversion.py
1 parent 1158294 commit 55a8fae

File tree

1 file changed

+48
-4
lines changed

1 file changed

+48
-4
lines changed

data_structures/stacks/infix_to_postfix_conversion.py

+48-4
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()):
54-
postfix.append(stack.pop())
55-
stack.push(char)
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+
elif char_precedence == TOS_precedence:
92+
if associativity(char) == "RL":
93+
stack.push(char)
94+
break
95+
else:
96+
postfix.append(stack.pop())
97+
else:
98+
postfix.append(stack.pop())
99+
56100
while not stack.is_empty():
57101
postfix.append(stack.pop())
58102
return " ".join(postfix)

0 commit comments

Comments
 (0)