mirror of
https://github.com/TheAlgorithms/Python.git
synced 2025-02-25 18:38:39 +00:00
fixes #8673; Add operator's associativity check for stacks/infix_to_postfix_conversion.py
This commit is contained in:
parent
11582943a5
commit
55a8fae7b2
@ -4,9 +4,26 @@ https://en.wikipedia.org/wiki/Reverse_Polish_notation
|
|||||||
https://en.wikipedia.org/wiki/Shunting-yard_algorithm
|
https://en.wikipedia.org/wiki/Shunting-yard_algorithm
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
from typing import Literal
|
||||||
|
|
||||||
from .balanced_parentheses import balanced_parentheses
|
from .balanced_parentheses import balanced_parentheses
|
||||||
from .stack import Stack
|
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:
|
def precedence(char: str) -> int:
|
||||||
"""
|
"""
|
||||||
@ -14,7 +31,15 @@ def precedence(char: str) -> int:
|
|||||||
order of operation.
|
order of operation.
|
||||||
https://en.wikipedia.org/wiki/Order_of_operations
|
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:
|
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 * +'
|
'a b c * + d e * f + g * +'
|
||||||
>>> infix_to_postfix("x^y/(5*z)+2")
|
>>> infix_to_postfix("x^y/(5*z)+2")
|
||||||
'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):
|
if not balanced_parentheses(expression_str):
|
||||||
raise ValueError("Mismatched parentheses")
|
raise ValueError("Mismatched parentheses")
|
||||||
@ -50,9 +77,26 @@ def infix_to_postfix(expression_str: str) -> str:
|
|||||||
postfix.append(stack.pop())
|
postfix.append(stack.pop())
|
||||||
stack.pop()
|
stack.pop()
|
||||||
else:
|
else:
|
||||||
while not stack.is_empty() and precedence(char) <= precedence(stack.peek()):
|
while True:
|
||||||
postfix.append(stack.pop())
|
if stack.is_empty():
|
||||||
stack.push(char)
|
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():
|
while not stack.is_empty():
|
||||||
postfix.append(stack.pop())
|
postfix.append(stack.pop())
|
||||||
return " ".join(postfix)
|
return " ".join(postfix)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user