【问题标题】:Putting All Logical Expression Variables Into An Array将所有逻辑表达式变量放入数组
【发布时间】:2016-06-05 01:40:01
【问题描述】:

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

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

输入:

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

indepVar: [A, B, C]

预期输出:

array: [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;
}

【问题讨论】:

  • 你还试过什么?
  • 我已经尝试了很多更改算法,已经两天了,但我还没有得到任何结果,特别是处理 (-A) 以及如何将它与更大的表达式分开。任何帮助都会得到帮助!

标签: java arrays truthtable


【解决方案1】:

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

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

main_method (indep, expr):
    add all of indep to array
    recur (expr,array)

recur (expr,array):
    find expression in parens
    recur (thing_in_parens,array)
    add expr to array

我希望这会有所帮助!

【讨论】:

    【解决方案2】:

    我不知道这是否能完全达到您的预期输出,但如果您试图分解基于主运算符的逻辑公式,例如我有公式:

    (AvB) -> C

    主运算符是“->”。在你给出的公式中:

    ((-A)+B))+C

    应该是“+”。然后您可以遍历公式字符串并跟踪计数变量中的左右括号,注意当您到达公式中左右计数相等的点时,紧随其后的字符将成为主要运算符类似:

        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)));
    
    }
    

    }

    我几乎没有测试过,但我认为这个想法仍然不错。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-01-19
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多