递归体式格局穷举Google方程式(javascript完成)

此为《算法的兴趣》读书笔记,我用javascript从新完成算法。这个完成计划还很通用,应用了战略形式,把详细的方程盘算断绝包装到了回调函数中。

Google方程式

题目:有一个由字符构成的等式:WWWDOT – GOOGLE = DOTCOM,每一个字符代表一个0~9之间的数字,请找出一组字符和数字的对应关联,使等式建立。

定义数据结构

定义charItem数组保留题目中一切涌现的字母,leading属性示意该字母会涌如今首位;定义tagCharValue数组保留数字,used属性示意该字母的运用状况,由于差别的字母在同一时间不能相称。

var charItem = [
    { c:'W', value:-1, leading:true},
    { c:'D', value:-1, leading:true},
    { c:'O', value:-1, leading:false},
    { c:'T', value:-1, leading:false},
    { c:'G', value:-1, leading:true},
    { c:'L', value:-1, leading:false},
    { c:'E', value:-1, leading:false},
    { c:'C', value:-1, leading:false},
    { c:'M', value:-1, leading:false}
];
var tagCharValue = [
    { used:false, value:0 },
    { used:false, value:1 },
    { used:false, value:2 },
    { used:false, value:3 },
    { used:false, value:4 },
    { used:false, value:5 },
    { used:false, value:6 },
    { used:false, value:7 },
    { used:false, value:8 },
    { used:false, value:9 }
];

回调函数(详细盘算划定规矩)

把详细盘算划定规矩提取出来,放到回调函数中,运用算法具有能用性。

searchingResult(charItem,tagCharValue,0,function(ci){
    var minuend = 'WWWDOT';
    var subtrahend = 'GOOGLE';
    var diff = 'DOTCOM';

    var m = MakeIntegerValue(ci, minuend);
    var s = MakeIntegerValue(ci, subtrahend);
    var d = MakeIntegerValue(ci, diff);

    if(m - s == d){
        console.log(m + ' - ' + s + ' = ' + d);
    }
})

字符串到整数的转换

把字符替换成响应的数字。

function MakeIntegerValue(ci, str){
    var rs = str.split('');
    var outcome = 0;
    rs.forEach(function(al){
        for(var i=0; i<charItem.length; i++){
            if(charItem[i].c == al){
                outcome = outcome * 10 + charItem[i].value;
                break;
            }
        }
    })
    return outcome;
}

有效性检测

基于数字的位置及其运用情况,举行有效性检测。零不能在首位,差别字符不能相称。

function isValueValid(item, value){
    if(item.leading){
        return !value.used && value.value;
    }else{
        return !value.used;
    }
}

搜刮函数

第一层挪用,设置第一个字符后递归挪用,字符范围减少了首字符;边界条件是一切的字符都设置完成,即挪用回调函数,检测等式是不是建立,并输出等式建立的计划。

function searchingResult(ci, cv, index, callback){
    if(index == charItem.length){
        callback(ci);
        return;
    }
    for(var i=0; i<tagCharValue.length; 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;
        }
    }
}

输出效果

本题有两个解。

777589 - 188103 = 589486
777589 - 188106 = 589483

比较非递归计划

我的第一回响反映,非递归计划应当效力要高,为了考证,我写以下的非递归完成。运转的效果超越我的预期,非递归计划比递归计划慢了不止一个数量级。
剖析缘由,非递归对差别字符不能取雷同的数字的推断不好完成,且不能防止(也有多是我的判重算法效力太低);而递归计划却很天然的防止了这个题目。

for(var w = 1; w <= 9; w++)
for(var d = 1; d <= 9; d++)
for(var o = 0; o <= 9; o++)
for(var t = 0; t <= 9; t++)
for(var g = 1; g <= 9; g++)
for(var l = 0; l <= 9; l++)
for(var e = 0; e <= 9; e++)
for(var c = 0; c <= 9; c++)
for(var m = 0; m <= 9; m++){
    var tmp = {};
    tmp[w]=1;
    tmp[d]=1;
    tmp[o]=1;
    tmp[t]=1;
    tmp[g]=1;
    tmp[l]=1;
    tmp[e]=1;
    tmp[c]=1;
    tmp[m]=1;
    if(Object.keys(tmp).length == 9){
        if(w*100000+w*10000+w*1000+d*100+o*10+t - g*100000-o*10000-o*1000-g*100-l*10-e == d*100000+o*10000+t*1000+c*100+o*10+m)
            console.log(w.toString()+w.toString()+w.toString()+d.toString()+o.toString()+t.toString()+'-'+ 
                        g.toString()+o.toString()+o.toString()+g.toString()+l.toString()+e.toString()+'='+ 
                        d.toString()+o.toString()+t.toString()+c.toString()+o.toString()+m.toString());
    }
}
    原文作者:zhoutk
    原文地址: https://segmentfault.com/a/1190000004865671
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞