I'm working on a php script that evaluates an object into true or false. The object itself can be nested and contains many objects, for example:
{
"nodeType": "and",
"0": {
"nodeType": "or",
"0": {
"nodeType": "or",
"1": false,
"2": true
},
"3": false
},
"4": true
}
The previous object should be evaluated to true. It can be nested as well, for example:
{
"nodeType": "and",
"0": {
"nodeType": "or",
"0": {
"nodeType": "and",
"0": {
"nodeType": "or",
"1": false,
"2": true
},
"2": true
},
"3": false
},
"4": true
}
I already have a working script that works fine with the help of trincot The script is:
public function findAnswer($expr) {
if (is_bool($expr)) return $expr; // Base case
// If OR, we can stop when we find true (and return true).
// If AND, we can stop when we find false (and return false).
// if($expr["nodeType"] == "not"){
// return ! $expr;
// }
if($expr["nodeType"] == "or"){
$search = true;
}
else{
$search = false;
}
foreach ($expr as $key => $value) {
if ($key !== "nodeType" && $this->findAnswer($value) === $search) {
return $search;
}
}
// If that never happened, return the opposite (false for OR, true for AND)
return !$search;
}
The problem is that the script doesn't work when there is not
as nodeType. example:
{
"nodeType": "and",
"0": {
"nodeType": "or",
"0": {
"nodeType": "not",
"1": false,
},
"3": false
},
"4": false
}
The previous object should be evaluated to false.
Any suggestions to improve the script to work also with not
nodeTypes?
Edit: The answer works with some cases but not with the following:
{
"nodeType": "and",
"0": {
"nodeType": "or",
"0": {
"nodeType": "and",
"0": {
"nodeType": "not",
"1": true
},
"2": true
},
"3": false
},
"4": true
}
This is evaluated to true while it should be evaluated to false.
CodePudding user response:
When the operator is "not", then we could consider the other argument(s) as arguments of a NAND logical operator. So if all arguments are false then it will be evaluated as true, and false otherwise. If you will never pass more than one argument to a NOT operator, then this doesn't really make a difference, but it is nice to make it work also with some logic when more arguments would need to be supported.
Here is the suggested code:
public function findAnswer($expr) {
if (is_bool($expr)) return $expr; // Base case
// If OR, we can stop when we find true (and return true).
// If NAND or NOT, we can stop when we find false (and return false).
// If NOT, negate the outcome. When multiple arguments, perform a NOR operator
$negate = $expr["nodeType"] == "not";
$search = $expr["nodeType"] == "or";
foreach ($expr as $key => $value) {
if ($key !== "nodeType" && $this->findAnswer($value) === $search) {
return $search !== $negate;
}
}
// If that never happened, return the opposite (false for OR, true for AND)
return $search === $negate;
}