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

 

 

posted @ 2016-07-16 17:52  HongYi_Liang  阅读(1612)  评论(0编辑  收藏  举报