加减乘除24

加减乘除24,去除了大部分重复结果


基本原理就是取出数组中的两个数字,运算以后和剩余的数字组成新的数组,循环前面的过程直到新数组只有一位数字,判断这个数字等不等于24。

定义类Num是为了记录数字的生成表达式和去除多余括号。

再次修改:加入了几个需要加括号的情况,减号后面是加减的情况,如6-(5-1);除号后面是表达式的情况,如6/(6/2)。


public class Dian24 {
	public static void main(String[] args) {
		Dian24 dian24 = new Dian24();
		dian24.start(2, 3, 5, 12);
		dian24.start(1, 3, 4, 6);
		dian24.start(8, 3, 8, 3);
		dian24.start(6, 6, 6, 6);
		dian24.start(1, 1, 1, 1);
		dian24.start(13, 11);
//		dian24.start(3, 3, 3, 3, 9,9);
	}

	void start(int... args) {
		Num[] nums = new Num[args.length];
		StringBuilder str = new StringBuilder();
		for (int i = 0; i < args.length; i++) {
			nums[i] = new Num(args[i]);
			if (i != 0) {
				str.append(",");
			}
			str.append(args[i]);
		}
		resultList = new HashSet<>();
		dian24(nums);
		if (resultList.size() == 0) {
			System.out.println(str.toString() + ":不能算出24");
		} else {
			System.out.print(str.toString() + ":");
			for (String result : resultList) {
				System.out.print(result + " ");
			}
			System.out.println();
		}
	}

	Set<String> resultList = null;

	/**
	 * 取出数组中两个数做加减乘除操作,结果和剩余的数字再组成一个数组,循环操作,直到数组只有一个数字,判断是不是24
	 * 在进行运算时,如果是加和乘操作,是没有先后顺序的,所以此时只需要做一遍,条件为i<j 如果是乘和除操作,外面不用加括号
	 * 判断数组中是否有重复数字,可以避免重复结果,去除i和j区间内是有和i、j重复的数字的情况
	 * 现在3,8,3,8的情况算不出来结果,23.99999999999999,但是不等于24
	 * 可以通过判断结果是否非常接近24来判断:Math.abs(nums[0].number - 24) < 1E-6
	 * 
	 * @param nums
	 */
	void dian24(Num[] nums) { // polynomials 多项式
		if (nums.length == 1) {
			// 如果结果非常接近24,认为是由于浮点类型计算的误差导致
			if (nums[0].number == 24 || Math.abs(nums[0].number - 24) < 1E-6) {
				// System.out.println(nums[0].polynomial + "=24");
				resultList.add(nums[0].polynomial + "=24");
			}
		} else {
			for (int i = 0; i < nums.length; i++) {
				for (int j = 0; j < nums.length; j++) {
					if (i == j) {
						continue;
					}

					Num[] next = new Num[nums.length - 1];
					int index = 1;
					for (int k = 0; k < nums.length; k++) {
						if (k == i || k == j) {
							continue;
						}
						next[index++] = nums[k];
					}
					if (i < j) {// 去除重复,因为加和乘没有先后顺序
						next[0] = Num.operat(nums[i], nums[j], '+');
						dian24(next);
					}
					next[0] = Num.operat(nums[i], nums[j], '-');
					dian24(next);
					if (i < j) {
						next[0] = Num.operat(nums[i], nums[j], '*');
						dian24(next);
					}
					next[0] = Num.operat(nums[i], nums[j], '/');
					dian24(next);
				}
			}
		}
	}

	static class Num {
		double number;
		String polynomial;// number运算过程字符串
		char operation; // 上一次的操作符,默认没有(0)

		public Num() {
		}

		public Num(double number) {
			this.number = number;
			this.polynomial = String.valueOf((int) number);
			operation = 0;
		}

		// test
		public Num(double number, int index) {
			this.number = number;
			this.polynomial = String.valueOf((int) number + "(" + index + ")");
			operation = 0;
		}

		public static Num operat(Num num1, Num num2, char operation) {
			Num num = new Num();
			boolean flag1 = false, flag2 = false;// 是否需要加括号的标志位
			String num1Poly, num2Poly;
			switch (operation) {
			case '+':
				num.number = num1.number + num2.number;
				break;
			case '-':
				num.number = num1.number - num2.number;
				if (num2.operation == '+' || num2.operation == '-') {
					flag2 = true;
				}
				break;
			case '*':
				num.number = num1.number * num2.number;
				if (num1.operation == '-' || num1.operation == '+') {
					flag1 = true;
				}
				if (num2.operation == '-' || num2.operation == '+') {
					flag2 = true;
				}
				break;
			case '/':
				num.number = num1.number / num2.number;
				if (num1.operation == '-' || num1.operation == '+') {
					flag1 = true;
				}
				if (num2.operation == '-' || num2.operation == '+'
						|| num2.operation == '*' || num2.operation == '/') {
					flag2 = true;
				}
				break;
			}
			if (flag1) {
				num1Poly = "(" + num1.polynomial + ")";
			} else {
				num1Poly = num1.polynomial;
			}
			if (flag2) {
				num2Poly = "(" + num2.polynomial + ")";
			} else {
				num2Poly = num2.polynomial;
			}
			num.operation = operation;
			num.polynomial = num1Poly + operation + num2Poly;
			return num;
		}
	}
}




运行结果:

2,3,5,12:12/(3-5/2)=24 
1,3,4,6:6/(1-3/4)=24 
8,3,8,3:8/(3-8/3)=24 
6,6,6,6:6+6+6+6=24 6*6-(6+6)=24 6*6-6-6=24 
1,1,1,1:不能算出24
13,11:13+11=24 


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值