另类穷举计算24

 

 

/******************************************************************************
计算 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);
   }

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
https://bbs.125.la/forum.php?mod=viewthreadtid=14664204 前天搞到现在,终于搞完了。 设计了一种原理和正则有一点相像的表达式,不是匹配文本,而是穷举生成文本 关键字:`\()<>[]{} 1    aa11    字符 2    aA0    裂变元    a依次裂变a,b,c,...z,0依次裂变0,1,2,...9 3    `01-100`    数值过渡    起始-结束,依次是01,02,03,...100,如果起始小于等于结束,递增过渡,否则递减,可以在较小数值前面补0,指定结果最小长度 4    \PI\    回调cha询    用这个关键词去调用回调函数取结果 0    (aa11)    字符组    括号包含的非关键字识别为字符,整个表达式外层默认识别为一个字符组,即外层出现的非关键字默认识别为字符 0    <aA0>    裂变元组    尖括号包含的非关键字识别为裂变元 5    [123]    可选组    两个结果(选或不选),一个空白,一个123 6    {123(444)}    集合单选组    依次是1,2,3,(444) 四种括号可以任意嵌套,里面的内容含义,取决于由内到外的括号链 同层没有优先级,从右到左进行 //如果设计一个互斥组,可以实现m选n,目前不支持,不偏向这个,也没有更多括号了…… //*3~3 示例: qq<00000>    结果:qq00000,qq00001,qq00002,...qq99999的10w个字符串 id`8-80`    结果:id8,id9,id10,...id80 \time\    结果:16:40,如果指定了回调函数,回调函数cha询time,返回了16:40 {123456789}<0000>    结果:10000-99999 {(123)4}[5]    结果:123,4,1235,45 <0aaa>    结果:1个数字开头,后面3个字母到5个字母的所有组合
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值