4张纸加减乘除牌求24
昨天有个同学问我如何使用5,5,5,1这四个数加减乘除求出24,我想了很久才想出来答案。
还记得很久以前也玩过一个类似的游戏:翻出4张纸牌牌,用加减乘除求24。
对于这个问题,写了一个小程序解决:
程序如下:输入4个数和1个答案,给出运算的路径。
编程语言:C 环境:vs2012
运行结果如下:
关键流程如下:
1、求出把四张牌的24种排列顺序,
2、这24种排列中再更换中间的运算符的符号位置(4的3次方种情况)
3、以上每一种情况再对应4种括号位置:('.'表示符号)
1、(a.b).c).d 2、(a.(b.c).d 3、(a.b).(c.d) 4、a.(b.(c.d)
4、这个程序存在很多相同的情况,还有大量优化空间 比如a+b+c+d括号括哪都是一样,而且abcd位置怎么改变结果都是一样的
列出关键算法:
1、递归求出全排列:
//lst[]:输入数据数组
//length:输入数据长度
//*buf:排列存放地址
2、输入数字与符号计算结果
//:a,b,c,d:输入四个待运算的浮点数
//symbol1,symbol2,symbol3:中间3个运算符的种类
//这一段程序对应上述第1种括号情况,第2-4种情况对应函数checking2-checking4
3、获得最终路径
//a、b、c、d表示4张牌的数字,sum表示结果(算24输入24)
//*result:输出队列的地址,每8个数为1组:1、其中一张牌的数字,2、符号,3、其中一张牌得数字,4、符号,5、其中一张牌得数字,6、符号,7、剩下一张牌得数字,8、括号的位置(对应上面提到的4种情况)
//返回:1运算成功,0:排列的数量多于data_perm的长度
程序清单:
#include <stdio.h>
#include <memory.h>
#define NUM 4
#define ENDFLAG 255
#define NUMOFRESEULT 600
unsigned char result[NUMOFRESEULT]={0};
//计算结果
float checking(float a,char symbol1,float b,char symbol2,float c,char symbol3,float d)
{
const char symbolBuf[NUM]={'+','-','*','/'};
float temp1;
float temp2;
float temp3;
if(symbol1==symbolBuf[0])
temp1=a+b;
else if(symbol1==symbolBuf[1])
temp1=a-b;
else if(symbol1==symbolBuf[2])
temp1=a*b;
else if(symbol1==symbolBuf[3])
temp1=a/b;
if(symbol2==symbolBuf[0])
temp2=temp1+c;
else if(symbol2==symbolBuf[1])
temp2=temp1-c;
else if(symbol2==symbolBuf[2])
temp2=temp1*c;
else if(symbol2==symbolBuf[3])
temp2=temp1/c;
if(symbol3==symbolBuf[0])
temp3=temp2+d;
else if(symbol3==symbolBuf[1])
temp3=temp2-d;
else if(symbol3==symbolBuf[2])
temp3=temp2*d;
else if(symbol3==symbolBuf[3])
temp3=temp2/d;
return temp3;
}
//先结合中间的计算结果
float checking_2(float a,char symbol1,float b,char symbol2,float c,char symbol3,float d)
{
const char symbolBuf[NUM]={'+','-','*','/'};
float temp1;
float temp2;
float temp3;
if(symbol2==symbolBuf[0])
temp1=b+c;
else if(symbol2==symbolBuf[1])
temp1=b-c;
else if(symbol2==symbolBuf[2])
temp1=b*c;
else if(symbol2==symbolBuf[3])
temp1=b/c;
if(symbol1==symbolBuf[0])
temp2=a+temp1;
else if(symbol1==symbolBuf[1])
temp2=a-temp1;
else if(symbol1==symbolBuf[2])
temp2=a*temp1;
else if(symbol1==symbolBuf[3])
temp2=a/temp1;
if(symbol3==symbolBuf[0])
temp3=temp2+d;
else if(symbol3==symbolBuf[1])
temp3=temp2-d;
else if(symbol3==symbolBuf[2])
temp3=temp2*d;
else if(symbol3==symbolBuf[3])
temp3=temp2/d;
return temp3;
}
//先结合后边的计算结果
float checking_3(float a,char symbol1,float b,char symbol2,float c,char symbol3,float d)
{
const char symbolBuf[NUM]={'+','-','*','/'};
float temp1;
float temp2;
float temp3;
if(symbol1==symbolBuf[0])
temp1=a+b;
else if(symbol1==symbolBuf[1])
temp1=a-b;
else if(symbol1==symbolBuf[2])
temp1=a*b;
else if(symbol1==symbolBuf[3])
temp1=a/b;
if(symbol3==symbolBuf[0])
temp2=c+d;
else if(symbol3==symbolBuf[1])
temp2=c-d;
else if(symbol3==symbolBuf[2])
temp2=c*d;
else if(symbol3==symbolBuf[3])
temp2=c/d;
if(symbol2==symbolBuf[0])
temp3=temp1+temp2;
else if(symbol2==symbolBuf[1])
temp3=temp1-temp2;
else if(symbol2==symbolBuf[2])
temp3=temp1*temp2;
else if(symbol2==symbolBuf[3])
temp3=temp1/temp2;
return temp3;
}
//结合后三个的计算结果
float checking_4(float a,char symbol1,float b,char symbol2,float c,char symbol3,float d)
{
const char symbolBuf[NUM]={'+','-','*','/'};
float temp1;
float temp2;
float temp3;
if(symbol3==symbolBuf[0])
temp1=c+d;
else if(symbol3==symbolBuf[1])
temp1=c-d;
else if(symbol3==symbolBuf[2])
temp1=c*d;
else if(symbol3==symbolBuf[3])
temp1=c/d;
if(symbol2==symbolBuf[0])
temp2=b+temp1;
else if(symbol2==symbolBuf[1])
temp2=b-temp1;
else if(symbol2==symbolBuf[2])
temp2=b*temp1;
else if(symbol2==symbolBuf[3])
temp2=b/temp1;
if(symbol1==symbolBuf[0])
temp3=a+temp2;
else if(symbol1==symbolBuf[1])
temp3=a-temp2;
else if(symbol1==symbolBuf[2])
temp3=a*temp2;
else if(symbol1==symbolBuf[3])
temp3=a/temp2;
return temp3;
}
//交换*a和*b
void swap(float *a,float *b)
{
float c;
c=*a;
*a=*b;
*b=c;
}
//求排列
void perm(float list[], int k, int m,float *buf,int *cnt)
{
int i;
if(k > m)
{
for(i = 0; i <= m; i++)
{
// printf("%d ", list[i]);
*(buf+(*cnt))=list[i];
(*cnt)++;
}
}
else
{
for(i = k; i <= m; i++)
{
swap(&list[k], &list[i]);
perm(list, k + 1, m,buf,cnt);
swap(&list[k], &list[i]);
}
}
}
//求全排
void Permutation(float list[], int length,float *buf)
{
int cnt=0;
perm(list,0,length-1,buf,&cnt);
}
//计算获得答案的算法
int cal_arithmetic(unsigned char *result,int a,int b,int c,int d,int sum)
{
float dataIn[4];
float data_perm[4*4*3*2*1];
int symbol[NUM]={'+','-','*','/'};
int i;
int j;
int k;
int cnt;
int cnt_result=0;
//求排列
dataIn[0]=a;
dataIn[1]=b;
dataIn[2]=c;
dataIn[3]=d;
Permutation(dataIn,4,data_perm);
for(i=0;i<NUM;i++)
{
for(j=0;j<NUM;j++)
{
for(k=0;k<NUM;k++)
{
for(cnt=0;cnt<24;cnt++)
{
if(checking(data_perm[4*cnt],symbol[i],data_perm[4*cnt+1],symbol[j],data_perm[4*cnt+2],symbol[k],data_perm[4*cnt+3])==(float)sum)
{
*(result+cnt_result)=(unsigned char)data_perm[4*cnt];
cnt_result++;
*(result+cnt_result)=symbol[i];
cnt_result++;
*(result+cnt_result)=(unsigned char)data_perm[4*cnt+1];
cnt_result++;
*(result+cnt_result)=symbol[j];
cnt_result++;
*(result+cnt_result)=(unsigned char)data_perm[4*cnt+2];
cnt_result++;
*(result+cnt_result)=symbol[k];
cnt_result++;
*(result+cnt_result)=(unsigned char)data_perm[4*cnt+3];
cnt_result++;
*(result+cnt_result)=0;
cnt_result++;
}
if(checking_2(data_perm[4*cnt],symbol[i],data_perm[4*cnt+1],symbol[j],data_perm[4*cnt+2],symbol[k],data_perm[4*cnt+3])==(float)sum)
{
*(result+cnt_result)=(unsigned char)data_perm[4*cnt];
cnt_result++;
*(result+cnt_result)=symbol[i];
cnt_result++;
*(result+cnt_result)=(unsigned char)data_perm[4*cnt+1];
cnt_result++;
*(result+cnt_result)=symbol[j];
cnt_result++;
*(result+cnt_result)=(unsigned char)data_perm[4*cnt+2];
cnt_result++;
*(result+cnt_result)=symbol[k];
cnt_result++;
*(result+cnt_result)=(unsigned char)data_perm[4*cnt+3];
cnt_result++;
*(result+cnt_result)=1;
cnt_result++;
}
if(checking_3(data_perm[4*cnt],symbol[i],data_perm[4*cnt+1],symbol[j],data_perm[4*cnt+2],symbol[k],data_perm[4*cnt+3])==(float)sum)
{
*(result+cnt_result)=(unsigned char)data_perm[4*cnt];
cnt_result++;
*(result+cnt_result)=symbol[i];
cnt_result++;
*(result+cnt_result)=(unsigned char)data_perm[4*cnt+1];
cnt_result++;
*(result+cnt_result)=symbol[j];
cnt_result++;
*(result+cnt_result)=(unsigned char)data_perm[4*cnt+2];
cnt_result++;
*(result+cnt_result)=symbol[k];
cnt_result++;
*(result+cnt_result)=(unsigned char)data_perm[4*cnt+3];
cnt_result++;
*(result+cnt_result)=2;
cnt_result++;
}
if(checking_4(data_perm[4*cnt],symbol[i],data_perm[4*cnt+1],symbol[j],data_perm[4*cnt+2],symbol[k],data_perm[4*cnt+3])==(float)sum)
{
*(result+cnt_result)=(unsigned char)data_perm[4*cnt];
cnt_result++;
*(result+cnt_result)=symbol[i];
cnt_result++;
*(result+cnt_result)=(unsigned char)data_perm[4*cnt+1];
cnt_result++;
*(result+cnt_result)=symbol[j];
cnt_result++;
*(result+cnt_result)=(unsigned char)data_perm[4*cnt+2];
cnt_result++;
*(result+cnt_result)=symbol[k];
cnt_result++;
*(result+cnt_result)=(unsigned char)data_perm[4*cnt+3];
cnt_result++;
*(result+cnt_result)=3;
cnt_result++;
}
}
}
}
}
*(result+cnt_result)=ENDFLAG;
return 0;
}
//获取数
void getdata(int *a,int *b,int *c,int *d,int *e)
{
printf("请输入A:");
scanf("%d",a);
printf("\r\n请输入B:");
scanf("%d",b);
printf("\r\n请输入C:");
scanf("%d",c);
printf("\r\n请输入D:");
scanf("%d",d);
printf("\r\n请输入要计算的答案:");
scanf("%d",e);
}
//输出数据
void printfdata(void)
{
int i=0;
printf("\r\n结果:");
while(result[i*8]!=ENDFLAG)
{
if(result[i*8+7]==0)
printf("(%d %c %d) %c %d) %c %d\r\n",result[i*8],result[i*8+1],result[i*8+2],result[i*8+3],result[i*8+4],result[i*8+5],result[i*8+6]);
else if(result[i*8+7]==1)
printf("(%d %c (%d %c %d)) %c %d\r\n",result[i*8],result[i*8+1],result[i*8+2],result[i*8+3],result[i*8+4],result[i*8+5],result[i*8+6]);
else if(result[i*8+7]==2)
printf("(%d %c %d) %c (%d %c %d)\r\n",result[i*8],result[i*8+1],result[i*8+2],result[i*8+3],result[i*8+4],result[i*8+5],result[i*8+6]);
else if(result[i*8+7]==3)
printf("%d %c (%d %c %d %c %d)\r\n",result[i*8],result[i*8+1],result[i*8+2],result[i*8+3],result[i*8+4],result[i*8+5],result[i*8+6]);
i++;
}
}
int main()
{
int input1,input2,input3,input4,input5;//获取4个输入和1个结果
while(1)
{
//清零输出数组和指针
memset((void*)result,0,NUMOFRESEULT*sizeof(result[0]));
//获取数据和答案
getdata(&input1,&input2,&input3,&input4,&input5);
//寻找算法
cal_arithmetic(result,input1,input2,input3,input4,input5);
//打印算法
printfdata();
}
}