将所有逻辑表达式变量放入数组中

时间:2016-06-05 01:40:01

标签: java arrays truthtable

我正在编写一个程序,它将打印表达式的真值表。目前我的代码采用逻辑表达式并将其转换为两个数组,如输入中所示。我需要帮助来满足我的算法的以下输出

示例:逻辑表达式=(( - A)+ B))+ C

输入:

logExp:[(,(, - ,A,),+,B,),),+,C]

indepVar:[A,B,C]

预期产出:

数组:[A,B,C,( - A),( - A)+ B,((-A)+ B))+ C] //确定是否带括号。

当前输出我使用此算法:

数组:[A,B,C,( - A)+ B)]

代码:

public static ArrayList<String> Head(ArrayList<Character> logExp, ArrayList<Character> indepVar){
    ArrayList<String> array = new ArrayList<String>();
    int count = 0;
    String str = "";

    for(int i = 0; i < indepVar.size(); i++){
        array.add(indepVar.get(i).toString());
    }

    for(int i = 0; i < logExp.size(); i++){
        if(logExp.get(i)== '(')
            count++;
        else if(logExp.get(i) == ')')
            count--;
        if(count > 0)
            str += logExp.get(i);
        if(count == 0 && str != ""){
            array.add(str);
            str = "";
        }

    }
    return array;

我对递归函数不是很熟悉,但我尝试做类似于上面算法的算法,算法应该通过取一个字符串并将括号之间的所有内容添加到数组来递归工作。

然后再次将其作为参数传递给同一算法,直到括号中的所有表达式都添加到数组中。但它并没有很好地工作,我不知道我错了。有什么想法吗?

以下是代码:

public static ArrayList<String> rec(String str){
    int count = 0;
    char ch;
    String s = "";
    ArrayList<String> array = new ArrayList<String>();

    for(int i = 0; i < str.length(); i++){
        ch = str.charAt(i);

        if(ch == '(')
            count++;
        if(count > 0)
            s += ch;

        if(ch == ')')
            count--;

        if(count == 0 && s != ""){
            s = s.substring(1, s.length()-1);
            array.add(s);
            count = 0;
            return rec(s);
        }
    }
    return array;
}

2 个答案:

答案 0 :(得分:0)

您当前的算法所做的是在一组括号内添加任何内容。从这个问题的性质来看,我认为它应该是递归的。

一个简单的解决方案(伪代码)是:

 zones: [{
      value: 1000, 
      color: 'green'
    }, {
      color: 'red'
    }],

我希望这有帮助!

答案 1 :(得分:0)

我不知道这是否能完全达到预期的输出效果,但是如果你试图打破基于主操作符的逻辑公式,就好像我有公式:

(AvB) - &gt; ç

主要运营商将是&#34; - &gt;&#34;。在你给出的公式中:

(( - A)+ B))+ C

它将是&#34; +&#34;。然后你可以迭代公式字符串并跟踪计数变量中的左右括号,注意到当你到达公式中左右计数相等的点时,紧跟在后面的字符将成为主运算符类似的东西:

    for (int i = 0; i < formula.length(); i++) {
        if (formula.charAt(i) == '(')
            countl++;
        if (formula.charAt(i) == ')')
            countr++;
        if ((countl == countr) && countl != 0) {
            indexOfOp = i;
            break;
        }
    }

现在如果你想以递归的方式做这件事,你可以使用这个一般的想法:

    ArrayList<String> subFormulas = new ArrayList<>();
String[][] parseFormulas(String formula) {
    base case where if formula doesnt have parentheses return the operands 

    subFormulas.add(formula);
    for (int i = 0; i < formula.length(); i++) {
        if (formula.charAt(i) == '(')
            countl++;
        if (formula.charAt(i) == ')')
            countr++;
        if ((countl == countr) && countl != 0) {
            indexOfOp = i;
            break;
        }
    }

    // for a formula "A op B"
    parseFormulas(formula.substring(0, indexOfOp + 1));//A
    parseFormulas(formula.substring(indexOfOp + 2, formula.length()));//B

}

此方法可能有效,但如果您尝试打印真值表,则可以更容易使用postfix表示法来解析和计算公式的真值。你将它与你的变量的所有真值组合组合起来制作真值表。这是我实施这个想法的可怜尝试:

public class TruthTable {

//highest order of precedence going from the right of array
char[] operators = {'<', '>', 'v', '&', '~'};

//list of variables
char[] alphabet = {
        'a', 'b', 'c', 'd', 'e', 'f', 'g',
        'h', 'i', 'j', 'k', 'l', 'm', 'n',
        'o', 'p', 'q', 'r', 's', 't', 'u',
        'w', 'x', 'y', 'z', 'A', 'B',
        'C', 'D', 'E', 'F', 'G', 'H', 'I',
        'J', 'K', 'L', 'M', 'N', 'O', 'P',
        'Q', 'R', 'S', 'T', 'U', 'W',
        'X', 'Y', 'Z'
};


public static void printString(String[][] s) {
    for (int i = 0; i < s.length; i++) {
        System.out.print("{");
        for (int j = 0; j < s[0].length; j++) {
            System.out.print(s[i][j]);
            if (!(j == s[0].length - 1)) {
                System.out.print(" ");
            }
        }
        System.out.println("}");
    }

}
public static int indexOf(ArrayList<Character> list, Character c) {
    int index = 0;
    for (int i = 0; i < list.size(); i++) {
        if (list.get(i) == c) {
            index = i;
        }
    }
    return index;
}
public static boolean contains(ArrayList<Character> list, Character c) {
    for (Character i : list) {
        if (i == c) return true;
    }
    return false;
}
public static boolean contains(char[] chars, Character c) {
    for (int i = 0; i < chars.length; i++) {
        if (chars[i] == c) return true;
    }
    return false;
}


/**
 * used this w/ makeTable to print to console
 */
public static String[][] makeEven(String[][] table){
    for(int j=0;j<table[0].length;j++){
        int largestString=0;
        for(int i=0;i<table.length;i++){
            if(table[i][j].length()>largestString)
                largestString = table[i][j].length();
        }
        for(int i=0;i<table.length;i++){
            if(table[i][j].length()<largestString){
                int diff=((largestString-table[i][j].length())/2);
                int middle=((diff/2)+1);
                String tmp = table[i][j];
                table[i][j]="";
                int count=0;
                while(table[i][j].length()!=largestString){
                    count++;
                    if(count!=middle)
                        table[i][j] += " ";

                    else
                        table[i][j] +=tmp;

                }
            }
        }
    }
    return table;
}

/**
 * POSSIBLY WORST METHOD EVER DEVISED FOR PRINTING A TABLE
 * @return the table to be printed
 */
public static String[][] makeTable(String formula, char[] variables, ArrayList<ArrayList<Boolean>> combos) {
    int spacing = 2;
    String[][] result = new String[combos.size() + 3][(spacing + 1) * variables.length + formula.length() + 2 * spacing];
    for (int i = 0; i < result.length; i++) {
        int count = 0;
        int k = 0;
        for (int j = 0; j < result[0].length; j++) {
            if (i == 1) {
                if(j < (variables.length * (spacing + 1) + spacing)) {
                    if ((j % (spacing + 1) == 2)) {
                        result[i][j] = "" + variables[k];
                        k++;
                    } else result[i][j] = "*";
                }
                else{
                    if (j == (variables.length * (spacing + 1) + spacing + (formula.length() / 2))) {
                        result[i][j]=formula;
                    } else result[i][j] = " ";
                }
            }
            if (i == 0 || i == (result[0].length - 1) || i == 2)
                result[i][j] = "*";

            if (j < (variables.length * (spacing + 1) + spacing) && (i > 2)) {
                if (j % (spacing + 1) == 2) {
                    if (combos.get(i - 3).get(count))
                        result[i][j] = "True";
                    else result[i][j] = "False";
                    count++;
                } else result[i][j] = "*";
            }
            else if(i>2) {
                if (j == (variables.length * (spacing + 1) + spacing + (formula.length() / 2))) {
                    if (combos.get(i - 3).get(count)) result[i][j] = "True";
                    else result[i][j] = "False";
                    count++;
                } else result[i][j] = " ";
            }

        }
    }
    return result;
}


/**
 * @param n number of variables in logic formula
 * @return 2d list where each 1d list has T/F vals
 *         for that row in table
 */
public static ArrayList<ArrayList<Boolean>> combos(int n) {
    ArrayList<ArrayList<Boolean>> output = new ArrayList<>();
    for (int i = 1; i <= Math.pow(2, n); i++) {
        ArrayList<Boolean> tmp = new ArrayList<>();
        String combo = Integer.toBinaryString(i - 1);
        while (combo.length() < n) {
            combo = "0" + combo;
        }
        for (int j = 0; j < combo.length(); j++) {
            if (combo.charAt(j) == '0')
                tmp.add(false);
            else tmp.add(true);
        }
        output.add(tmp);
    }
    return output;
}

/**
 * @param formula logic formula like "(a&b)>c"
 * @return character array of variables in formula
 */
public char[] getVariables(String formula) {
    String vars = "";
    for (int i = 0; i < formula.length(); i++) {
        if (contains(alphabet, formula.charAt(i)))
            vars += formula.charAt(i);
    }
    char[] variables = new char[vars.length()];
    for (int i = 0; i < vars.length(); i++) {
        variables[i] = vars.charAt(i);
    }
    return variables;
}

/**
 * @param formula string to test
 * @return true if parentheses are validly placed
 */
public boolean parenMatch(String formula) {
    Stack parenStack = new Stack();
    for (int i = 0; i < formula.length(); i++) {
        char token = formula.charAt(i);
        if (token == '(') {
            parenStack.push(token);
        } else if (token == ')') {
            if (parenStack.isEmpty()) {
                return false;
            }
            parenStack.pop();
        }
    }
    if (parenStack.isEmpty()) {
        return true;
    }
    return false;
}

/**
 * Shunting-yard
 *
 * @param formula logic formula
 * @return postfix expression
 */
public String parseFormula(String formula) {
    if (!parenMatch(formula)) {
        System.out.println("this formula:  '" + formula + "' doesnt work, parentheses dont match");
        String result = "";
        return result;
    }
    ArrayList<Character> infix = new ArrayList<Character>();
    for (int i = 0; i < formula.length(); i++) {
        infix.add(formula.charAt(i));
    }
    ArrayList<Character> removeFromInfix = new ArrayList<Character>();//remove spaces from input
    for (Character c : infix) {
        if (c == ' ') removeFromInfix.add(c);
    }
    for (Character c : removeFromInfix) {
        infix.remove(c);
    }


    ArrayList<Character> operators = new ArrayList<Character>();
    ArrayList<Character> alphabet = new ArrayList<Character>();
    for (int i = 0; i < this.operators.length; i++) {
        operators.add(this.operators[i]);
    }
    for (int i = 0; i < this.alphabet.length; i++) {
        alphabet.add(this.alphabet[i]);
    }


    Stack<Character> operatorStack = new Stack<Character>();
    Queue<Character> inputTokens = new Queue<Character>();
    Queue<Character> output = new Queue<Character>();


    for (int i = 0; i < infix.size(); i++) {
        inputTokens.enqueue(infix.get(i));
    }

    while ((!inputTokens.isEmpty())) {
        Character token = inputTokens.dequeue();

        //if its a character in alphabet
        if (contains(alphabet, token)) output.enqueue(token);

            //if its an operator
        else if (contains(operators, token)) {
            if (operatorStack.empty()) {
                operatorStack.push(token);
            } else {
                Character topOperator = operatorStack.peek();
                //while (precedence of op on top of operator stack > token) enqueue op onto result
                while ((indexOf(operators, operatorStack.peek())) > (indexOf(operators, token))) {
                    output.enqueue(topOperator);
                    topOperator = operatorStack.peek();
                    operatorStack.pop();

                    if (operatorStack.isEmpty()) {
                        break;
                    }
                }
                operatorStack.push(token);
            }
        } else if (token == '(') {
            operatorStack.push(token);
        } else if (token == ')') {
            while (!(operatorStack.peek().equals('('))) {
                output.enqueue(operatorStack.peek());
                operatorStack.pop();
            }
            operatorStack.pop();
        }
    }//end while

    while (!operatorStack.isEmpty()) {
        output.enqueue(operatorStack.pop());
    }

    String result = "";
    for (char c : output) {
        result += c;
    }
    return result;
}

/**
 * @param postfix given from parseFormula
 * @param inputs  true and false values in the order the variables are listed in postfix
 * @return resulting true or false value of posfix expression
 */
public boolean evalPostfix(String postfix, ArrayList<Boolean> inputs) {
    //to make sure not to change the inputs outside of this function
    ArrayList<Boolean> inputsCopy = new ArrayList<>();
    for (int i = 0; i < inputs.size(); i++) {
        inputsCopy.add(inputs.get(i));
    }

    Stack<Boolean> output = new Stack<>();
    for (int i = 0; i < postfix.length(); i++) {
        char token = postfix.charAt(i);
        if (!contains(operators, token))//if variable
            output.push(inputsCopy.remove(0));

        else {//if operator
            boolean result = false;
            if (token == '~')
                result = !output.pop();
            else {
                boolean A = output.pop();
                boolean B = output.pop();
                if (token == '&')
                    result = A && B;
                else if (token == 'v')
                    result = A || B;
                else if (token == '>')
                    result = !B || A;
            }
            output.push(result);
        }
    }
    return output.pop();
}


public static void main(String[] args) throws Exception {
    TruthTable t = new TruthTable();

    String formula = "((pvq)&(jvk))>r";
    char[] variables = t.getVariables(formula);

    String postfix = t.parseFormula(formula);
    ArrayList<ArrayList<Boolean>> combos = combos(variables.length);
    for (ArrayList<Boolean> combo : combos) {
        combo.add(t.evalPostfix(postfix, combo));
    }
    printString(makeEven(t.makeTable(formula,variables,combos)));

}

}

我几乎没有测试它,但我认为这个想法仍然可以。