Skip to content

Commit

Permalink
Solution to "Parsing A Boolean Expression" problem
Browse files Browse the repository at this point in the history
  • Loading branch information
dkoval committed Oct 20, 2024
1 parent 3c8bf66 commit 12c2ae3
Show file tree
Hide file tree
Showing 2 changed files with 121 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
package com.github.dkoval.leetcode.challenge;

import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Set;

/**
* <a href="https://leetcode.com/problems/parsing-a-boolean-expression/">Parsing A Boolean Expression (Hard)</a>
* <p>
* A boolean expression is an expression that evaluates to either true or false. It can be in one of the following shapes:
* <ul>
* <li>'t' that evaluates to true.</li>
* <li>'f' that evaluates to false.</li>
* <li>'!(subExpr)' that evaluates to the logical NOT of the inner expression subExpr.</li>
* <li>'&(subExpr1, subExpr2, ..., subExprn)' that evaluates to the logical AND of the inner expressions subExpr1, subExpr2, ..., subExprn where n >= 1.</li>
* <li>'|(subExpr1, subExpr2, ..., subExprn)' that evaluates to the logical OR of the inner expressions subExpr1, subExpr2, ..., subExprn where n >= 1.</li>
* </ul>
* Given a string expression that represents a boolean expression, return the evaluation of that expression.
* <p>
* It is guaranteed that the given expression is valid and follows the given rules.
*/
public interface ParsingBooleanExpression {

boolean parseBoolExpr(String expression);

class ParsingBooleanExpressionRev1 implements ParsingBooleanExpression {
private static final Set<Character> OPERATORS = Set.of('&', '|', '!');
private static final Set<Character> IGNORE = Set.of('(', ',');

@Override
public boolean parseBoolExpr(String expression) {
int n = expression.length();

Deque<Character> stack = new ArrayDeque<>();
for (int i = 0; i < n; i++) {
char c = expression.charAt(i);

if (IGNORE.contains(c)) {
continue;
}

if (c != ')') {
stack.push(c);
} else {
boolean seenTrue = false;
boolean seenFalse = false;

while (!OPERATORS.contains(stack.peek())) {
char x = stack.pop();
if (x == 't') {
seenTrue = true;
} else if (x == 'f') {
seenFalse = true;
}
}

char operator = stack.pop();

if (operator == '&') {
// logical AND
stack.push(seenFalse ? 'f' : 't');
} else if (operator == '|') {
// logical OR
stack.push(seenTrue ? 't' : 'f');
} else {
// logical NOT
stack.push(seenFalse ? 't' : 'f');
}
}
}
return stack.peek() == 't';
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package com.github.dkoval.leetcode.challenge

import com.github.dkoval.leetcode.challenge.ParsingBooleanExpression.ParsingBooleanExpressionRev1
import org.junit.jupiter.api.Assertions.assertEquals
import org.junit.jupiter.api.Nested
import org.junit.jupiter.api.extension.ExtensionContext
import org.junit.jupiter.params.ParameterizedTest
import org.junit.jupiter.params.provider.Arguments
import org.junit.jupiter.params.provider.ArgumentsProvider
import org.junit.jupiter.params.provider.ArgumentsSource
import java.util.stream.Stream

internal class ParsingBooleanExpressionTest {

class InputArgumentsProvider : ArgumentsProvider {

override fun provideArguments(context: ExtensionContext): Stream<out Arguments> = Stream.of(
Arguments.of(
"&(|(f))",
false
),
Arguments.of(
"|(f,f,f,t)",
true
),
Arguments.of(
"!(&(f,t))",
true
)
)
}

@Nested
inner class ParsingBooleanExpressionRev1Test {

@ParameterizedTest
@ArgumentsSource(InputArgumentsProvider::class)
fun `should return the evaluation of the expression`(expression: String, expected: Boolean) {
ParsingBooleanExpressionRev1().test(expression, expected)
}
}
}

private fun ParsingBooleanExpression.test(expression: String, expected: Boolean) {
val actual = parseBoolExpr(expression)
assertEquals(expected, actual)
}

0 comments on commit 12c2ae3

Please sign in to comment.