Google方程式

Posted coolcpp

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Google方程式相关的知识,希望对你有一定的参考价值。

书名:《算法的乐趣》

1. 问题描述:

有一个由字符组成的等式:WWWDOT - GOOGLE = DOTCOM,每个字符代表一个0-9之间的数字,并且这三组字母组成的都是合法的数字,不能以0开头。找出一组字符和数字的对应关系,使满足这个式子。

2. 解题思路:

首先定义一个表示字符属性的结构:

typedef struct{
    char c;        //字母本身
    int value;     //字母代表的数字
    bool leading;  //是否是数字的最高位
}CHAR_ITEM;

这样,本题可以初始化为:

CHAR_ITEM charItem[] = {
    {‘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 } };

由于这是一个组合问题,两个字母不能为相同的数字,所以,需要对每个数字做一个标记,表示其是否已被使用。

typedef struct{
    bool used;  //是否已被使用
    int value;  //值
}CHAR_VALUE;

穷举的搜索算法采用递归的方式进行组合枚举, 按照charItem中的顺序,逐个对每个字符进行数字遍历:

void SearchingResult(CHAR_ITEM ci[], CHAR_VALUE cv[],
    int index, CharListReadyFuncPtr callback)
{
    if(index == max_char_count)
    {
        callback(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;  //用0-9来测
            SearchingResult(ci, cv, index + 1, callback);
            cv[i].used = false;  //清除标记
        }
    }
}

开头字母为‘W‘,‘G‘,‘D‘,所以这三个数字不能为0,在IsValueValid中实行判断。index用来标识字符索引,每次递归调用对索引为index的字符进行数字遍历。当index等于字符个数时,表示所有的字符都已经指定了对应的数字,便可调用callback进行结果判断。

IsValueValid的实现:

bool IsValueValid(CharItem ci, CharValue cv)
{
    if(cv.used)
    {
        return false;
    }
    
    if(ci.leading && (cv.value == 0))
    {
        return false;
    }
    
    return true;
}

callback函数的实现:

void OnCharListReady(CHAR_ITEM ci[])
{
    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;
    }
}

MakeIntegerValue用于将组成的数字转化为6位的值,其实现为:

int MakeIntegerValue(CharItem ci[max_char_count], char *chars)
{
    assert(chars);
    
    int value = 0;
    char *p = chars;
    while(*p != 0)
    {
        CharItem *char_item = GetCharItem(ci, *P);
        
        if(NULL == char_item)
        {
            return 0;
        }
        
        value = value * 10 + char_item->value;
        p++;
    }
    
    return value;
}

3. 完整代码

//equa_define.h
#pragma once

typedef struct
{
    char c;        //字母本身
    int value;     //代表的数字
    bool leading;  //是否是最高位
}CharItem;

typedef struct
{
    bool used;  //是否使用过
    int value;  //值
}CharValue;

const int max_number_count = 10;
const int max_char_count = 9;

typedef void(*CharListReadyFuncPtr)(CharItem ci[max_char_count]);
//char_equation.h
#pragma once
#include "equa_define.h"

int MakeIntegerValue(CharItem ci[max_char_count], char *chars);
void SearchingResult(CharItem ci[max_char_count],
                     CharValue cv[max_number_count],
                     int index, CharListReadyFuncPtr callback);
//char_equation.cpp
#include <cassert>
#include "char_equation.h"

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

int MakeIntegerValue(CharItem ci[max_char_count], char *chars)
{
    assert(chars);

    int value = 0;
    char *p = chars;
    while (*p != 0)
    {
        CharItem *char_item = GetCharItem(ci, *p);

        if (NULL == char_item)
        {
            return 0;
        }

        value = value * 10 + char_item->value;
        p++;
    }

    return value;
}

bool IsValueValid(CharItem ci, CharValue cv)
{
    if (cv.used)
    {
        return false;
    }

    if (ci.leading && (cv.value == 0))
    {
        return false;
    }

    return true;
}

void SearchingResult(CharItem ci[max_char_count],
                     CharValue cv[max_number_count],
                     int index, CharListReadyFuncPtr callback)
{
    if (index == max_char_count)
    {
        callback(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;  //用0-9来测
            SearchingResult(ci, cv, index + 1, callback);
            cv[i].used = false;
        }
    }
}
//main.cpp
#include <iostream>
#include "char_equation.h"
#include "equa_define.h"

void OnCharListReady(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;
    }
}

int main()
{
    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 } };
    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} };
    
    SearchingResult(char_item, char_val, 0, OnCharListReady);

    return 0;
}

输出:
777589 - 188103 = 589486
777589 - 188106 = 589483



以上是关于Google方程式的主要内容,如果未能解决你的问题,请参考以下文章

RecyclerView holder中的Android Google Maps动态片段

片段中的 Xamarin Android Google 地图错误

算法系列:Google方程式

穷举搜索的例子:Google方程式(Java题解)

Google方程式

Java 封装