Skip to content
52 changes: 48 additions & 4 deletions data_structures/stacks/infix_to_postfix_conversion.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,42 @@
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:
"""
Return integer value representing an operator's precedence, or
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:
Expand All @@ -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")
Expand All @@ -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)
Expand Down