加减乘除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