import java.util.List;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
import java.util.Scanner;
import java.util.Set;
public class TwentyFourPoint {
public static void main(String[] args) {
System.out.println("请输入4个0~13的整数:");
int b1=new Scanner(System.in).nextInt();
int b2=new Scanner(System.in).nextInt();
Scanner a3=new Scanner(System.in);
int b3=a3.nextInt();
Scanner a4=new Scanner(System.in);
int b4=a4.nextInt();
if((0<=b1&&b1<=13)&&(0<b2&&b2<=13)&&(0<b2&&b2<=13)&&(0<b2&&b2<=13)) {
}
else {
System.out.println("数值输入错误,请重新输入");
TwentyFourPoint.main(args);
}
try {
Set<String> set = caculate(new int[] { b1, b2, b3, b4 }, 24);
printlnResultSet(set);
} catch (Exception e) {
// e.printStackTrace();开发期间方便查找错误,测试通过后就无需打印错误信息了
System.err.println(e.getMessage());
}
}
private static void printlnResultSet(Collection<String> resultSet) {
for (String str : resultSet) {
System.out.println(str);
}
}
private static int[][] arrangeAllNumbers(int[] numbers) {
List<int[]> list = new ArrayList<int[]>();
allSort(numbers, 0, numbers.length - 1, list);
int[][] resultSet = new int[list.size()][list.get(0).length];
resultSet = list.toArray(resultSet);
return resultSet;
}
/**
* 得到给定的操作中出现的所有操作符排列情况
*
* @param operators
* 出现的操作符数组
* @param number
* 每组操作符的数量
* @return 所有操作符排列数组
*/
private static char[][] arrangeAllOperators(char[] operators, int number) {
int setSize = (int) Math.pow(operators.length, number);
int index = 0;
char[][] resultSet = new char[setSize][number];
for (int i = 0; i < operators.length; i++) {
for (int j = 0; j < operators.length; j++) {
for (int k = 0; k < operators.length; k++) {
resultSet[index][0] = operators[i];
resultSet[index][1] = operators[j];
resultSet[index][2] = operators[k];
index++;
}
}
}
return resultSet;
}
public static Set<String> caculate(int[] numbers, int targetNumber)
throws Exception {
Set<String> resultSet = new HashSet<String>();// 这里用Set而不是用List,主要是因为当给定的一组数字中如果有重复数字的话,同一结果会被出现多次,如果用List存放的话,会将重复的结果都存放起来,而Set会自动消除重复值
char[][] operatorsArrangement = arrangeAllOperators(new char[] { '+',
'-', '*', '/' }, 3);
int[][] numbersArrangement = arrangeAllNumbers(numbers);
for (int[] nums : numbersArrangement)
for (char[] operators : operatorsArrangement) {
int result = 0;
try {
result = caculate(nums, operators);
} catch (Exception e) {// 出现非精确计算
continue;
}
if (result == targetNumber)
resultSet.add(buildString(nums, operators, targetNumber));// 如果计算后的结果等于想要的结果,就存放到集合中
}
if (resultSet.isEmpty())
throw new Exception("给定的数字:" + Arrays.toString(numbers)
+ "不能通过加减乘除运算得到结果:" + targetNumber);
return resultSet;
}
private static String buildString(int[] nums, char[] operators, int target) {
String str = String.valueOf(nums[0]);
for (int i = 0; i < operators.length; i++) {
str = '('+str +' '+ operators[i] +' '+ nums[i + 1]+')';
}
str = str + " = " + target;
return str;
}
private static int caculate(int[] nums, char[] operators) throws Exception {
int result = 0;
for (int i = 0; i < operators.length; i++) {
if (i == 0) {
result = caculate(nums[i], nums[i + 1], operators[i]);
} else {
result = caculate(result, nums[i + 1], operators[i]);
}
}
return result;
}
private static int caculate(int num1, int num2, char operator)
throws Exception {
double result = 0;
switch (operator) {// 根据操作符做相应的计算操作
case '+':
result = num1 + num2;
break;
case '-':
result = num1 - num2;
break;
case '*':
result = num1 * num2;
break;
case '/':
result = (double) num1 / (double) num2;
break;
}
if (!check(result))
throw new Exception("不精确的计算数字");
return (int) result;
}
private static boolean check(double result) {
String str = String.valueOf(result);
int pointIndex = str.indexOf(".");// 小数点的下标值
String fraction = str.substring(pointIndex + 1);
return fraction.equals("0") ? true : false;// 通过判断小数点后是否只有一个0来确定是否可以无损转换为整型数值
}
private static void allSort(int[] buf, int start, int end, List<int[]> list) {
if (start == end) {// 当只要求对数组中一个字母进行全排列时,只要就按该数组输出即可
int[] a = new int[buf.length];
System.arraycopy(buf, 0, a, 0, a.length);
list.add(a);
} else {// 多个字母全排列
for (int i = start; i <= end; i++) {
int temp = buf[start];// 交换数组第一个元素与后续的元素
buf[start] = buf[i];
buf[i] = temp;
allSort(buf, start + 1, end, list);// 后续元素递归全排列
temp = buf[start];// 将交换后的数组还原
buf[start] = buf[i];
buf[i] = temp;
}
}
}
}