我想要什么
我需要一种方法来获取逻辑公式中主运算符的索引。
所以这就是我想要的例子:
输入:〜(BVC)V(AVE),其中"〜"是否定," V"是脱节。
输出:[〜(BVC),V,(AVE)]
一般来说,给出一个命题逻辑的公式,形式为" A OP B"作为String返回列表[A,OP,B]
我的想法
使用Shunting-yard algo (Wiki page)将输入转换为postfix,然后在原始输入中从输出中获取最后一个字符。所以在上面的例子中你有" V"作为索引6的主要运算符,因此输出将是
{formula.substring(0,6),formula.charAt(6),formula.substring(7,11)}`
或更一般地
{
formula.substring(0,opIndex),
lastElement,
formula.substring(opIndex+1,formula.length())
}
我的剧本
import java.util.ArrayList;
import java.util.Stack;
public class Parser {
/**
* print String array
*/
public static void printString(String[] s){
System.out.print("{");
for(int i=0;i<s.length;i++){
System.out.print(s[i]);
if(!(i==s.length-1)){
System.out.print(",");
}
}
System.out.println("}");
}
/**
*
* @return the index of c in list
*/
public 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;
}
/**
*
* @return true if c is in list
*/
public boolean contains(ArrayList<Character> list, Character c){
for(Character i:list){
if(i==c) return true;
}
return false;
}
/**
* @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 = A OP B
* @return [A,OP,B]
*/
public String[] parseFormula(String formula){
if(!parenMatch(formula)){
System.out.println("this formula: '"+formula+ "' doesnt work");
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);
}
char[] operators1={'<','>','V','&','~'};//highest order of precedence going from the right of array
char[] alphabet1= {//V is not in list bc its an op
'a', 'b', 'c', 'd', 'e', 'f', 'g',
'h', 'i', 'j', 'k', 'l', 'm', 'n',
'o', 'p', 'q', 'r', 's', 't', 'u',
'v', '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'
};
ArrayList<Character> operators=new ArrayList<>();
ArrayList<Character> alphabet=new ArrayList<>();
for(int i=0; i<operators1.length;i++){
operators.add(operators1[i]);
}
for(int i=0; i<alphabet1.length;i++){
alphabet.add(alphabet1[i]);
}
Stack<Character> operatorStack = new Stack<>();
Queue<Character> inputTokens = new Queue<>();
Queue<Character> output = new Queue<>();
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);
}
}
//if its a "("
else if (token == '(') {
operatorStack.push(token);
}
else if (token == ')') {
while (!(operatorStack.peek().equals('('))) {
output.enqueue((Character) operatorStack.peek());
operatorStack.pop();
}
operatorStack.pop();
}
}//end while
while(!operatorStack.isEmpty()){
output.enqueue(operatorStack.pop());
}
//get last element
char lastElement=' ';
for(char c: output){
System.out.print(c);
lastElement=c;
}
System.out.println();
int opIndex=infix.indexOf(lastElement);
String A=formula.substring(0,opIndex);
String op=""+lastElement;
String B=formula.substring(opIndex+1,formula.length());
String[] result ={A,op,B};
return result;
}
public static void main(String[] args) {
//~(BVC)V(AVE)
Parser p =new Parser();
printString(p.parseFormula("~(BVC)V(AVE)"));
}
}
问题
这是输出:{〜(B,V,C)V(AVE)}。
所以这个方法的问题是,当你从左到右进行多次相同的操作搜索时,不会给你所需的索引。