练习程序:算法系列1:Google方程式

描述、思路

参考1:算法系列之一 :Google方程式

补充知识

参考2:C语言条件编译及编译预处理阶段
参考3:C++技巧之断言Assert

实现

使用条件编译,解决不同问题时选择性注释一下条件编译#define ISGOOGLE指令即可分别解决不同问题:
“WWWDOT - GOOGLE = DOTCOM” ——》 #define ISGOOGLE
“AAB – BBC = CCD” —————————》 //#define ISGOOGLE(注释掉即可)

#include <iostream>
#include <cassert>
// 条件编译
// #define ISGOOGLE 未被注释掉时,表示求解google equation问题
// #define ISGOOGLE 被注释掉时,表示求解secret equation问题
//#define ISGOOGLE

const int max_number_count = 10;
#ifdef ISGOOGLE
const int max_char_count = 9;
#else
const int max_char_count = 4;
#endif //ISGOOGLE

/*字母三元组*/
struct CharItem
{
    char c;         // 字母
    int value;      // 数值
    bool leading;   // 是否为开头
};

/* 数值二元组 */
struct CharValue
{
    bool used;      // 是否被使用
    int value;      // 数值
};

/* 回调函数指针(回调判断本次分配的字母数值组合是否满足方程) */
typedef void (*CharListReadyFuncPtr)(CharItem ci[max_char_count]);

/* 从字母三元组数组ci中,找到字符c对应的指向三元组的指针 */
CharItem* GetCharItem(CharItem ci[max_char_count], char c)
{
    for(int i = 0; i < max_char_count; ++i)
    {
        if(ci[i].c == c)
        {
            return &ci[i];
        }
    }
    return NULL;
}

/* 判断是否可以为ci中的字母分配cv中的数字 */
bool IsValueValid(CharItem ci, CharValue cv)
{
    if(cv.used)
    {
        return false;
    }
    if(ci.leading && (cv.value == 0))
    {
        return false;
    }
    return true;
}

/* 根据字母三元组ci的分配,计算字符串chars对应的整数值 */
int MakeIntegerValue(CharItem ci[max_char_count], char* chars)
{
    assert(chars);
    int value = 0;
    char* p = chars;
    while(*p)
    {
        CharItem* char_item = GetCharItem(ci, *p);
        if(char_item == NULL)
        {
            return 0;
        }
        value = value* 10 + char_item->value;
        p++;
    }
    return value;
}

#ifdef ISGOOGLE
/* 检查本次分配的字母数值是否满足等式,若满足则打印 */
void CharListReady(CharItem ci[max_char_count])
{
    char* minuend    = "WWWDOT";
    char* subtrahend = "GOOGLE";
    char* diff       = "DOTCOM";

    int m = MakeIntegerValue(ci, minuend);
    int s = MakeIntegerValue(ci, subtrahend);
    int d = MakeIntegerValue(ci, diff);
    if((m - s) == d)
    {
        std::cout << m << " - " << s << " = " << d << std::endl;
    }
    return;
}
#else

/* ABCD问题:检查本次分配的字母数值是否满足等式,若满足则打印 */
void CharListReady(CharItem ci[max_char_count])
{
    char* minuend    = "AAB";
    char* subtrahend = "BBC";
    char* diff       = "CCD";

    int m = MakeIntegerValue(ci, minuend);
    int s = MakeIntegerValue(ci, subtrahend);
    int d = MakeIntegerValue(ci, diff);
    if((m - s) == d)
    {
        std::cout << m << " - " << s << " = " << d << std::endl;
    }
    return;
}
#endif // ISGOOGLE

/* 核心: 为字母三元组数组ci分配数值二元组中的可能的数值组合,
  index标志分配到的字母编号,从0开始 */
void SearchingResult(CharItem ci[max_char_count],
                     CharValue cv[max_number_count],
                     int index, CharListReadyFuncPtr callback)
{
    //为所有字符分配完数值,若是解则打印,然后返回上一层
    if(index == max_char_count)
    {
        callback(ci);//检查ci是否是符合等式的字符组合,若符合则打印
        return;
    }
    //每层递归要遍历所有未使用的数字
    for(int i = 0; i < max_number_count; ++i)
    {
        // 检查能否分配该数字,检查数字是否使用、字母是否是开头字母
        if(IsValueValid(ci[index], cv[i]))
        {
            //穷举赋值
            cv[i].used = true;
            ci[index].value = cv[i].value;
            //继续下层递归
            SearchingResult(ci, cv, index + 1, callback);
            //继续同层遍历
            cv[i].used = false;
        }
    }
    return;
}

void solve()
{
    /* 数值二元组初始化 */
    CharValue char_val[max_number_count] =
    {
        {false,0}, {false,1}, {false,2}, {false,3},
        {false,4}, {false,5}, {false,6}, {false,7},
        {false,8}, {false,9}
    };
    #ifdef ISGOOGLE
    std::cout << "Solve Google Equation \"WWWDOT - GOOGLE = DOTCOM\" : " << std::endl;
    /* 字母三元组初始化 */
    CharItem char_item[max_char_count] =
    {
        {'W',-1,true}, {'D',-1,true}, {'O',-1,false},
        {'T',-1,false}, {'G',-1,true}, {'L',-1,false},
        {'E',-1,false}, {'C',-1,false}, {'M',-1,false}
    };
    #else
    std::cout << "Solve Secret Equation \"AAB – BBC = CCD\" : " << std::endl;
    /* 字母三元组初始化 */
    CharItem char_item[max_char_count] =
    {
        {'A',-1,true}, {'B',-1,true}, {'C',-1,true}, {'D',-1,false}
    };
    #endif //ISGOOGLE
    SearchingResult(char_item, char_val, 0, CharListReady);
    return;
}

int main()
{
    // 代码顶部#define ISGOOGLE,表示求解GOOGLE方程问题
    // 代码顶部#define ISGOOGLE被注释掉时,表示求解Secret方程问题
    solve();
    return 0;
}

运行结果

每次编译、运行时改变的源码顶部以及运行效果如图:

Goolge问题效果图:

这里写图片描述

Secret问题效果图:

这里写图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值