package com.interview.books.ccinterview;
import java.util.HashMap;
/**
* Created_By: stefanie
* Date: 14-12-13
* Time: 下午8:42
*/
public class CC23_ParenthesizeExpression {
int[] total; //Cat(N): Catalan Sequence
//Memo: key is "start-end", also can use int[exp.rows()][exp.rows()], but need set initial value to -1
HashMap<String, Integer> trueCount;
public int countWays(String exp, boolean result) {
trueCount = new HashMap<>();
total = catalan((exp.length() - 1) / 2);
return countWays(exp, result, 0, exp.length() - 1);
}
private int countWays(String exp, boolean expected, int start, int end) {
String key = start + "-" + end;
int ways = 0;
if (trueCount.containsKey(key)) ways = trueCount.get(key);
else {
if (start == end) { //unit case
if (exp.charAt(start) == '1') ways = 1;
else ways = 0;
}
for (int i = start + 1; i <= end; i += 2) { //enumerate places to insert parenthesis
char op = exp.charAt(i);
if (op == '&') {
ways += countWays(exp, true, start, i - 1) * countWays(exp, true, i + 1, end);
} else if (op == '|') {
int leftOps = (i - 1 - start) / 2;
int rightOps = (end - i - 1) / 2;
int totalWays = total[leftOps] + total[rightOps];
int totalFalse = countWays(exp, false, start, i - 1) * countWays(exp, false, i + 1, end);
ways += totalWays - totalFalse;
} else if (op == '^') {
ways += countWays(exp, true, start, i - 1) * countWays(exp, false, i + 1, end);
ways += countWays(exp, false, start, i - 1) * countWays(exp, true, i + 1, end);
}
}
trueCount.put(key, ways);
}
if (expected) { //expected == True
return ways;
} else { //expected == False
int len = (end - start) / 2;
return total[len] - ways;
}
}
private int[] catalan(int n) {
int[] total = new int[n + 1];
total[0] = 1;
for (int i = 1; i <= n; i++) {
for (int j = 0; j < i; j++) {
total[i] += total[j] * total[i - 1 - j];
}
}
return total;
}
public static void main(String[] args) {
CC23_ParenthesizeExpression counter = new CC23_ParenthesizeExpression();
String exp = "1^0|0|1";
System.out.println(counter.countWays(exp, false));
}
}