火柴棍移动的一道面试题

最近有朋友找工作,面试某公司,遇到一个火柴棍移动的面试题,感觉有点意思,在此抛砖引玉。


题目大致是这样的:

一个三个数的式子,移动其中一根火柴,使等式成立,用程序或实现(可以用伪码),输出能成立的等式。

注:“+”可以移走一根火柴变成“-”

例如:



废话不说,直接上代码,哪位网友有更好的方法,请分享一下,多谢

#include <stdio.h>

/* 定义操作符号,"+"或"-" */
#define SYMBOL_ERROR 0
#define SYMBOL_ADD   1
#define SYMBOL_MINUS 2

/* 定义变化标识,取值原则:3个中随便取出n个相加不能等于其中一个数 */
#define FLAG_NO    0     /* 没有移动 */
#define FLAG_MINUS 10    /* 去一根火柴 */
#define FLAG_ADD   100   /* 增加一根火柴 */
#define FLAG_SELF  1000  /* 拿一根放自己身上另外的位置 */

/* 定义合法移动 */
#define MOVE_TO_ANOTHER 110   /* 10 + 100 + 0,一个数拿一根,放到另一个数上 */
#define MOVE_TO_SELF    1000  /* 1000 + 0 + 0,自己拿一根放自己身上其他位置 */
#define MOVE_FROM_PLUS  100   /* 100 + 0 + 0,从加号上拿一根放一个数身上 */

/* 定义火柴移动结构体 */
typedef struct matchstick
{
    int iFlag; /* 变化标识 */
    int iData; /* 火柴表示的数 */
}MATCH_STICK_S;

/* 
  获取一个数不动或移动一根火柴后得到的数(只列举3和6,其他数值类似)
  入参:指定的数(0-9)
  出差:MATCH_STICK_S结构数组
  返回值:移动一根火柴得到的数的个数
*/
int getDataAfterMoveStick(int iData, MATCH_STICK_S *pstStick)
{
    int iCount = 0;
    
    switch(iData)
    {
        case 3:
        {
            pstStick[0].iFlag = FLAG_NO; pstStick[0].iData = 3;   /* 不动 */
            pstStick[1].iFlag = FLAG_ADD; pstStick[1].iData = 9;  /* 加一根 */
            pstStick[2].iFlag = FLAG_SELF; pstStick[2].iData = 2; /* 自己移动一根 */
            pstStick[3].iFlag = FLAG_SELF; pstStick[3].iData = 3;
            pstStick[4].iFlag = FLAG_SELF; pstStick[4].iData = 5;
            iCount = 5;
            break;
        }
        case 6:
        {
            pstStick[0].iFlag = FLAG_NO; pstStick[0].iData = 6;    /* 不动 */
            pstStick[1].iFlag = FLAG_ADD; pstStick[1].iData = 8;   /* 加一根 */
            pstStick[5].iFlag = FLAG_MINUS; pstStick[5].iData = 5; /* 减一根 */
            pstStick[2].iFlag = FLAG_SELF; pstStick[2].iData = 0;  /* 自己移动一根 */
            pstStick[3].iFlag = FLAG_SELF; pstStick[3].iData = 6;
            pstStick[4].iFlag = FLAG_SELF; pstStick[4].iData = 9;            
            iCount = 6;
            break;
        }
        default:
        {
            break;
        }
    }
    
    return iCount;
}

/* 移动火柴
   返回值:
   SYMBOL_ERROR:非法移动
   SYMBOL_MINUS:从"+"上取一根加到某个数上
   SYMBOL_ADD:  不从"+"取火柴时,移动一根
 */
char checkStickMove(int iFlag1, int iFlag2, int iFlag3)
{
    char cSymbol = SYMBOL_ERROR;
    int iFlagSum = iFlag1 + iFlag2 + iFlag3;
    
    if((MOVE_TO_ANOTHER == iFlagSum) || (MOVE_TO_SELF == iFlagSum))
    {
        cSymbol = SYMBOL_ADD;
    }
    else if(MOVE_FROM_PLUS == iFlagSum)
    {
        cSymbol = SYMBOL_MINUS;
    }
    
    return cSymbol;
}

/* 满足移动规则,并能使等式成立的,打印出来 */
void printResult(MATCH_STICK_S *pstStick1, MATCH_STICK_S *pstStick2, MATCH_STICK_S *pstStick3)
{
    int iFlag1 = pstStick1->iFlag;
    int iFlag2 = pstStick2->iFlag;
    int iFlag3 = pstStick3->iFlag;
    int iData1 = pstStick1->iData;
    int iData2 = pstStick2->iData;
    int iData3 = pstStick3->iData;
    
    char cSymbol = checkStickMove(iFlag1, iFlag2, iFlag3);
    
    if((SYMBOL_ADD == cSymbol) && (iData3 == iData1 + iData2))
    {
    	printf("%d + %d = %d\n", iData1, iData2, iData3);
    }
    else if((SYMBOL_MINUS == cSymbol) && (iData3 == iData1 - iData2))
    {
    	printf("%d - %d = %d\n", iData1, iData2, iData3);
    }
    
    return;
}

/* 处理火柴移动 */
void dealStickMove(int iData1, int iData2, int iData3)
{
    unsigned long ulLoop1, ulLoop2, ulLoop3;   
    int iCount1, iCount2, iCount3;
    MATCH_STICK_S astStick1[10];
    MATCH_STICK_S astStick2[10];
    MATCH_STICK_S astStick3[10];
    
    iCount1 = getDataAfterMoveStick(iData1, astStick1);
    iCount2 = getDataAfterMoveStick(iData2, astStick2);
    iCount3 = getDataAfterMoveStick(iData3, astStick3);
    
    for(ulLoop1 = 0; ulLoop1 < iCount1; ulLoop1++)
    {
        for(ulLoop2 = 0; ulLoop2 < iCount2; ulLoop2++)
        {
            for(ulLoop3 = 0; ulLoop3 < iCount3; ulLoop3++)
            {
                printResult(&astStick1[ulLoop1], &astStick2[ulLoop2], &astStick3[ulLoop3]);
            }
        }
    }

    return;
}

int main()
{
    dealStickMove(3, 6, 3);
    
    return 0;
}


运行结果:

3 + 0 = 3
9 - 6 = 3

  • 3
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值