Skip to content

Commit 633b9d4

Browse files
alxkmalxkm
and
alxkm
authored
refactor: PostfixToInfix (#5409)
* refactor: PostfixToInfix * checkstyle: fix formatting * refactor: add support for one character --------- Co-authored-by: alxkm <[email protected]>
1 parent fc5a70e commit 633b9d4

File tree

2 files changed

+74
-83
lines changed

2 files changed

+74
-83
lines changed

src/main/java/com/thealgorithms/stacks/PostfixToInfix.java

+41-83
Original file line numberDiff line numberDiff line change
@@ -20,125 +20,83 @@ public final class PostfixToInfix {
2020
private PostfixToInfix() {
2121
}
2222

23+
/**
24+
* Determines if a given character is a valid arithmetic operator.
25+
*
26+
* @param token the character to check
27+
* @return true if the character is an operator, false otherwise
28+
*/
2329
public static boolean isOperator(char token) {
24-
switch (token) {
25-
case '+':
26-
case '-':
27-
case '/':
28-
case '*':
29-
case '^':
30-
return true;
31-
default:
32-
return false;
33-
}
30+
return token == '+' || token == '-' || token == '/' || token == '*' || token == '^';
3431
}
3532

33+
/**
34+
* Validates whether a given string is a valid postfix expression.
35+
*
36+
* A valid postfix expression must meet these criteria:
37+
* 1. It should have at least one operator and two operands.
38+
* 2. The number of operands should always be greater than the number of operators at any point in the traversal.
39+
*
40+
* @param postfix the postfix expression string to validate
41+
* @return true if the expression is valid, false otherwise
42+
*/
3643
public static boolean isValidPostfixExpression(String postfix) {
37-
/* Postfix expression length should NOT be less than 3 */
38-
if (postfix.length() < 3) {
39-
return false;
44+
if (postfix.length() == 1 && (Character.isAlphabetic(postfix.charAt(0)))) {
45+
return true;
4046
}
4147

42-
/* First two characters should NOT be operators */
43-
if (isOperator(postfix.charAt(0))) {
44-
return false;
45-
}
46-
if (isOperator(postfix.charAt(1))) {
47-
return false;
48+
if (postfix.length() < 3) {
49+
return false; // Postfix expression should have at least one operator and two operands
4850
}
4951

5052
int operandCount = 0;
5153
int operatorCount = 0;
5254

53-
/* Traverse the postfix string to check if --> Number of operands = Number of operators + 1
54-
*/
55-
for (int i = 0; i < postfix.length(); i++) {
56-
char token = postfix.charAt(i);
57-
55+
for (char token : postfix.toCharArray()) {
5856
if (isOperator(token)) {
5957
operatorCount++;
6058
if (operatorCount >= operandCount) {
61-
return false;
59+
return false; // Invalid: more operators than operands at any point
6260
}
6361
} else {
64-
if (operatorCount == 0) {
65-
operandCount++;
66-
continue;
67-
}
68-
69-
if (operandCount != operatorCount + 1) {
70-
return false;
71-
}
72-
73-
/* Operand count is set to 2 because:-
74-
*
75-
* 1) the previous set of operands & operators combined have become a single valid
76-
* expression, which could be considered/assigned as a single operand.
77-
*
78-
* 2) the operand in the current iteration.
79-
*/
80-
operandCount = 2;
81-
82-
/* Reset operator count */
83-
operatorCount = 0;
62+
operandCount++;
8463
}
8564
}
8665

87-
return (operandCount == operatorCount + 1);
66+
return operandCount == operatorCount + 1;
8867
}
8968

69+
/**
70+
* Converts a valid postfix expression to an infix expression.
71+
*
72+
* @param postfix the postfix expression to convert
73+
* @return the equivalent infix expression
74+
* @throws IllegalArgumentException if the postfix expression is invalid
75+
*/
9076
public static String getPostfixToInfix(String postfix) {
91-
String infix = "";
92-
9377
if (postfix.isEmpty()) {
94-
return infix;
78+
return "";
9579
}
9680

97-
/* Validate Postfix expression before proceeding with the Infix conversion */
9881
if (!isValidPostfixExpression(postfix)) {
9982
throw new IllegalArgumentException("Invalid Postfix Expression");
10083
}
10184

10285
Stack<String> stack = new Stack<>();
10386
StringBuilder valueString = new StringBuilder();
10487

105-
String operandA;
106-
String operandB;
107-
char operator;
108-
109-
for (int index = 0; index < postfix.length(); index++) {
110-
char token = postfix.charAt(index);
111-
88+
for (char token : postfix.toCharArray()) {
11289
if (!isOperator(token)) {
11390
stack.push(Character.toString(token));
114-
continue;
91+
} else {
92+
String operandB = stack.pop();
93+
String operandA = stack.pop();
94+
valueString.append('(').append(operandA).append(token).append(operandB).append(')');
95+
stack.push(valueString.toString());
96+
valueString.setLength(0);
11597
}
116-
117-
operator = token;
118-
operandB = stack.pop();
119-
operandA = stack.pop();
120-
121-
valueString.append('(');
122-
123-
valueString.append(operandA);
124-
valueString.append(operator);
125-
valueString.append(operandB);
126-
127-
valueString.append(')');
128-
129-
stack.push(valueString.toString());
130-
valueString.setLength(0);
13198
}
13299

133-
infix = stack.pop();
134-
return infix;
135-
}
136-
137-
public static void main(String[] args) {
138-
assert getPostfixToInfix("ABC+/").equals("(A/(B+C))");
139-
assert getPostfixToInfix("AB+CD+*").equals("((A+B)*(C+D))");
140-
assert getPostfixToInfix("AB+C+D+").equals("(((A+B)+C)+D)");
141-
assert getPostfixToInfix("ABCDE^*/-").equals("(A-(B/(C*(D^E))))");
142-
assert getPostfixToInfix("AB+CD^/E*FGH+-^").equals("((((A+B)/(C^D))*E)^(F-(G+H)))");
100+
return stack.pop();
143101
}
144102
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
package com.thealgorithms.stacks;
2+
3+
import static org.junit.jupiter.api.Assertions.assertEquals;
4+
import static org.junit.jupiter.api.Assertions.assertThrows;
5+
6+
import java.util.stream.Stream;
7+
import org.junit.jupiter.api.Test;
8+
import org.junit.jupiter.params.ParameterizedTest;
9+
import org.junit.jupiter.params.provider.Arguments;
10+
import org.junit.jupiter.params.provider.MethodSource;
11+
12+
class PostfixToInfixTest {
13+
14+
@ParameterizedTest
15+
@MethodSource("provideValidPostfixToInfixTestCases")
16+
void testValidPostfixToInfixConversion(String postfix, String expectedInfix) {
17+
assertEquals(expectedInfix, PostfixToInfix.getPostfixToInfix(postfix));
18+
}
19+
20+
static Stream<Arguments> provideValidPostfixToInfixTestCases() {
21+
return Stream.of(Arguments.of("A", "A"), Arguments.of("ABC+/", "(A/(B+C))"), Arguments.of("AB+CD+*", "((A+B)*(C+D))"), Arguments.of("AB+C+D+", "(((A+B)+C)+D)"), Arguments.of("ABCDE^*/-", "(A-(B/(C*(D^E))))"), Arguments.of("AB+CD^/E*FGH+-^", "((((A+B)/(C^D))*E)^(F-(G+H)))"));
22+
}
23+
24+
@Test
25+
void testEmptyPostfixExpression() {
26+
assertEquals("", PostfixToInfix.getPostfixToInfix(""));
27+
}
28+
29+
@Test
30+
void testNullPostfixExpression() {
31+
assertThrows(NullPointerException.class, () -> PostfixToInfix.getPostfixToInfix(null));
32+
}
33+
}

0 commit comments

Comments
 (0)