From 12c2ae3901b25c6a0343260715022f6cd9b7d30d Mon Sep 17 00:00:00 2001 From: dkoval Date: Sun, 20 Oct 2024 23:05:01 +0200 Subject: [PATCH] Solution to "Parsing A Boolean Expression" problem --- .../challenge/ParsingBooleanExpression.java | 74 +++++++++++++++++++ .../challenge/ParsingBooleanExpressionTest.kt | 47 ++++++++++++ 2 files changed, 121 insertions(+) create mode 100644 src/main/java/com/github/dkoval/leetcode/challenge/ParsingBooleanExpression.java create mode 100644 src/test/kotlin/com/github/dkoval/leetcode/challenge/ParsingBooleanExpressionTest.kt diff --git a/src/main/java/com/github/dkoval/leetcode/challenge/ParsingBooleanExpression.java b/src/main/java/com/github/dkoval/leetcode/challenge/ParsingBooleanExpression.java new file mode 100644 index 00000000..8002670e --- /dev/null +++ b/src/main/java/com/github/dkoval/leetcode/challenge/ParsingBooleanExpression.java @@ -0,0 +1,74 @@ +package com.github.dkoval.leetcode.challenge; + +import java.util.ArrayDeque; +import java.util.Deque; +import java.util.Set; + +/** + * Parsing A Boolean Expression (Hard) + *

+ * A boolean expression is an expression that evaluates to either true or false. It can be in one of the following shapes: + *

+ * Given a string expression that represents a boolean expression, return the evaluation of that expression. + *

+ * 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 OPERATORS = Set.of('&', '|', '!'); + private static final Set IGNORE = Set.of('(', ','); + + @Override + public boolean parseBoolExpr(String expression) { + int n = expression.length(); + + Deque 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'; + } + } +} diff --git a/src/test/kotlin/com/github/dkoval/leetcode/challenge/ParsingBooleanExpressionTest.kt b/src/test/kotlin/com/github/dkoval/leetcode/challenge/ParsingBooleanExpressionTest.kt new file mode 100644 index 00000000..1ccb5216 --- /dev/null +++ b/src/test/kotlin/com/github/dkoval/leetcode/challenge/ParsingBooleanExpressionTest.kt @@ -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 = 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) +}