zoukankan      html  css  js  c++  java
  • 移动一根火柴使等式成立js版本(递归)

    修改成递归版本

    思路:

      1、设定规则数组,比如:1加一根火柴只可以变成7.

      2、设定方法数组,比如:一个数增加了一根火柴,其他的数必然减少一根火柴。

      3、增加Array方法,由元素名和方法,得到规则对象。

      4、增加替换数组元素的方法,根据原数组和下标,得到 一个字符串。有2个方法,一个深度copy,一个普通指针,这样就可以自由选择是否改变原来的数组了。

      5、主逻辑:

        根据式子生成数组

        遍历数组元素,匹配规则,匹配到,递归进行二次匹配。

        匹配不到规则,递归下一个元素。

          

    <html>
    <head>
    <title>移动一根火柴使等式成立js版本</title>
    <meta http-equiv="Content-Type" content="text/html; charset=gbk">
    <script language="javascript">
    //递归阶乘
    function getNum(i){
        if (i>1){
            return i*getNum(i-1);
        }else{
            return 1;
        }
    }
    //console.log(getNum(3));
    
    
    /**
    * 规则的设定,按照信号灯样式,8就是由7根火柴棍组成
    * 设定变化规则:
    * add:    0-》8
    *        1-》7
    *        3-》9
    *        5-》6,9
    *        6-》8
    *        9-》8
    *        - -》+,=
    * sub: 6-》5
    *        7-》1
    *        8-》0.6,9
    *        9->3,5
    *        + -> -
    *        = -> -
    * mv:    0 -> 6,9
    *        2 -> 3
    *        3 -> 5
    *        6 -> 9
    *        9 -> 0,6
    */        
    var data = [];
    data.push({a:0,b:[8],m:"add"}); //0加一根火柴可以变化为8以此类推
    data.push({a:0,b:[6,9],m:"mv"});
    data.push({a:1,b:[7],m:"add"});
    data.push({a:2,b:[3],m:"mv"});
    data.push({a:3,b:[5],m:"mv"});
    data.push({a:3,b:[9],m:"add"});
    data.push({a:5,b:[6,9],m:"add"});
    data.push({a:6,b:[5],m:"sub"});
    data.push({a:6,b:[9],m:"mv"});
    data.push({a:6,b:[8],m:"add"});
    data.push({a:7,b:[1],m:"sub"});
    data.push({a:8,b:[0,6,9],m:"sub"});
    data.push({a:9,b:[0,6],m:"mv"});
    data.push({a:9,b:[3,5],m:"sub"});
    data.push({a:9,b:[8],m:"add"});
    data.push({a:"+",b:["-"],m:"sub"});
    data.push({a:"-",b:["+","="],m:"add"});
    data.push({a:"=",b:["-"],m:"sub"});
    
    //修改数组,增加方法 可以由key和method得到唯一的变化规则对象。
    Array.prototype.get = function(key, method){
        for(var i = 0; i < this.length; i++){
            if(this[i].a == key && this[i].m == method){
                return this[i];
            }
        }
    }
    
    
    /**
    *    转换字符串:将原式子替换成根据规则变换后的式子
    *    params:
    *        ori:    原式子
    *        index:    需要替换的位置
    *        fin:    根据规则替换的数字
    *
    *    return 替换后的字符串
    */
    function changeStr(ori, index, fin){
        var str = ori.substr(0, index) + fin + ori.substring(index+1, ori.length); 
        return str;
    }
    
    //返回替换后的字符串,并不改变原来数组的值,深度copy
    function changeArrMirror(oriArr, index, fin){
        var tempArr = oriArr.slice(0);
        tempArr[index] = fin; 
        var str = tempArr.join("");
        return str;
    }
    
    //返回替换后的字符串,并改变原来数组的值,指针copy
    function changeArrAll(oriArr, index, fin){
        oriArr[index] = fin; 
        var str = oriArr.join("");
        return str;
    }
    
    /**
    * 计算主体方法:以2+3=6为例
    * 基本逻辑:得到原字符串数组[2, +, 3, =, 6],从第一位开始,查找规则,
    *        匹配到规则,递归下一个元素查找相反规则,构成字符串,查看是否成立,成立则打印,继续程序,查找下一个成立等式
    *        匹配不到规则,递归下一个方法元素,都匹配不到,递归下一个式子元素。    
    * param:
    *        originArr: 拆分的待匹配的数组
    *        originIndex: 式子数组的索引,正在匹配的元素下标
    *        methodIndex: 方法数组的索引
    *        isChanged: 是否匹配了第一个元素
    * return:
    */
    function compare(originArr, originIndex, methodIndex, isChanged){
        if (originIndex >= originArr.length){
            return;
        }
        if (methodIndex == 2){
            isChanged = true;
        }
    
        //已经匹配第一次的式子,进行第二次匹配,需要得到 methodArr[methodIndex]的成对方法匹配
        //        匹配不到规则,递归式子数组的下一个值
        //        匹配到规则,循环查看规则的值,看是否有能另等式成立的,如果都不能成立,递归式子数组的下一个值
        if(isChanged){
            var role = data.get(originArr[originIndex], methodArr[methodIndex][1]);
            if (role == undefined || role == null){
                compare(originArr, originIndex + 1, methodIndex, isChanged);
            }else{
                for (var matchIndex=0; matchIndex < role.b.length; matchIndex++){
                    var changedStr = changeArrMirror(originArr, originIndex, role.b[matchIndex]);    
                    if (eval(changedStr.split("=")[0]) == eval(changedStr.split("=")[1])){
                        console.log(changedStr);
                        flag = true;
                        return;
                    }
                }
                compare(originArr, originIndex + 1, methodIndex, isChanged);
            }
        }else{
            //匹配方法数组元素的第一个method,看是否有规则
            //        如果有,设定匹配标识isChanged=true,进行二次匹配
            //        如果没有,递归下一个式子数组元素。
            var role = data.get(originArr[originIndex], methodArr[methodIndex][0]);
            
            //如果没有相应rule,匹配方法数组的其他方法,直到都匹配了
            if (role == undefined || role == null){
                if (methodIndex >= methodArr.length)
                    compare(originArr, originIndex + 1, 0, isChanged);
                else
                    compare(originArr, originIndex, methodIndex + 1, isChanged);
            }else{
                for (var matchIndex=0; matchIndex < role.b.length; matchIndex++){
                    var changedStr = changeArrAll(originArr, originIndex, role.b[matchIndex]);    
                    isChanged = !isChanged;
                    compare(originArr, originIndex + 1, methodIndex, isChanged);
                }
            }
    
        }
    }
    
    //方法数组,成对出现
    var methodArr = [["add", "sub"], ["sub", "add"], ["mv", "mv"]];
    var flag = false;
    
    //得到原始式子,分割成数组,调用递归函数进行计算。
    function compute(){
        var originStr = document.getElementById("origin").value;
        
        var baseArr = originStr.split("");
        for (var i=0; i<baseArr.length; i++){
            var tempBaseArr = baseArr.slice(0);
            compare(tempBaseArr, i, 0, false);
        }
        if (!flag){
            console.log("没有匹配答案");
        }
        
    }
    
    
     
    </script>
    </head>
    <body>
    输入一个需要计算的式子,例如:1+2+3=6
    <input id="origin" onkeypress="if(event.keyCode == 13) compute();"/>
    <input type="button" value="计算" onclick="compute()" />
    </body>
    </html>
  • 相关阅读:
    js数组
    js字符串和控制语句
    生成器、列表解析
    js属性
    js函数
    js变量
    python抽象方法
    python 装饰器的缺点以及解决方法
    windows文件关联、打开方式列表之修改注册表攻略
    JavaScript定时器及其他
  • 原文地址:https://www.cnblogs.com/PPBoy/p/9329518.html
Copyright © 2011-2022 走看看