Detailed Solution for Parsing Boolean Expressions on LeetCode
Understanding the Problem: Evaluating Boolean Expressions
In this problem, we are given a string representing a boolean expression, and we need to evaluate it to determine whether it's true or false. But what exactly is a boolean expression? Parsing Boolean Expression
What is a Boolean Expression?
A boolean expression is a statement that can be either true or false. Think of it like a question that can be answered with a simple "yes" or "no". For example, "Is it raining outside?" is a boolean expression because it can be either true (yes, it's raining) or false (no, it's not raining).
In this problem, we are dealing with a specific type of boolean expression that can be written in a certain format. Let's break it down.
The Format of the Boolean Expression
The boolean expression can be in one of the following shapes:
t
(true)f
(false)!(subExpr)
(NOT subExpr)&(subExpr1, subExpr2,..., subExprn)
(AND of subExpr1, subExpr2,..., subExprn)|(subExpr1, subExpr2,..., subExprn)
(OR of subExpr1, subExpr2,..., subExprn)
Let's understand each of these shapes:
t
andf
are straightforward. They represent true and false values.!(subExpr)
means "NOT subExpr". For example,!(t)
it means "NOT true", which is false.&(subExpr1, subExpr2,..., subExprn)
means "AND of subExpr1, subExpr2,..., subExprn". For example,&(t, f)
it means "true AND false", which is false.|(subExpr1, subExpr2,..., subExprn)
means "OR of subExpr1, subExpr2,..., subExprn". For example,|(f, t)
it means "false OR true", which is true.
Evaluating the Boolean Expression
Our task is to evaluate the given boolean expression and determine whether it's true or false. We can do this by following the order of operations:
Evaluate the innermost expressions first (i.e., the subExprs inside the parentheses).
Apply the logical operations (NOT, AND, OR) to the evaluated expressions.
Repeat steps 1 and 2 until we have a final true or false value.
Intuition
When tackling the problem of evaluating a boolean expression with nested parentheses, our initial thought is to identify and evaluate the innermost expressions first. This is because the values of the inner expressions will be used to determine the values of the outer expressions.
To achieve this, we can utilize a stack data structure to keep track of the expressions and their evaluations. The idea is to push the characters of the expression onto the stack, and when we encounter a closing parenthesis )
, we know that we have reached the end of an inner expression.
Class Structure
The class has a single instance variable $stack
of type SplStack
, which is a PHP class that implements a stack data structure. The class also has several methods:
__construct
: Initializes the$stack
instance variable with a newSplStack
object.evalWithOp
: Evaluates a list of values with a given operator (&
or|
).parseInnerExp
: Parses an inner expression (i.e., a sub-expression enclosed in parentheses) and evaluates it usingevalWithOp
.evalExp
: Evaluates a single expression (i.e., a sub-expression enclosed in parentheses) and returns a boolean value.getExpression
: Retrieves an inner expression from the stack by popping elements until a(
is found.parseBoolExpr
: The main method that parses and evaluates the input boolean expression.
Method Explanations
evalWithOp
This method takes an array of values and an operator (&
or |
) as input. It creates a new stack opStack
and pushes all values onto it. Then, it enters a loop that continues until opStack
it is empty. In each iteration, it:
Checks if
opStack
has only one element left. If so, it returns the value of that element ("t"
or"f"
).Pops two elements from
opStack
, converts them to boolean values (true
orfalse
), and applies the given operator (&
or|
) to them.Pushes the result of the operation back onto
opStack
.
public function evalWithOp(array $values, string $op): bool
{
$opStack = new SplStack();
foreach ($values as $value) {
$opStack->push($value);
}
if ($opStack->count() == 1) {
return $opStack->pop() == "t" ? true : false;
}
while (!$opStack->isEmpty()) {
if ($opStack->count() == 1) {
return $opStack->pop() == "t" ? true : false;
}
$opOne = $opStack->pop();
$opTwo = $opStack->pop();
$leftOp = $opOne == "t" ? true : false;
$rightOp = $opTwo == "t" ? true : false;
if ($op == "&") {
$opStack->push(($leftOp && $rightOp) ? "t" : "f");
}
if ($op == "|") {
$opStack->push(($leftOp || $rightOp) ? "t" : "f");
}
}
}
parseInnerExp
This method takes an inner expression (a string) and an operator (&
or |
) as input. It:
Splits the inner expression into an array of values using commas as separators.
Calls
evalWithOp
to evaluate the array of values with the given operator.Returns the result of the evaluation.
evalExp
This method takes a single expression (a string) as input. It:
Checks the first character of the expression:
If it's
&
, callsparseInnerExp
with the inner expression (everything except the first and last characters) and the&
operator.If it's
|
, callsparseInnerExp
with the inner expression and the|
operator.If it's
!
, callsparseInnerExp
with the inner expression and the!
operator, and negates the result.
Returns the result of the evaluation.
getExpression
This method retrieves an inner expression from the stack by popping elements until a (
is found. It:
Initializes an empty string
innerExp
.While the top element of the stack is not
(
, pops the top element and prepends it toinnerExp
.Pops the
(
element and prepends it toinnerExp
.Returns the complete inner expression.
public function getExpression(): string
{
$innerExp = "";
while ($this->stack->top() != "(") {
$innerExp = $this->stack->pop() . $innerExp;
}
$innerExp = $this->stack->pop() . $innerExp;
return $this->stack->pop() . $innerExp;
}
parseBoolExpr
This method is the main entry point for parsing and evaluating a boolean expression. It:
Iterates over the input expression character by character.
When a
)
is encountered, it:Calls
getExpression
to retrieve the inner expression.Calls
evalExp
to evaluate the inner expression.Pushes the result of the evaluation onto the stack.
When a non-
)
character is encountered, it simply pushes the character onto the stack.After iterating over the entire expression, returns the top element of the stack (
"t"
or"f"
).
public function parseBoolExpr(string $exp): bool
{
$expLen = strlen($exp);
for ($i = 0; $i < $expLen; $i++) {
if ($exp[$i] == ")") {
$this->stack->push($exp[$i]);
$innerExp = $this->getExpression();
$expValue = $this->evalExp($innerExp);
$this->stack->push($expValue ? "t" : "f");
continue;
} else {
$this->stack->push($exp[$i]);
continue;
}
}
return $this->stack->top()=="t" ? true : false;
}
Final Code
class Solution
{
public SplStack $stack;
public function __construct()
{
$this->stack = new SplStack();
}
public function evalWithOp(array $values, string $op): bool
{
$opStack = new SplStack();
foreach ($values as $value) {
$opStack->push($value);
}
if ($opStack->count() == 1) {
return $opStack->pop() == "t" ? true : false;
}
while (!$opStack->isEmpty()) {
if ($opStack->count() == 1) {
return $opStack->pop() == "t" ? true : false;
}
$opOne = $opStack->pop();
$opTwo = $opStack->pop();
$leftOp = $opOne == "t" ? true : false;
$rightOp = $opTwo == "t" ? true : false;
if ($op == "&") {
$opStack->push(($leftOp && $rightOp) ? "t" : "f");
}
if ($op == "|") {
$opStack->push(($leftOp || $rightOp) ? "t" : "f");
}
}
}
public function parseInnerExp(string $exp, string $op)
{
$values = explode(",", $exp);
return $this->evalWithOp($values, $op);
}
public function evalExp(string $innerExp): bool
{
if ($innerExp[0] == "&") {
return $this->parseInnerExp(substr($innerExp, 2, -1), "&");
}
if ($innerExp[0] == "|") {
return $this->parseInnerExp(substr($innerExp, 2, -1), "|");
}
if ($innerExp[0] == "!") {
return !$this->parseInnerExp(substr($innerExp, 2, -1), "!");
}
return true;
}
public function getExpression(): string
{
$innerExp = "";
while ($this->stack->top() != "(") {
$innerExp = $this->stack->pop() . $innerExp;
}
$innerExp = $this->stack->pop() . $innerExp;
return $this->stack->pop() . $innerExp;
}
/**
* @param String $exp
* @return Boolean
*/
public function parseBoolExpr(string $exp): bool
{
$expLen = strlen($exp);
for ($i = 0; $i < $expLen; $i++) {
if ($exp[$i] == ")") {
$this->stack->push($exp[$i]);
$innerExp = $this->getExpression();
$expValue = $this->evalExp($innerExp);
$this->stack->push($expValue ? "t" : "f");
continue;
} else {
$this->stack->push($exp[$i]);
continue;
}
}
return $this->stack->top()=="t" ? true : false;
}
}
Conclusion
we explored the problem of evaluating a boolean expression with nested parentheses and presented a solution that utilizes a stack data structure to efficiently evaluate the expressions. By breaking down the problem into smaller sub-problems and using a stack to track the expressions and their evaluations, we can correctly determine the final result of the boolean expression.
Have you encountered similar problems involving nested structures? How did you approach them? Share your experiences and insights in the comments below!
What do you think about this solution? Do you have any suggestions or improvements? Let us know in the comments below!
Subscribe to my newsletter
Read articles from Saravana Sai directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
Saravana Sai
Saravana Sai
I am a self-taught web developer interested in building something that makes people's life awesome. Writing code for humans not for dump machine