# Boolean Parenthesization Problem | DP-37

Given a boolean expression with the following symbols.

Symbols
'T' ---> true
'F' ---> false 

And following operators filled between symbols

Operators
&   ---> boolean AND
|   ---> boolean OR
^   ---> boolean XOR 

Count the number of ways we can parenthesize the expression so that the value of expression evaluates to true.
Let the input be in form of two arrays one contains the symbols (T and F) in order and the other contains operators (&, | and ^}

Examples:

Input: symbol[]    = {T, F, T}
operator[]  = {^, &}
Output: 2
The given expression is "T ^ F & T", it evaluates true
in two ways "((T ^ F) & T)" and "(T ^ (F & T))"

Input: symbol[]    = {T, F, F}
operator[]  = {^, |}
Output: 2
The given expression is "T ^ F | F", it evaluates true
in two ways "( (T ^ F) | F )" and "( T ^ (F | F) )".

Input: symbol[]    = {T, T, F, T}
operator[]  = {|, &, ^}
Output: 4
The given expression is "T | T & F ^ T", it evaluates true
in 4 ways ((T|T)&(F^T)), (T|(T&(F^T))), (((T|T)&F)^T)
and (T|((T&F)^T)). 
Recommended Practice

Solution:
Let T(i, j) represent the number of ways to parenthesize the symbols between i and j (both inclusive) such that the subexpression between i and j evaluates to true.

Let F(i, j) represent the number of ways to parenthesize the symbols between i and j (inclusive) such that the subexpression between i and j evaluates to false.

Base Cases:

T(i, i) = 1 if symbol[i] = 'T'
T(i, i) = 0 if symbol[i] = 'F'

F(i, i) = 1 if symbol[i] = 'F'
F(i, i) = 0 if symbol[i] = 'T'

If we draw the recursion tree of the above recursive solution, we can observe that it has many overlapping subproblems. Like other dynamic programming problems, it can be solved by filling a table in a bottom-up manner. Following is the implementation of a dynamic programming solution.

## C++

 #include  #include  using namespace std;   // Returns count of all possible // parenthesizations that lead // to result true for a boolean  // expression with symbols like // true and false and operators  // like &, | and ^ filled // between symbols int countParenth(char symb[], char oper[], int n) {     int F[n][n], T[n][n];       // Fill diagonal entries first     // All diagonal entries in      // T[i][i] are 1 if symbol[i]     // is T (true).  Similarly,      // all F[i][i] entries are 1 if     // symbol[i] is F (False)     for (int i = 0; i < n; i++) {         F[i][i] = (symb[i] == 'F') ? 1 : 0;         T[i][i] = (symb[i] == 'T') ? 1 : 0;     }       // Now fill T[i][i+1],      // T[i][i+2], T[i][i+3]... in order     // And F[i][i+1], F[i][i+2],      // F[i][i+3]... in order     for (int gap = 1; gap < n; ++gap)      {         for (int i = 0, j = gap;               j < n; ++i, ++j)         {             T[i][j] = F[i][j] = 0;             for (int g = 0;                  g < gap; g++)             {                 // Find place of parenthesization using                 // current value of gap                 int k = i + g;                   // Store Total[i][k]                  // and Total[k+1][j]                 int tik = T[i][k] + F[i][k];                 int tkj = T[k + 1][j]                    + F[k + 1][j];                   // Follow the recursive formulas                  // according                 // to the current operator                 if (oper[k] == '&') {                     T[i][j] += T[i][k]                              * T[k + 1][j];                     F[i][j] += (tik * tkj                                 - T[i][k]                                  * T[k + 1][j]);                 }                 if (oper[k] == '|') {                     F[i][j] += F[i][k]                        * F[k + 1][j];                     T[i][j] += (tik * tkj                                 - F[i][k]                                  * F[k + 1][j]);                 }                 if (oper[k] == '^') {                     T[i][j] += F[i][k]                        * T[k + 1][j]                       + T[i][k]                       * F[k + 1][j];                     F[i][j] += T[i][k]                              * T[k + 1][j]                             + F[i][k] * F[k + 1][j];                 }             }         }     }     return T[0][n - 1]; }   // Driver code int main() {     char symbols[] = "TTFT";     char operators[] = "|&^";     int n = strlen(symbols);       // There are 4 ways     // ((T|T)&(F^T)), (T|(T&(F^T))), (((T|T)&F)^T) and     // (T|((T&F)^T))     cout << countParenth(symbols, operators, n);     return 0; }

## Java

 import java.io.*; import java.util.*;   class GFG {       // Returns count of all possible     // parenthesizations that lead to     // result true for a boolean     // expression with symbols like true     // and false and operators like &, |     // and ^ filled between symbols     static int countParenth(char symb[], char oper[], int n)     {         int F[][] = new int[n][n];         int T[][] = new int[n][n];           // Fill diagonal entries first         // All diagonal entries in T[i][i]         // are 1 if symbol[i] is T (true).         // Similarly, all F[i][i] entries         // are 1 if symbol[i] is F (False)         for (int i = 0; i < n; i++) {             F[i][i] = (symb[i] == 'F') ? 1 : 0;             T[i][i] = (symb[i] == 'T') ? 1 : 0;         }           // Now fill T[i][i+1], T[i][i+2],         // T[i][i+3]... in order And F[i][i+1],         // F[i][i+2], F[i][i+3]... in order         for (int gap = 1; gap < n; ++gap) {             for (int i = 0, j = gap; j < n; ++i, ++j) {                 T[i][j] = F[i][j] = 0;                 for (int g = 0; g < gap; g++)                   {                     // Find place of parenthesization                     // using current value of gap                     int k = i + g;                       // Store Total[i][k]                     // and Total[k+1][j]                     int tik = T[i][k] + F[i][k];                     int tkj = T[k + 1][j] + F[k + 1][j];                       // Follow the recursive formulas                     // according to the current operator                     if (oper[k] == '&') {                         T[i][j] += T[i][k] * T[k + 1][j];                         F[i][j]                             += (tik * tkj                                 - T[i][k] * T[k + 1][j]);                     }                     if (oper[k] == '|') {                         F[i][j] += F[i][k] * F[k + 1][j];                         T[i][j]                             += (tik * tkj                                 - F[i][k] * F[k + 1][j]);                     }                     if (oper[k] == '^') {                         T[i][j] += F[i][k] * T[k + 1][j]                                    + T[i][k] * F[k + 1][j];                         F[i][j] += T[i][k] * T[k + 1][j]                                    + F[i][k] * F[k + 1][j];                     }                 }             }         }         return T[0][n - 1];     }       // Driver code     public static void main(String[] args)     {         char symbols[] = "TTFT".toCharArray();         char operators[] = "|&^".toCharArray();         int n = symbols.length;           // There are 4 ways         // ((T|T)&(F^T)), (T|(T&(F^T))),         // (((T|T)&F)^T) and (T|((T&F)^T))         System.out.println(             countParenth(symbols, operators, n));     } }   // This code has been contributed // by 29AjayKumar

## Python

 # Returns count of all possible # parenthesizations that lead to # result true for a boolean # expression with symbols like # true and false and operators # like &, | and ^ filled between symbols     def countParenth(symb, oper, n):     F = [[0 for i in range(n + 1)]          for i in range(n + 1)]     T = [[0 for i in range(n + 1)]          for i in range(n + 1)]       # Fill diagonal entries first     # All diagonal entries in     # T[i][i] are 1 if symbol[i]     # is T (true). Similarly, all     # F[i][i] entries are 1 if     # symbol[i] is F (False)     for i in range(n):         if symb[i] == 'F':             F[i][i] = 1         else:             F[i][i] = 0           if symb[i] == 'T':             T[i][i] = 1         else:             T[i][i] = 0       # Now fill T[i][i+1], T[i][i+2],     # T[i][i+3]... in order And     # F[i][i+1], F[i][i+2],     # F[i][i+3]... in order     for gap in range(1, n):         i = 0         for j in range(gap, n):             T[i][j] = F[i][j] = 0             for g in range(gap):                   # Find place of parenthesization                 # using current value of gap                 k = i + g                   # Store Total[i][k] and Total[k+1][j]                 tik = T[i][k] + F[i][k]                 tkj = T[k + 1][j] + F[k + 1][j]                   # Follow the recursive formulas                 # according to the current operator                 if oper[k] == '&':                     T[i][j] += T[i][k] * T[k + 1][j]                     F[i][j] += (tik * tkj - T[i][k] *                                 T[k + 1][j])                 if oper[k] == '|':                     F[i][j] += F[i][k] * F[k + 1][j]                     T[i][j] += (tik * tkj - F[i][k] *                                 F[k + 1][j])                 if oper[k] == '^':                     T[i][j] += (F[i][k] * T[k + 1][j] +                                 T[i][k] * F[k + 1][j])                     F[i][j] += (T[i][k] * T[k + 1][j] +                                 F[i][k] * F[k + 1][j])             i += 1     return T[0][n - 1]     # Driver Code symbols = "TTFT" operators = "|&^" n = len(symbols)   # There are 4 ways # ((T|T)&(F^T)), (T|(T&(F^T))), # (((T|T)&F)^T) and (T|((T&F)^T)) print(countParenth(symbols, operators, n))   # This code is contributed by # sahil shelangia

## C#

 // C# program of above approach using System;   class GFG  {           // Returns count of all possible      // parenthesizations that lead to     // result true for a boolean      // expression with symbols like true     // and false and operators like &, |      // and ^ filled between symbols     static int countParenth(char []symb,                      char []oper, int n)      {         int [,]F = new int[n, n];         int [,]T = new int[n, n];           // Fill diagonal entries first         // All diagonal entries in T[i,i]          // are 1 if symbol[i] is T (true).          // Similarly, all F[i,i] entries          // are 1 if symbol[i] is F (False)         for (int i = 0; i < n; i++)          {             F[i,i] = (symb[i] == 'F') ? 1 : 0;             T[i,i] = (symb[i] == 'T') ? 1 : 0;         }           // Now fill T[i,i+1], T[i,i+2],          // T[i,i+3]... in order And F[i,i+1],         // F[i,i+2], F[i,i+3]... in order         for (int gap = 1; gap < n; ++gap)         {             for (int i = 0, j = gap; j < n; ++i, ++j)              {                 T[i, j] = F[i, j] = 0;                 for (int g = 0; g < gap; g++)                  {                     // Find place of parenthesization                      // using current value of gap                     int k = i + g;                       // Store Total[i,k] and Total[k+1,j]                     int tik = T[i, k] + F[i, k];                     int tkj = T[k + 1, j] + F[k + 1, j];                       // Follow the recursive formulas                      // according to the current operator                     if (oper[k] == '&')                      {                         T[i, j] += T[i, k]                                  * T[k + 1, j];                         F[i, j] += (tik * tkj                                  - T[i, k] * T[k + 1, j]);                     }                     if (oper[k] == '|')                      {                         F[i,j] += F[i, k]                            * F[k + 1, j];                         T[i,j] += (tik                                 * tkj - F[i, k]                                     * F[k + 1, j]);                     }                     if (oper[k] == '^')                     {                         T[i, j] += F[i, k] * T[k + 1, j] +                                      T[i, k] * F[k + 1, j];                         F[i, j] += T[i, k] * T[k + 1, j] +                                      F[i, k] * F[k + 1, j];                     }                 }             }         }         return T[0,n - 1];     }       // Driver code     public static void Main()      {         char []symbols = "TTFT".ToCharArray();         char []operators = "|&^".ToCharArray();         int n = symbols.Length;           // There are 4 ways         // ((T|T)&(F^T)), (T|(T&(F^T))),          // (((T|T)&F)^T) and (T|((T&F)^T))         Console.WriteLine(countParenth(symbols,                             operators, n));     } }   /* This code contributed by PrinciRaj1992 */

## Javascript

 

Output

4

Time Complexity: O(n3), as we are using nested loops to traverse n3 times. Where n is the length of the symbols string.
Auxiliary Space: O(n2), as we are using extra space for the DP matrix. Where n is the length of the symbols string.

Approach 2:

We can also use the recursive approach (Top-Down DP), this approach uses memoization.

## C++

 #include  using namespace std;   int dp[101][101][2]; int parenthesis_count(string s,                        int i,                        int j,                        int isTrue) {     // Base Condition     if (i > j)         return false;     if (i == j) {         if (isTrue == 1)             return s[i] == 'T';         else             return s[i] == 'F';     }       if (dp[i][j][isTrue] != -1)         return dp[i][j][isTrue];     int ans = 0;     for (int k = i + 1          ; k <= j - 1; k = k + 2)      {         int leftF, leftT, rightT, rightF;         if (dp[i][k - 1][1] == -1)          {             leftT = parenthesis_count(s, i, k - 1, 1);         } // Count no. of T in left partition         else {             leftT = dp[i][k - 1][1];         }           if (dp[k + 1][j][1] == -1)          {             rightT = parenthesis_count(s, k + 1, j, 1);         } // Count no. of T in right partition         else         {             rightT = dp[k + 1][j][1];         }           if (dp[i][k - 1][0] == -1)          {             // Count no. of F in left partition             leftF = parenthesis_count(s, i, k - 1, 0);         }         else         {             leftF = dp[i][k - 1][0];         }           if (dp[k + 1][j][0] == -1)          {             // Count no. of F in right partition             rightF = parenthesis_count(s, k + 1, j, 0);         }         else         {             rightF = dp[k + 1][j][0];         }           if (s[k] == '&')         {             if (isTrue == 1)                 ans += leftT * rightT;             else                 ans += leftF * rightF + leftT * rightF                        + leftF * rightT;         }         else if (s[k] == '|')         {             if (isTrue == 1)                 ans += leftT * rightT + leftT * rightF                        + leftF * rightT;             else                 ans = ans + leftF * rightF;         }         else if (s[k] == '^')         {             if (isTrue == 1)                 ans = ans + leftF * rightT + leftT * rightF;             else                 ans = ans + leftT * rightT + leftF * rightF;         }         dp[i][j][isTrue] = ans;     }     return ans; }   // Driver Code int main() {     string symbols = "TTFT";     string operators = "|&^";     string s;     int j = 0;       for (int i = 0; i < symbols.length(); i++)      {         s.push_back(symbols[i]);         if (j < operators.length())             s.push_back(operators[j++]);     }           // We obtain the string  T|T&F^T     int n = s.length();           // There are 4 ways     // ((T|T)&(F^T)), (T|(T&(F^T))), (((T|T)&F)^T) and     // (T|((T&F)^T))     memset(dp, -1, sizeof(dp));     cout << parenthesis_count(s, 0, n - 1, 1);     return 0; }

## Java

 import java.io.*; import java.util.*;   class GFG {     public static int countWays(int N, String S)     {         int dp[][][] = new int[N + 1][N + 1][2];           for (int row[][] : dp)             for (int col[] : row)                 Arrays.fill(col, -1);         return parenthesis_count(S, 0, N - 1, 1, dp);     }       public static int parenthesis_count(String str, int i,                                         int j, int isTrue,                                         int[][][] dp)     {         if (i > j)             return 0;           if (i == j)         {             if (isTrue == 1)             {                 return (str.charAt(i) == 'T') ? 1 : 0;             }             else             {                 return (str.charAt(i) == 'F') ? 1 : 0;             }         }           if (dp[i][j][isTrue] != -1)             return dp[i][j][isTrue];           int temp_ans = 0;           int leftTrue, rightTrue, leftFalse, rightFalse;           for (int k = i + 1; k <= j - 1; k = k + 2)          {               if (dp[i][k - 1][1] != -1)                 leftTrue = dp[i][k - 1][1];             else             {                 // Count number of True in left Partition                 leftTrue = parenthesis_count(str, i, k - 1,                                              1, dp);             }             if (dp[i][k - 1][0] != -1)                 leftFalse = dp[i][k - 1][0];             else             {                                 // Count number of False in left Partition                 leftFalse = parenthesis_count(str, i, k - 1,                                               0, dp);             }             if (dp[k + 1][j][1] != -1)                 rightTrue = dp[k + 1][j][1];             else             {                                 // Count number of True in right Partition                 rightTrue = parenthesis_count(str, k + 1, j,                                               1, dp);             }             if (dp[k + 1][j][0] != -1)                 rightFalse = dp[k + 1][j][0];             else             {                                 // Count number of False in right Partition                 rightFalse = parenthesis_count(str, k + 1,                                                j, 0, dp);             }               // Evaluate AND operation             if (str.charAt(k) == '&')             {                 if (isTrue == 1)                  {                     temp_ans                         = temp_ans + leftTrue * rightTrue;                 }                 else                 {                     temp_ans = temp_ans                                + leftTrue * rightFalse                                + leftFalse * rightTrue                                + leftFalse * rightFalse;                 }             }             // Evaluate OR operation             else if (str.charAt(k) == '|')             {                 if (isTrue == 1)                 {                     temp_ans = temp_ans                                + leftTrue * rightTrue                                + leftTrue * rightFalse                                + leftFalse * rightTrue;                 }                 else                 {                     temp_ans                         = temp_ans + leftFalse * rightFalse;                 }             }                         // Evaluate XOR operation             else if (str.charAt(k) == '^')              {                 if (isTrue == 1)                 {                     temp_ans = temp_ans                                + leftTrue * rightFalse                                + leftFalse * rightTrue;                 }                 else                 {                     temp_ans = temp_ans                                + leftTrue * rightTrue                                + leftFalse * rightFalse;                 }             }             dp[i][j][isTrue] = temp_ans;         }         return temp_ans;     }       // Driver code     public static void main(String[] args)     {         String symbols = "TTFT";         String operators = "|&^";         StringBuilder S = new StringBuilder();         int j = 0;           for (int i = 0; i < symbols.length(); i++)         {             S.append(symbols.charAt(i));             if (j < operators.length())                 S.append(operators.charAt(j++));         }           // We obtain the string  T|T&F^T         int N = S.length();           // There are 4 ways         // ((T|T)&(F^T)), (T|(T&(F^T))), (((T|T)&F)^T) and         // (T|((T&F)^T))         System.out.println(countWays(N, S.toString()));     } }   // This code is contributed by farheenbano.

## Python3

 def parenthesis_count(Str, i, j, isTrue, dp) :           if (i > j) :       return 0           if (i == j) :             if (isTrue == 1) :                 return 1 if Str[i] == 'T' else 0               else :                 return 1 if Str[i] == 'F' else 0           if (dp[i][j][isTrue] != -1) :       return dp[i][j][isTrue]           temp_ans = 0           for k in range(i + 1, j, 2) :             if (dp[i][k - 1][1] != -1) :         leftTrue = dp[i][k - 1][1]       else :         # Count number of True in left Partition         leftTrue = parenthesis_count(Str, i, k - 1, 1, dp)                 if (dp[i][k - 1][0] != -1) :         leftFalse = dp[i][k - 1][0]       else :         # Count number of False in left Partition         leftFalse = parenthesis_count(Str, i, k - 1, 0, dp)              if (dp[k + 1][j][1] != -1) :         rightTrue = dp[k + 1][j][1]       else :         # Count number of True in right Partition         rightTrue = parenthesis_count(Str, k + 1, j, 1, dp)               if (dp[k + 1][j][0] != -1) :         rightFalse = dp[k + 1][j][0]       else :         # Count number of False in right Partition         rightFalse = parenthesis_count(Str, k + 1, j, 0, dp)             # Evaluate AND operation       if (Str[k] == '&') :         if (isTrue == 1) :           temp_ans = temp_ans + leftTrue * rightTrue         else :           temp_ans = temp_ans + leftTrue * rightFalse + leftFalse * rightTrue + leftFalse * rightFalse       # Evaluate OR operation       elif (Str[k] == '|') :         if (isTrue == 1) :           temp_ans = temp_ans + leftTrue * rightTrue + leftTrue * rightFalse + leftFalse * rightTrue         else :           temp_ans = temp_ans + leftFalse * rightFalse             # Evaluate XOR operation       elif (Str[k] == '^') :          if (isTrue == 1) :           temp_ans = temp_ans + leftTrue * rightFalse + leftFalse * rightTrue         else :           temp_ans = temp_ans + leftTrue * rightTrue + leftFalse * rightFalse       dp[i][j][isTrue] = temp_ans       return temp_ans       def countWays(N, S) :        dp = [[[-1 for k in range(2)] for i in range(N + 1)] for j in range(N + 1)]      return parenthesis_count(S, 0, N - 1, 1, dp)    symbols = "TTFT" operators = "|&^" S = "" j = 0 for i in range(len(symbols)) :     S = S + symbols[i]   if (j < len(operators)) :     S = S + operators[j]     j += 1   # We obtain the string  T|T&F^T N = len(S)   # There are 4 ways # ((T|T)&(F^T)), (T|(T&(F^T))), (((T|T)&F)^T) and # (T|((T&F)^T)) print(countWays(N, S))   # This code is contributed by divyesh072019

## C#

 using System; class GFG  {     static int parenthesis_count(string str, int i,                                int j, int isTrue,                                int[,,] dp)   {     if (i > j)       return 0;       if (i == j)     {       if (isTrue == 1)       {         return (str[i] == 'T') ? 1 : 0;       }       else       {         return (str[i] == 'F') ? 1 : 0;       }     }       if (dp[i, j, isTrue] != -1)       return dp[i, j, isTrue];       int temp_ans = 0;       int leftTrue, rightTrue, leftFalse, rightFalse;       for (int k = i + 1; k <= j - 1; k = k + 2)      {         if (dp[i, k - 1, 1] != -1)         leftTrue = dp[i, k - 1, 1];       else       {         // Count number of True in left Partition         leftTrue = parenthesis_count(str, i, k - 1, 1, dp);       }       if (dp[i, k - 1, 0] != -1)         leftFalse = dp[i, k - 1, 0];       else       {           // Count number of False in left Partition         leftFalse = parenthesis_count(str, i, k - 1, 0, dp);       }       if (dp[k + 1, j, 1] != -1)         rightTrue = dp[k + 1, j, 1];       else       {           // Count number of True in right Partition         rightTrue = parenthesis_count(str, k + 1, j,                                       1, dp);       }       if (dp[k + 1, j, 0] != -1)         rightFalse = dp[k + 1, j, 0];       else       {           // Count number of False in right Partition         rightFalse = parenthesis_count(str, k + 1,                                        j, 0, dp);       }         // Evaluate AND operation       if (str[k] == '&')       {         if (isTrue == 1)          {           temp_ans             = temp_ans + leftTrue * rightTrue;         }         else         {           temp_ans = temp_ans             + leftTrue * rightFalse             + leftFalse * rightTrue             + leftFalse * rightFalse;         }       }       // Evaluate OR operation       else if (str[k] == '|')       {         if (isTrue == 1)         {           temp_ans = temp_ans             + leftTrue * rightTrue             + leftTrue * rightFalse             + leftFalse * rightTrue;         }         else         {           temp_ans             = temp_ans + leftFalse * rightFalse;         }       }         // Evaluate XOR operation       else if (str[k] == '^')        {         if (isTrue == 1)         {           temp_ans = temp_ans             + leftTrue * rightFalse             + leftFalse * rightTrue;         }         else         {           temp_ans = temp_ans             + leftTrue * rightTrue             + leftFalse * rightFalse;         }       }       dp[i, j, isTrue] = temp_ans;     }     return temp_ans;   }     static int countWays(int N, string S)   {     int[,,] dp = new int[N + 1, N + 1, 2];     for(int i = 0; i < (N + 1); i++)     {       for(int j = 0; j < (N + 1); j++)       {         for(int k = 0; k < 2; k++)         {           dp[i, j, k] = -1;         }       }     }     return parenthesis_count(S, 0, N - 1, 1, dp);   }     // Driver code   static void Main()    {     string symbols = "TTFT";     string operators = "|&^";     string S = "";     int j = 0;     for (int i = 0; i < symbols.Length; i++)     {       S = S + symbols[i];       if (j < operators.Length)         S = S + operators[j++];     }       // We obtain the string  T|T&F^T     int N = S.Length;       // There are 4 ways     // ((T|T)&(F^T)), (T|(T&(F^T))), (((T|T)&F)^T) and     // (T|((T&F)^T))     Console.WriteLine(countWays(N, S));   } }   // This code is contributed by divyeshrabadiya07.

## Javascript

 

Output

4

Time Complexity: O(n3), as we are using a loop to traverse, n times and we are making recursive calls which will cost n2 times. Where n is the length of the symbols string.
Auxiliary Space: O(n2), as we are using extra space for the DP matrix. Where n is the length of the symbols string.

References:
http://people.cs.clemson.edu/~bcdean/dp_practice/dp_9.swf