Repository: TheAlgorithms/Python

Issue:
There is a missing check for the "associativity" of the operators in the stacks/infix_to_postfix_conversion.py file.
### Repository commit

11582943a555ae3b6a22938df6d3645b0327562e

### Python version (python --version)

Python 3.10.6

### Dependencies version (pip freeze)

astroid==2.11.3
bcc==0.18.0
black==22.3.0
blinker==1.4
Brlapi==0.8.3
certifi==2020.6.20
chardet==4.0.0


### Expected behavior

Hi, In the [data_structures/stacks/infix_to_postfix_conversion.py](https://github.com/TheAlgorithms/Python/blob/master/data_structures/stacks/infix_to_postfix_conversion.py) file, when we pass `"2^3^2"` argument to the `infix_to_postfix` function, it should return `'2 3 2 ^ ^'` back. This results in number `512` which is the correct calculation.

### Actual behavior

Currently `infix_to_postfix("2^3^2")` returns `'2 3 ^ 2 ^'` which is wrong. If we calculate it, it returns number `64`.

The reason behind this is that currently we don't have any check for the "associativity" of the operators. In particular `^` operator causes problem here. It has `Right-To-Left` associativity. 
There is a missing check for the "associativity" of the operators in the stacks/infix_to_postfix_conversion.py file.
### Repository commit

11582943a555ae3b6a22938df6d3645b0327562e

### Python version (python --version)

Python 3.10.6

### Dependencies version (pip freeze)

astroid==2.11.3
bcc==0.18.0
black==22.3.0
blinker==1.4
Brlapi==0.8.3
certifi==2020.6.20
chardet==4.0.0


### Expected behavior

Hi, In the [data_structures/stacks/infix_to_postfix_conversion.py](https://github.com/TheAlgorithms/Python/blob/master/data_structures/stacks/infix_to_postfix_conversion.py) file, when we pass `"2^3^2"` argument to the `infix_to_postfix` function, it should return `'2 3 2 ^ ^'` back. This results in number `512` which is the correct calculation.

### Actual behavior

Currently `infix_to_postfix("2^3^2")` returns `'2 3 ^ 2 ^'` which is wrong. If we calculate it, it returns number `64`.

The reason behind this is that currently we don't have any check for the "associativity" of the operators. In particular `^` operator causes problem here. It has `Right-To-Left` associativity. 


Discussion:

Resolving patch:
diff --git a/data_structures/stacks/infix_to_postfix_conversion.py b/data_structures/stacks/infix_to_postfix_conversion.py
--- 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()):
+            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
+                if char_precedence < tos_precedence:
+                    postfix.append(stack.pop())
+                    continue
+                # Precedences are equal
+                if associativity(char) == "RL":
+                    stack.push(char)
+                    break
                 postfix.append(stack.pop())
-            stack.push(char)
+
     while not stack.is_empty():
         postfix.append(stack.pop())
     return " ".join(postfix)


Test patch: