1. 程式人生 > >離散數學輸入表示式列印真值表和主析/合取正規化

離散數學輸入表示式列印真值表和主析/合取正規化

這是我們學校離散數學的作業題目,我用JAVA寫的,不廢話,上程式碼:

package lisanExperiment;

import java.io.BufferedReader;
import java.io.InputStreamReader;
public class li {
	//使用者輸入的表示式(以字串形式輸入)
		StringBuilder inputStr;
		//用於作為inputStr的副本,當每次計算完成後重置inputStr
		String inputStr2;
		//flag代表表示式的結果
		int flag=0;
		//用於統計最初輸入的表示式有幾個括號
		int count=0;
		//用於控制遞迴次數
		int COUNT;
		//下面的陣列用於儲存真值表
		int [][]table=new int[8][4];
		//用於表示是否含有括號
		boolean ifHas=false;
		//用於存放P,Q,R
		String[]pqr=new String[]{"P","Q","R"};
		//用於讓使用者輸入字串的函式
		public void input(StringBuilder string)
		{
			inputStr=string;
			inputStr2=string.toString();
		}
		//每輪迴圈之後重置
		public void restart()
		{
			inputStr=new StringBuilder(inputStr2);
		}
		//用於處理"!"運算子
		public int changeI(int x)
		{
			if(x==0)
				return 1;
			
				return 0;
		}
		public String changeS(int x)
		{
			if(x==0)
				return "1";
			
				return "0";
		}
		//用於處理析取運算子
		public int extract(int x,int y)
		{
			return (x|y);
		}
		//用於處理合取運算子
		public int conjunct(int x,int y)
		{
			return (x&y);
		}
		//運算不同情況下的表示式值,x是P的值,y的Q的值,z是R的值
		public void Calculate(int x,int y,int z)
		{
		//	System.out.println("FIRST\t"+inputStr);
			if(count==0&&ifHas==false)
			{
			for(int i=0;i<inputStr.length();i++)
			{
				if(inputStr.charAt(i)==')')
				{
					count++;
					ifHas=true;
				}
				COUNT=count;
			}
			}
			//System.out.println("COUNT"+COUNT);
			if(COUNT!=0)
			{
				COUNT--;
			for(int i=0;i<inputStr.length();i++)
			{
				
				if(inputStr.charAt(i)==')')
				{	
					for(int j=i;;j--)
					{
						
						if(inputStr.charAt(j)=='(')
						{
							int result;
							String[]strs=new String[3];
							strs[0]=inputStr.substring(0,j);
							strs[1]=inputStr.substring(j+1,i);
							strs[2]=inputStr.substring(i+1);
		
							StringBuilder s=new StringBuilder(strs[1]);
							result=computeSim(s,x,y,z);
							String string=strs[0]+result+strs[2];
							inputStr= new StringBuilder(string);
							//System.out.println("LAST\t"+inputStr);
							break;
						}
					}
					break;
				}
			}
			
			if(COUNT!=0)
			{
			Calculate(x,y,z);
			}
			if(COUNT==0)
			{	
				//System.out.println("我被呼叫了");
				flag=computeSim(inputStr,x,y,z);
			}
		}
		}
		//用於計算最內側括號裡的值
		public int computeSim(StringBuilder sb,int x,int y,int z)
		{
			//這是已經計算的部分的真值
			int been=0;
			for(int i=0;i<sb.length();i++)
			{
				if(sb.charAt(i)=='!')
				{
					if(sb.charAt(i+1)=='P')
					sb.replace(i, i+2, changeS(x));				
					else if(sb.charAt(i+1)=='Q')
					sb.replace(i, i+2, changeS(y));		
					else if(sb.charAt(i+1)=='R')
						sb.replace(i, i+2, changeS(z));		
					else if(sb.charAt(i+1)=='1')
						sb.replace(i, i+2, "0");
					else if(sb.charAt(i+1)=='0')
						sb.replace(i, i+2, "1");
					//System.out.println("刪除了一個非");
				}
			}
			for(int i=0;i<sb.length();i++)
			{	
				//以下程式碼用於初始化been
				if(i==0)
				{
						if(sb.charAt(i)=='P')
							been=x;
						else if(sb.charAt(i)=='Q')
							been=y;
						else if(sb.charAt(i)=='R')
							been=z;
						else if(sb.charAt(i)=='1')
							been=1;
						else if(sb.charAt(i)=='0')
							been=0;
					}
				switch(sb.charAt(i))
				{
				case'!':
					break;
				case '|':
					if(sb.charAt(i+1)=='P')
						been=extract(been,x);
					 if(sb.charAt(i+1)=='Q')
						been=extract(been,y);
					 if(sb.charAt(i+1)=='R')
						been=extract(been,z);
					 if(sb.charAt(i+1)=='1')
							been=extract(been,1);
					 if(sb.charAt(i+1)=='0')
							been=extract(been,0);
					break;
				case '&':
					if(sb.charAt(i+1)=='P')
						been=conjunct(been,x);
					 if(sb.charAt(i+1)=='Q')
						been=conjunct(been,y);
					 if(sb.charAt(i+1)=='R')
						been=conjunct(been,z);
					 if(sb.charAt(i+1)=='0')
							been=conjunct(been,0);
					 if(sb.charAt(i+1)=='1')
							been=conjunct(been,1);
							break;
				default:
					break;
				}
			}
			return been;
		}

		public void init()
		{
			int n=0;
			for(int i=1;i>=0;i--)
			{
				for(int j=1;j>=0;j--)
				{
					for(int k=1;k>=0;k--)
					{
						Calculate(i,j,k);
						table[n][0]=i;
						table[n][1]=j;
						table[n][2]=k;
						table[n][3]=flag;
						n++;
						restart();
						COUNT=count;
					//	System.out.println(inputStr);
					}
				}
			}
		}
		//用於把1和0轉換為T和F
		public String replace(int x)
		{
			if(x==1)
			return "T";
			return "F";
		}
		public void print()
		{
			System.out.println("P\tQ\tR\t"+inputStr);
			for(int i=0;i<8;i++)
			{
				for(int j=0;j<4;j++)
					System.out.print(replace(table[i][j])+"\t");
				System.out.println();
			}
		}
		public void mainX()
		{
			int x=0;
			for(int i=0;i<8;i++)
				if(table[i][3]==1)
					x=i;
			System.out.println("該式的主析取正規化");
			for(int i=0;i<8;i++)
			{
				if(table[i][3]==1)
				{
					System.out.print("(");
					for(int j=0;j<3;j++)
					{
						
						if(table[i][j]==0)
						System.out.print("!"+pqr[j]);
						else
						System.out.print(pqr[j]);
						if(j!=2)
							System.out.print("&");
						else
							System.out.print(")");
					}
					if(i!=x)
					System.out.print("|");
				}
			}
			System.out.println();
	}
			
		
		public void mainH()
		{
			int x=0;
			for(int i=0;i<8;i++)
				if(table[i][3]==0)
					x=i;
			System.out.println("該式的主合取正規化");
			for(int i=0;i<8;i++)
			{
				if(table[i][3]==0)
				{
					System.out.print("(");
					for(int j=0;j<3;j++)
					{
						
						if(table[i][j]==1)
						System.out.print("!"+pqr[j]);
						else
						System.out.print(pqr[j]);
						if(j!=2)
							System.out.print("|");
						else
							System.out.print(")");
					}
					if(i!=x)
					System.out.print("&");
				}
			}
			System.out.println();
		}
		public static void main(String []args)throws Exception
		{
			li l=new li();
			BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
			System.out.println("請輸入表示式,三個命題分別為P,Q,R,非號用!代替,析取號用|代替,合取號用&代替");
			System.out.println("輸入不當可能導致未知錯誤,請注意輸入格式");
			String s=null;
				s=br.readLine();
			StringBuilder sb=new StringBuilder(s);
			l.input(sb);
			l.init();
			l.print();
			l.mainX();
			l.mainH();
		}
}


事後感覺自己寫的蠢了,另外要完成不確定個數的變元輸入並不困難,甚至比確定的三個還要簡單。
水平有限,敬請指教。