Skip to content

Commit b61c547

Browse files
Hardvanalxkm
andauthored
Add Infix To Prefix new algorithm with unit tests (#5537)
* Add `Infix To Prefix` new algorithm * Update directory * Update directory * Fix clang * Fix clang * Add more tests * Fix comma error * Fix test cases * Fix comment * Remove unused import * Update directory * Add tests for null & empty strings * Implement suggested changes * Update directory * Fix comment --------- Co-authored-by: Hardvan <[email protected]> Co-authored-by: Alex Klymenko <[email protected]>
1 parent 5cbdb47 commit b61c547

File tree

3 files changed

+140
-0
lines changed

3 files changed

+140
-0
lines changed

DIRECTORY.md

+4
Original file line numberDiff line numberDiff line change
@@ -268,6 +268,7 @@
268268
* greedyalgorithms
269269
* [ActivitySelection](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/greedyalgorithms/ActivitySelection.java)
270270
* [CoinChange](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/greedyalgorithms/CoinChange.java)
271+
* [DigitSeparation](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/greedyalgorithms/DigitSeparation.java)
271272
* [FractionalKnapsack](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/greedyalgorithms/FractionalKnapsack.java)
272273
* [GaleShapley](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/greedyalgorithms/GaleShapley.java)
273274
* [JobSequencing](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/greedyalgorithms/JobSequencing.java)
@@ -545,6 +546,7 @@
545546
* [DecimalToAnyUsingStack](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/stacks/DecimalToAnyUsingStack.java)
546547
* [DuplicateBrackets](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/stacks/DuplicateBrackets.java)
547548
* [InfixToPostfix](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/stacks/InfixToPostfix.java)
549+
* [InfixToPrefix](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/stacks/InfixToPrefix.java)
548550
* [LargestRectangle](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/stacks/LargestRectangle.java)
549551
* [MaximumMinimumWindow](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/stacks/MaximumMinimumWindow.java)
550552
* [NextGreaterElement](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/stacks/NextGreaterElement.java)
@@ -759,6 +761,7 @@
759761
* greedyalgorithms
760762
* [ActivitySelectionTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/greedyalgorithms/ActivitySelectionTest.java)
761763
* [CoinChangeTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/greedyalgorithms/CoinChangeTest.java)
764+
* [DigitSeparationTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/greedyalgorithms/DigitSeparationTest.java)
762765
* [FractionalKnapsackTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/greedyalgorithms/FractionalKnapsackTest.java)
763766
* [GaleShapleyTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/greedyalgorithms/GaleShapleyTest.java)
764767
* [JobSequencingTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/greedyalgorithms/JobSequencingTest.java)
@@ -976,6 +979,7 @@
976979
* [DecimalToAnyUsingStackTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/stacks/DecimalToAnyUsingStackTest.java)
977980
* [DuplicateBracketsTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/stacks/DuplicateBracketsTest.java)
978981
* [InfixToPostfixTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/stacks/InfixToPostfixTest.java)
982+
* [InfixToPrefixTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/stacks/InfixToPrefixTest.java)
979983
* [LargestRectangleTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/stacks/LargestRectangleTest.java)
980984
* [NextGreaterElementTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/stacks/NextGreaterElementTest.java)
981985
* [NextSmallerElementTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/stacks/NextSmallerElementTest.java)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
package com.thealgorithms.stacks;
2+
3+
import java.util.Stack;
4+
import java.util.regex.Matcher;
5+
import java.util.regex.Pattern;
6+
7+
public final class InfixToPrefix {
8+
private InfixToPrefix() {
9+
}
10+
11+
/**
12+
* Convert an infix expression to a prefix expression using stack.
13+
*
14+
* @param infixExpression the infix expression to convert
15+
* @return the prefix expression
16+
* @throws IllegalArgumentException if the infix expression has unbalanced brackets
17+
* @throws NullPointerException if the infix expression is null
18+
*/
19+
public static String infix2Prefix(String infixExpression) throws IllegalArgumentException {
20+
if (infixExpression == null) {
21+
throw new NullPointerException("Input expression cannot be null.");
22+
}
23+
infixExpression = infixExpression.trim();
24+
if (infixExpression.isEmpty()) {
25+
return "";
26+
}
27+
if (!BalancedBrackets.isBalanced(filterBrackets(infixExpression))) {
28+
throw new IllegalArgumentException("Invalid expression: unbalanced brackets.");
29+
}
30+
31+
StringBuilder output = new StringBuilder();
32+
Stack<Character> stack = new Stack<>();
33+
// Reverse the infix expression for prefix conversion
34+
String reversedInfix = new StringBuilder(infixExpression).reverse().toString();
35+
for (char element : reversedInfix.toCharArray()) {
36+
if (Character.isLetterOrDigit(element)) {
37+
output.append(element);
38+
} else if (element == ')') {
39+
stack.push(element);
40+
} else if (element == '(') {
41+
while (!stack.isEmpty() && stack.peek() != ')') {
42+
output.append(stack.pop());
43+
}
44+
stack.pop();
45+
} else {
46+
while (!stack.isEmpty() && precedence(element) < precedence(stack.peek())) {
47+
output.append(stack.pop());
48+
}
49+
stack.push(element);
50+
}
51+
}
52+
while (!stack.isEmpty()) {
53+
output.append(stack.pop());
54+
}
55+
56+
// Reverse the result to get the prefix expression
57+
return output.reverse().toString();
58+
}
59+
60+
/**
61+
* Determines the precedence of an operator.
62+
*
63+
* @param operator the operator whose precedence is to be determined
64+
* @return the precedence of the operator
65+
*/
66+
private static int precedence(char operator) {
67+
switch (operator) {
68+
case '+':
69+
case '-':
70+
return 0;
71+
case '*':
72+
case '/':
73+
return 1;
74+
case '^':
75+
return 2;
76+
default:
77+
return -1;
78+
}
79+
}
80+
81+
/**
82+
* Filters out all characters from the input string except brackets.
83+
*
84+
* @param input the input string to filter
85+
* @return a string containing only brackets from the input string
86+
*/
87+
private static String filterBrackets(String input) {
88+
Pattern pattern = Pattern.compile("[^(){}\\[\\]<>]");
89+
Matcher matcher = pattern.matcher(input);
90+
return matcher.replaceAll("");
91+
}
92+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
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+
public class InfixToPrefixTest {
13+
14+
@ParameterizedTest
15+
@MethodSource("provideValidExpressions")
16+
void testValidExpressions(String infix, String expectedPrefix) throws Exception {
17+
assertEquals(expectedPrefix, InfixToPrefix.infix2Prefix(infix));
18+
}
19+
20+
@Test
21+
void testEmptyString() {
22+
// Assuming that an empty string returns an empty prefix or throws an exception
23+
assertEquals("", InfixToPrefix.infix2Prefix(""));
24+
}
25+
26+
@Test
27+
void testNullValue() {
28+
// Assuming that a null input throws a NullPointerException
29+
assertThrows(NullPointerException.class, () -> InfixToPrefix.infix2Prefix(null));
30+
}
31+
32+
private static Stream<Arguments> provideValidExpressions() {
33+
return Stream.of(Arguments.of("3+2", "+32"), // Simple addition
34+
Arguments.of("1+(2+3)", "+1+23"), // Parentheses
35+
Arguments.of("(3+4)*5-6", "-*+3456"), // Nested operations
36+
Arguments.of("a+b*c", "+a*bc"), // Multiplication precedence
37+
Arguments.of("a+b*c/d", "+a/*bcd"), // Division precedence
38+
Arguments.of("a+b*c-d", "-+a*bcd"), // Subtraction precedence
39+
Arguments.of("a+b*c/d-e", "-+a/*bcde"), // Mixed precedence
40+
Arguments.of("a+b*(c-d)", "+a*b-cd"), // Parentheses precedence
41+
Arguments.of("a+b*(c-d)/e", "+a/*b-cde") // Mixed precedence with parentheses
42+
);
43+
}
44+
}

0 commit comments

Comments
 (0)