离散数学——自动生成真值表、主合取范式
生活随笔
收集整理的這篇文章主要介紹了
离散数学——自动生成真值表、主合取范式
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
主要完成真值表的自動生成:
1. 自動生成真值表
2. 生成主合取范式
給出兩個版本,先給一個簡單的,怕大家看完都不想往下看了,簡單版本的,只需要100多行代碼!!!!(好像也不少),但是比第二個版本增加了生成主合取范式的功能,主要是利用了庫函數,所以比較簡單:
#include<iostream> #include<cstring> #include<algorithm> #include<cmath> using namespace std;int main() {string a,b;cin>>a;int n=a.length();b=a;int num=0;for(int i=0;i<n;i++){int q=1;for(int j=0;j<i;j++){if(a[i]==a[j]){q=0;break;} } if(a[i]>='a'&&a[i]<='z'&&q==1)num++; }char zimu[num];int o=pow(2,num);int fs[o][num+1]; int zhenzhi[num]={0};int k=0;for(int i=0;i<n;i++){int q=1;for(int j=0;j<i;j++){if(a[i]==a[j]){q=0;break;} } if(a[i]>='a'&&a[i]<='z'&&q==1){zimu[k]=a[i];k++;} }sort(zimu,zimu+num);for(int i=0;i<n+(2*num)+3;i++)cout<<"-" ;cout<<endl;for(int i=0;i<num;i++)cout<<zimu[i]<<" ";cout<<"| ";cout<<b<<endl;for(int i=0;i<n+(2*num)+3;i++)cout<<"-" ;cout<<endl;int cishu=0;while(cishu<pow(2,num)){ int m=n;string c=a; for(int i=0;i<num;i++){cout<<zhenzhi[i]<<" ";fs[cishu][i]=zhenzhi[i];}cout<<"| ";for(int i=0;i<n;i++){for(int j=0;j<num;j++){if(c[i]==zimu[j])c[i]=zhenzhi[j]+'0';}}while(m!=1){ if(c.find("!1")!=string::npos)c=c.replace(c.find("!1"),2,"0");if(c.find("!0")!=string::npos)c=c.replace(c.find("!0"),2,"1");if(c.find("1+1")!=string::npos)c=c.replace(c.find("1+1"),3 , "1");if(c.find("1+0")!=string::npos)c=c.replace(c.find("1+0"),3 , "1");if(c.find("0+1")!=string::npos)c=c.replace(c.find("0+1"),3 , "1");if(c.find("0+0")!=string::npos)c=c.replace(c.find("0+0"),3 , "0");if(c.find("1*1")!=string::npos)c=c.replace(c.find("1*1"),3 , "1");if(c.find("1*0")!=string::npos)c=c.replace(c.find("1*0"),3 , "0");if(c.find("0*1")!=string::npos)c=c.replace(c.find("0*1"),3 , "0");if(c.find("0*0")!=string::npos)c=c.replace(c.find("0*0"),3 , "0");if(c.find("1-1")!=string::npos)c=c.replace(c.find("1-1"),3 , "1");if(c.find("1-0")!=string::npos)c=c.replace(c.find("1-0"),3 , "0");if(c.find("0-1")!=string::npos)c=c.replace(c.find("0-1"),3 , "1");if(c.find("0-0")!=string::npos)c=c.replace(c.find("0-0"),3 , "1");if(c.find("1=1")!=string::npos)c=c.replace(c.find("1=1"),3 , "1");if(c.find("1=0")!=string::npos)c=c.replace(c.find("1=0"),3 , "0");if(c.find("0=1")!=string::npos)c=c.replace(c.find("0=1"),3 , "0");if(c.find("0=0")!=string::npos)c=c.replace(c.find("0=0"),3 , "1");if(c.find("(1)")!=string::npos)c=c.replace(c.find("(1)"),3 , "1");if(c.find("(0)")!=string::npos)c=c.replace(c.find("(0)"),3 , "0");m=c.length();}for(int i=0;i<(n/2);i++)cout<<" ";cout<<c<<endl;if(c=="1")fs[cishu][num]=1;else fs[cishu][num]=0;zhenzhi[num-1]=zhenzhi[num-1]+1;for(int i=num-1;i>=0;i--){if(zhenzhi[i]==2){zhenzhi[i]=0;zhenzhi[i-1]=zhenzhi[i-1]+1;}}cishu++;}for(int i=0;i<n+(2*num)+3;i++)cout<<"-" ;cout<<endl;int m=0;int M=0;for (int i=0;i<o;i++){if(fs[i][num]==1)m++;else M++;}cout<<"主析取范式:";if (m==0)cout<<"不存在"<<endl; else {for (int i=0;i<o;i++){ if(fs[i][num]==1){ cout<<"(";for(int j=0;j<num;j++){if(fs[i][j]==1)cout<<zimu[j];else cout<<"!"<<zimu[j];if(j!=num-1)cout<<"*";}m--;if(m!=0)cout<<")+";else cout<<")";}}}cout<<endl;cout<<"主合取范式:";if (M==0)cout<<"不存在"<<endl; else {for (int i=0;i<o;i++){ if(fs[i][num]==0){ cout<<"(";for(int j=0;j<num;j++){if(fs[i][j]==0)cout<<zimu[j];else cout<<"!"<<zimu[j];if(j!=num-1)cout<<"+";}M--;if(M!=0)cout<<")*";else cout<<")";}}}}第二個版本(代碼結構比較清楚):
//truetable.c #include<iostream> #include<string.h> #include<stdio.h> int getalpha(char a[],char b[]) {char tmpc=' ';int n=strlen(a),i=0,j=0,k=0;for(i=0; i<n; i++) { //是字母 if(((a[i]>='a')&&(a[i]<='z')) ||((a[i]>='A')&&(a[i]<='Z'))){for(k=0; k<j; k++) {if(b[k]==a[i]) {break;}}if(k>=j) {b[j]=a[i];j++;}}}//從低到高排序 for(i=0; i<j-1; i++) {for(k=0; k<j-i-1; k++) {if(b[k]>b[k+1]) {tmpc=b[k];b[k]=b[k+1];b[k+1]=tmpc;}}}b[j]='\0';//加上結束標志 return j;//小寫字母個數 }void fillValue(char a[],char varchar[],int nvar,char valchar[],char resultchar[]) {//a是原始公式 , varchar是變元列表如pqrs //valchar是變元的某次取值 int nLen=strlen(a),i=0,j=0,k=0;for(i=0; i<nLen; i++) {resultchar[i]=a[i];}resultchar[i]='\0';for(i=0; i<nLen; i++) {//原公式中的每個字符 for(j=0; j<nvar; j++) {//公式中的字符是第幾個變元 if(resultchar[i]==varchar[j]) {//是第j變元 ,其值換成第j個值 resultchar[i]=valchar[j];break;}}} }void negatecal(char a[]) {int _result=0,i=0,j=0;while(i<strlen(a)) {// !1 換成1 j=i;_result=0;if((j+1<strlen(a))&&(a[j]=='!')&&(a[j+1]=='1')) {a[j]='0';_result=1;}else if((j+1<strlen(a))&&(a[j]=='!')&&(a[j+1]=='0')) {a[j]='1';_result=1;}if(_result==1) { //如果有運算后面的往前移 j++;while(a[j+1]!='\0') { //后面的字符往前移一格 a[j]=a[j+1];j++;}a[j]='\0';} else { //沒有!0 或!1 則看下一個指針 i++;}} }void kuanhao(char a[]) {int _result=0,i=0,j=0;while(i<strlen(a)){//!1 ->1 j=i;_result=0;if((j+2<strlen(a))&&(a[j]=='(')&&(a[j+1]=='1')&&(a[j+2]==')')){a[j]='1';_result=1;}else if((j+2<strlen(a))&&(a[j]=='(')&&(a[j+1]=='0')&&(a[j+2]==')')){a[j]='0';_result=1;}if(_result==1) {j++;while(a[j+2]!='\0'){//后面的字符往前移一格 a[j]=a[j+2]; j++;}a[j]='\0';}else {//沒有!0 或!1 則看下一個指針 i++;}} } void conYsh(char a[]) {int _result=0,i=0,j=0;while(i<strlen(a)) {//!1 ->1 j=i;_result=0;if((j+2<strlen(a))&&(a[j]=='0')&&(a[j+1]=='*')&&(a[j+2]=='0')){ a[j]='0';_result=1;}else if((j+2<strlen(a))&&(a[j]=='0')&&(a[j+1]=='*')&&(a[j+2]=='1')){a[j]='0';_result=1;}else if((j+2<strlen(a))&&(a[j]=='1')&&(a[j+1]=='*')&&(a[j+2]=='0')){a[j]='0';_result=1;}else if((j+2<strlen(a))&&(a[j]=='1')&&(a[j+1]=='*')&&(a[j+2]=='1')){a[j]='1';_result=1;}if(_result==1) {j++;//后面的字符往前移兩格 while(a[j+2]!='\0'){a[j]=a[j+2];j++;}a[j]='\0';}else { //沒有!0 或!1 則看下一個指針 i++;}} } void biCondYsh(char a[]) {int _result=0,i=0,j=0;while(i<strlen(a)){j=i;_result=0;if((j+2<strlen(a))&&(a[j]=='0')&&(a[j+1]=='=')&&(a[j+2]=='0')){a[j]='1';_result=1;}else if((j+2<strlen(a))&&(a[j]=='0')&&(a[j+1]=='=')&&(a[j+2]=='1')){a[j]='0';_result=1;}else if((j+2<strlen(a))&&(a[j]=='0')&&(a[j+1]=='=')&&(a[j+2]=='0')){a[j]='0';_result=1;}else if((j+2<strlen(a))&&(a[j]=='1')&&(a[j+1]=='=')&&(a[j+2]=='1')){a[j]='1';_result=1;}if(_result==1){j++;while(a[j+2]!='\0'){a[j]=a[j+2];j++;}a[j]='\0';}else{i++;}} }void condYsh(char a[] ) {int _result=0,i=0,j=0;while(i<strlen(a)){j=i;_result=0;if((j+2<strlen(a))&&(a[j]=='0')&&(a[j+1]=='-')&&(a[j+2]=='0')){a[j]='1';_result=1;}else if((j+2<strlen(a))&&a[j]=='0'&&(a[j+1]=='-')&&(a[j+2]=='1')){a[j]='1';_result=1;}else if((j+2<strlen(a))&&a[j]=='1'&&(a[j+1]=='-')&&(a[j+2]=='0')){a[j]='0';_result=1;}else if((j+2<strlen(a))&&a[j]=='1'&&(a[j+1]=='-')&&(a[j+2]=='1')){a[j]='1';_result=1;}if(_result==1){j++;while(a[j+2]!='\0'){a[j]=a[j+2];j++;}a[j]='\0';}else{i++;}} } void disConjYsh(char a[]) {int _result=0,i=0,j=0;while(i<strlen(a)){j=i;_result=0;if((j+2<strlen(a))&&(a[j]=='0')&&(a[j+1]=='+')&&(a[j+2]=='0')){a[j]='0';_result=1;}else if((j+2<strlen(a))&&a[j]=='0'&&(a[j+1]=='+')&&(a[j+2]=='1')){a[j]='1';_result=1;}else if((j+2<strlen(a))&&a[j]=='1'&&(a[j+1]=='+')&&(a[j+2]=='0')){a[j]='1';_result=1;}else if((j+2<strlen(a))&&a[j]=='1'&&(a[j+1]=='+')&&(a[j+2]=='1')){a[j]='1';_result=1;}if(_result==1)//如果修改成功則后面的往前移 {j++;while(a[j+2]!='\0'){a[j]=a[j+2];j++;}a[j]='\0';}else{i++;}} } int main(int argc,char* argv[]) {char pstate[120],pstate0[120],charList[120],charVal[120];char minItem[1024][52],truetable[1024];//最多10個變量 int i=0,nold=0,nnew=0,nvar=1,nRow=1,j=0,flagsum=1,iMinItem=0;printf("請輸入公式(析+,合*,條—,雙=,否定!,01):\n");gets(pstate0);fflush(stdin);nold=strlen(pstate0)+1;nnew=strlen(pstate0);for(i=0;i<nnew;i++){pstate[i]=pstate0[i];}pstate[i]='\0';nvar=getalpha(pstate,charList);//真值表各個變元的值 nRow=1;for(i=0;i<nvar;i++){charVal[i]='0';nRow=nRow*2;}charVal[i]='\0';//真值表的首行 printf("\n");for(i=0;i<nvar;i++){printf("%4c",charList[i]);}printf("%15c%s\n",' ',pstate);for(i=0;i<nvar;i++){printf("%4c",'-');}printf("|");for(i=0;i<60;i++){printf("%c",'-');}printf("\n");for(i=0;i<nRow;i++){//真值表的各行 for(j=0;j<nvar;j++){printf("%4c",charVal[j]);}//將值填入到公式中 pstate[0]='\0';fillValue(pstate0,charList,nvar,charVal,pstate);//計算公式的值 nold=strlen(pstate0)+1;nnew=strlen(pstate);while (nnew<nold){nold=strlen(pstate);negatecal(pstate);//否定 kuanhao(pstate);//(A)conYsh(pstate);biCondYsh(pstate);condYsh(pstate);disConjYsh(pstate);nnew=strlen(pstate);}if(strlen(pstate)==1){if(pstate[0]=='1'){for(j=0;j<nvar;j++){minItem[iMinItem][j]=charVal[j];}minItem[iMinItem][j]='\0';iMinItem++;}truetable[i]=pstate[0];}printf("%20c%s",' ',pstate);printf("\n");//值加1flagsum=1;for(j=nvar-1;j>=0;j--){if(charVal[j]=='1'){if(flagsum==1){//1+1=10//進位 charVal[j]='0';flagsum=1; }else //1+0=1 不變 {break; }}else if(charVal[j]=='0'){if(flagsum==1)//0+1=1//沒有進位 {charVal[j]='1';flagsum=0;} else //0+0結束 {break; }}} }for(i=0;i<iMinItem;i++){if(i==0){printf("m%s",minItem[i]);}else {printf("+m%s",minItem[i]);}}printf("\n");for(i=0;i<iMinItem;i++){if(i==0){printf("(");for(j=0;j<nvar;j++){if(j==0){if(minItem[i][j]=='1'){printf("%c",charList[j]);}else {printf("!%c",charList[j]);}}else{if(minItem[i][j]=='1'){printf("*%c",charList[j]);}else {printf("*!%c",charList[j]);}}}printf(")");}else {printf("+(");for(j=0;j<nvar;j++){if(j==0){if(minItem[i][j]=='1'){printf("%c",charList[j]);}else {printf("!%c",charList[j]);}}else{if(minItem[i][j]=='1'){printf("*%c",charList[j]);}else{printf("*!%c",charList[j]);}}}printf(")");}}}第一個程序主要是用了庫函數find()和replace()所以比較簡單,第二個就寫的很模塊化,可能更容易理解,大家自己看看叭~
Ps:find()和replace()函數用來處理字符串很舒服!!!!!!(C++)
總結
以上是生活随笔為你收集整理的离散数学——自动生成真值表、主合取范式的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: C# 页面关联类似模式窗口
- 下一篇: 非常经典的C字符串函数的实现