/******************************************************************************
计算 A 、B、 C、 D四个数据+-*/以及括号运算得到24,
可穷举获得各种可行的答案,数据类型使用float。
关键在于对 4 数据运算分类,结合数组、函数指针等巧妙使用循环完成穷举:
Kind 1: ((A op1 B) op3 (C op2 D))
Kind 2: (( (A op1 B) op2 C) op3 D)
Copyright (C) 2007 jixingzhong. The Institue of Computer System
*******************************************************************************/
#include <stdio.h>
#include <stdlib.h>
typedef float (*PF)(float, float);
char *ch[]={NULL,"A","2","3","4","5","6","7","8","9","10","J","Q","K"};
char cc[]="+-*/";
//int rand_seed = 0;
void rand_num(int *num)
{
int i;
// srand(num[(rand_seed++)%4]);
for(i=0; i<4; i++)
num[i] = rand()%12 +1;
}
/* +-*/ 的计算函数*/
float add(float x, float y)
{
return x+y;
}
float sub(float x, float y)
{
return x-y;
}
float mul(float x, float y)
{
return x*y;
}
float divide(float x, float y)
{
if((y>-0.0000001)&&(y<0.0000001))
return 0;
else return x/y;
}
/*compute!*/
void compute_24(int num[])
{
PF pf[4]={add,sub,mul,divide};
int i,j,k,x,y,z,t;
int flag=0,flag_i=0, flag_j=0, flag_equ_end2=0;
float op_x, op_y, op_z;
/* Kind 1: ((A op1 B) op3 (C op2 D)) */
for(i=0; i<4; i++) /*num[i] is the first para*/
{
for(t=0; t<i; t++)
if(num[t] == num[i])
flag_i = 1;
if(flag_i)
{
flag_i=0;
continue;
}
for(j=0; j<4; j++) /*num[j] is the 2nd para*/
{
if(j == i)
continue;
for(t=j-1; t>0; t--)
if((num[j] == num[t])&&(num[i]!=num[t]))
flag_j = 1;
if(flag_j)
{
flag_j=0;
continue;
}
for(x=0; x<4; x++) /*pf[x] is the 1st operation*/
{
if((j<i)&&
((x==0)||(x==2))
)
continue;
op_x = pf[x]((float)num[i],(float)num[j]);
for(k=0; k<4; k++) /*num[k] is the 3rd para, and the last is num[6-i-j-k]*/
{
if(k==i || k==j)
continue;
if(num[k] == num[6-i-j-k])
flag_equ_end2 = 1;
for(y=0; y<4; y++) /*pf[y] is the 2nd operation*/
{
if( (k<j)&&
(((x<2)&&(y<2)) ||
((x>1)&&(y>1)))
)
continue;
op_y = pf[y](op_x, (float)num[k]);
for(z=0; z<4; z++) /*pf[z] is the 3rd operation*/
{
if((x==y)&&(x==z)&&((i!=0)||(j!=1)||(k!=2)))
continue;
if( (((z<2)&&(y<2)) ||
((z>1)&&(y>1))) &&
(k>(6-i-j-k))
)
continue;
op_z = pf[z](op_y, (float)num[6-i-j-k]);
if(((op_z - 24)>-0.0000001) && ((op_z - 24)<0.0000001))
{
flag=1;
printf("((%d %c %d) %c %d) %c %d == 24/n",num[i], cc[x], num[j], cc[y], num[k], cc[z], num[6-i-j-k]);
}
}
}
if(flag_equ_end2)
{
flag_equ_end2 = 0;
break;
}
}
}
}
}
/* Kind 2: (( (A op1 B) op2 C) op3 D) */
for(i=0; i<4; i++) /*num[i] is the first para*/
{
for(t=0; t<i; t++)
if(num[t] == num[i])
flag_i = 1;
if(flag_i)
{
flag_i=0;
continue;
}
for(j=0; j<4; j++) /*num[j] is the 2nd para*/
{
if(j == i)
continue;
for(t=j-1; t>-1; t--)
if((num[j] == num[t])&&(num[i]!=num[t]))
flag_j = 1;
if(flag_j)
{
flag_j=0;
continue;
}
for(x=0; x<2; x++) /*pf[x] is the 1st operation*/
{
if((j<i)&&(x==0))
continue;
op_x = pf[x]((float)num[i],(float)num[j]);
for(k=0; k<4; k++) /*num[k] is the 3rd para, and the last is num[6-i-j-k]*/
{
if(k==i || k==j)
continue;
for(y=0; y<2; y++) /*pf[y] is the 2nd operation*/
{
if((y==0)&&(k>(6-i-j-k)))
continue;
op_y = pf[y]((float)num[k],(float)num[6-i-j-k]);
for(z=2; z<4; z++) /*pf[z] is the 3rd operation*/
{
if((z==2) &&
(((k<i)&&(k<j)) ||
(((6-i-j-k)<i)&&((6-i-j-k)<j))
)
)
continue;
op_z = pf[z](op_x, op_y);
if(((op_z - 24)>-0.0000001) && ((op_z - 24)<0.0000001))
{
flag=1;
printf("(%d %c %d) %c (%d %c %d) == 24/n",num[i], cc[x], num[j], cc[z], num[k], cc[y], num[6-i-j-k]);
}
}
}
}
}
}
}
if(!flag)
{
flag = 0;
puts("Sorry, there is no answer!!");
}
}
int main()
{
int num[4],i;
char c='y';
while(c == 'y')
{
rand_num(num);
for(i=0; i<4; i++)
printf("%d--%s/t",num[i],ch[num[i]]);
puts("");
compute_24(num);
printf("/n/nEnter 'y' continue or others break: ");
scanf("%c",&c);
fflush(stdin);
}
}