巧填算符

小朋友3年级的数学题:1 2 3 4 5 每个数字之间填上符号,使最后计算结果等于20。要找到一个答案就很容易,但小朋友要比试谁找到的答案多,这就有意思了。干脆写个程序来穷举所有的例子。

这种问题,第一个就要想到使用栈,因为数字排列是有顺序的。按1,2,3,4,5的顺序依次push到栈中,每次push一个新数字进去的时候,可以有五个选择:
1、什么都不做
2-5、pop两个数字,分别做加、减、乘、除,然后把结果push进栈
因此尝试每种选择,进行递推的处理。每试过一种选择之后,都要把现场还原——把放进栈中的数字取出来,把取出来的数字放回去。最后就是栈外没有数字,栈中只有一个数字,如果这个数字是20,那么就有一个解了。

在这个过程中,注意要记录每一步生成的算式,再处理一下括号的问题,就完成了。

import Util.OperateType;
import Util.Polynomial;

import java.util.ArrayList;
import java.util.List;
import java.util.Stack;

public class FillOperator {
    private static Stack<Polynomial> restPolynomial = new Stack<Polynomial>();
    private static Stack<Polynomial> runStack = new Stack<Polynomial>();
    private static OperateType[] opes = new OperateType[]{OperateType.OPE_ADD,
                                            OperateType.OPE_SUBTRACT,
                                            OperateType.OPE_MUTIPLY,
                                            OperateType.OPE_DIVIDE};
    private static int targetValue;
    private static List<String> resultList = new ArrayList<String>();

    public static void main(String[] args){
        targetValue = 20;
        restPolynomial.push(new Polynomial(5));
        restPolynomial.push(new Polynomial(4));
        restPolynomial.push(new Polynomial(3));
        restPolynomial.push(new Polynomial(2));
        restPolynomial.push(new Polynomial(1));

        round();

        for (String desc : resultList){
            System.out.println(desc);
        }
    }

    private static void round(){
        if ((restPolynomial.isEmpty()) && (1 == runStack.size())){
            if (targetValue == runStack.get(0).value){
                if (!resultList.contains(runStack.get(0).desc)){
                    resultList.add(runStack.get(0).desc);
                }
            }
            return;
        }

        if (!restPolynomial.isEmpty()){
            Polynomial basePolynomial = restPolynomial.pop();
            runStack.push(basePolynomial);
            round();
            runStack.pop();
            restPolynomial.push(basePolynomial);
        }

        if (runStack.size() >= 2){
            Polynomial b = runStack.pop();
            Polynomial a = runStack.pop();

            for (OperateType opeType : opes){
                Polynomial mergedPolynomial = a.merge(b, opeType);
                if (null != mergedPolynomial){
                    runStack.push(mergedPolynomial);
                    round();
                    runStack.pop();
                }
            }

            runStack.push(a);
            runStack.push(b);
        }
    }
}

package Util;

public enum OperateType {
    OPE_ADD,
    OPE_SUBTRACT,
    OPE_MUTIPLY,
    OPE_DIVIDE,
    OPE_NONE;

    public static int compareOpearteType(OperateType a, OperateType b){
        if (((OPE_MUTIPLY == a) || (OPE_DIVIDE == a)) && ((OPE_ADD == b) || (OPE_SUBTRACT == b))){
            return 10; // 10表示 a 更高级
        }

        if (((OPE_MUTIPLY == b) || (OPE_DIVIDE == b)) && ((OPE_ADD == a) || (OPE_SUBTRACT == a))){
            return -10; // -10表示 b 更高级
        }

        return 0; // 0 表示 a,b同级
    }
}

package Util;

public class Polynomial {
    public int value;
    public String desc;
    public OperateType operateType;

    public Polynomial(int value){
        this.value = value;
        this.desc = String.valueOf(value);
        this.operateType = OperateType.OPE_NONE;
    }

    public Polynomial merge(Polynomial target, OperateType opeType) {
        Polynomial mergedPolynomial = null;
        switch (opeType) {
            case OPE_ADD:
                mergedPolynomial = new Polynomial(this.value + target.value);
                mergedPolynomial.desc = mergeDesc(this, target, opeType);
                mergedPolynomial.operateType = OperateType.OPE_ADD;
                break;
            case OPE_SUBTRACT:
                if (this.value >= target.value) {
                    mergedPolynomial = new Polynomial(this.value - target.value);
                    mergedPolynomial.desc = mergeDesc(this, target, opeType);
                    mergedPolynomial.operateType = OperateType.OPE_SUBTRACT;
                }
                break;
            case OPE_MUTIPLY:
                mergedPolynomial = new Polynomial(this.value * target.value);
                mergedPolynomial.desc = mergeDesc(this, target, opeType);
                mergedPolynomial.operateType = OperateType.OPE_MUTIPLY;
                break;
            case OPE_DIVIDE:
                if ((target.value != 0) && (0 == (this.value % target.value))) {
                    mergedPolynomial = new Polynomial(this.value / target.value);
                    mergedPolynomial.desc = mergeDesc(this, target, opeType);
                    mergedPolynomial.operateType = OperateType.OPE_DIVIDE;
                }
                break;
            default:
                break;
        }

        return mergedPolynomial;
    }

    private String mergeDesc(Polynomial a, Polynomial b, OperateType opeType){
        String left, right;

        if (OperateType.OPE_NONE == a.operateType){
            left = a.desc;
        }else{
            if (10 == OperateType.compareOpearteType(opeType, a.operateType)){
                left = String.format("(%s)", a.desc);
            }else{
                left = a.desc;
            }
        }

        if (OperateType.OPE_NONE == b.operateType){
            right = b.desc;
        }else{
            if ((OperateType.OPE_SUBTRACT == opeType) || (OperateType.OPE_DIVIDE == opeType)){
                right = String.format("(%s)", b.desc);
            }else if (10 == OperateType.compareOpearteType(opeType, b.operateType)){
                right = String.format("(%s)", b.desc);
            }else {
                right = b.desc;
            }
        }

        switch (opeType) {
            case OPE_ADD:
                return String.format("%s + %s", left, right);
            case OPE_SUBTRACT:
                return String.format("%s - %s", left, right);
            case OPE_MUTIPLY:
                return String.format("%s x %s", left, right);
            case OPE_DIVIDE:
                return String.format("%s / %s", left, right);
            default:
                return "";
        }
    }
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值