1. 程式人生 > >1 2 3 4 5 6 7 8 9 = 110,在數字間填入加號或者減號(可以不填,但不能填入其它符號)使等式成立。

1 2 3 4 5 6 7 8 9 = 110,在數字間填入加號或者減號(可以不填,但不能填入其它符號)使等式成立。

一共有3^8種可能。 答案: 成功:12+34+56+7-8+9 = 110
成功:12+3+45+67-8-9 = 110
成功:12-3+4-5+6+7+89 = 110
成功:1+2+34+5+67-8+9 = 110
成功:1-2+3+45-6+78-9 = 110
成功:123+4-5-6-7-8+9 = 110
成功:123-4+5-6-7+8-9 = 110
成功:123-4-5+6+7-8-9 = 110
成功:123+4+5+67-89 = 110
成功:1+234-56-78+9 = 110

兩種方法:

/**
 * Copyright (C) 2012 Lear C
 */

/**
 * 1 2 3 4 5 6 7 8 9 = 110 
 * <p/> 
 * 在數字間填入加號或者減號(可以不填,但不能填入其它符號)使等式成立。 <br/>
 * 一種更好的方法是:<br/>
 * 每一個空隙之間都有三種可能,"+", "-", "",所以一共有3^8種可能。
 * 
 * @author Lear
 */
public class Tester2 {
	
	private static final char[] NUMBERS = {'1', '2', '3', '4', '5', '6', '7', '8', '9'};  
	private static final String[] OPERATORS = {"+", "-", ""};
    private static final int RESULT = 110;  // 計算結果  

	public static void main(String[] args) {
		sortAndCompute(0, "");
	}

	private static void sortAndCompute(int numIndex, String buffer) {
		// 說明到最後一個字元了
		if(numIndex == NUMBERS.length - 1) {
			buffer += NUMBERS[numIndex];
			String formula = buffer.toString();
			if(sum(formula) == RESULT) {
				System.out.println(formula + " = " + RESULT);
			}
			return;
		}
		
		for(int operIndex = 0; operIndex < OPERATORS.length; ++operIndex) {
			buffer += NUMBERS[numIndex];
			buffer += OPERATORS[operIndex];
			sortAndCompute(numIndex + 1, buffer);
			// 消除前面兩個已經新增的字元恢復原狀,以便下一次迴圈的疊加
			// 但是當中間連線符變為''的時候,則只刪除buffer中的前面一個字元
			buffer = operIndex != 2 ? buffer.substring(0, buffer.length() - 2)
					: buffer.substring(0, buffer.length() - 1);
		}
	}
	
	private static int sum(String formula) {
		if(formula == null || formula.trim().length() == 0)
			throw new IllegalArgumentException("formula is invalid!");
		
		Stack<String> numStack = new Stack<String>();
		Stack<String> operStack = new Stack<String>();
		StringBuffer numBuffer = new StringBuffer();
		
		formula += "#";	// 新增一個結束符到公式末尾便於計算
		char[] chs = formula.toCharArray();
		for(int index = 0; index < formula.length(); ++index) {
			if(chs[index] != '+' && chs[index] != '-' && chs[index] != '#') {
				numBuffer.append(chs[index]);
			} else {
				numStack.push(numBuffer.toString());
				numBuffer.delete(0, numBuffer.length());
				
				if(operStack.isEmpty()) operStack.push(chs[index] + "");
				else {
					int numAft = Integer.parseInt(numStack.pop());
					int numBef = Integer.parseInt(numStack.pop());
					String oper = operStack.pop();
					int sum = oper.equals("+") ? numBef + numAft : numBef - numAft;
					numStack.push(sum + "");
					operStack.push(chs[index] + "");
				}
			}
		}
		return Integer.parseInt(numStack.pop());
	}
}




package test;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
 * 1 2 3 4 5 6 7 8 9 = 110
 * <p/>
 * 在數字間填入加號或者減號(可以不填,但不能填入其它符號)使等式成立。
 * @author Lear
 *
 */
public class Tester {

	private static final char[] NUMBERS = {'1', '2', '3', '4', '5', '6', '7', '8', '9'/**/};
	private static final int RESULT = 110;	// 計算結果
	
	public static void main(String[] args) {
		List<List<String>> all = sort(NUMBERS);
		testPrint(all);
		for(List<String> aRank : all) {
			printEstablishEquation(aRank);
		}
	}
	
	private static void testPrint(List<List<String>> all) {
		for(List<String> aRank : all) {
			System.out.println(aRank);
		}
	}

	/**
	 * 按nums的順序進行排列組合,最後返回一個List陣列,它將包含所有的可能的一個由一列資料的List陣列。
	 * <p/>
	 * 此為一個遞迴函式,第一個的組合數字後面的字元都將繼續呼叫此函式以計算出List<List<String>>.<br/>
	 * 缺點:資料量增大時,將導致記憶體溢位,而且演算法的效率低下
	 * 
	 * @param nums
	 * @return 格式:[[1,2,3,4..],[12,3,4,..],[12,34,...],....]
	 */
	private static List<List<String>> sort(char[] nums) {
		if(nums.length == 0) return Collections.emptyList();
		
		List<List<String>> all = new ArrayList<List<String>>();
		// 字元陣列直接加入此List中
		List<String> firstRank = new ArrayList<String>();
		for(int i = 0; i < nums.length; ++i) {
			firstRank.add(nums[i] + "");
		}
		all.add(firstRank);
		
		// 組合數字的個數,如:1,2,3,4.... ; 12,3,4,5.. ; 123,4,5.. ; 1234.5 ...
		for(int combinationNum = 2; combinationNum <= nums.length; ++combinationNum) {
			// 此組合的偏移量,如:12,3.... ; 1,23,4....; 1,2,34,...
			for(int offset = 0; offset < nums.length - (combinationNum - 1); ++offset) {
				List<String> preRank = new ArrayList<String>();
				StringBuilder buffer = new StringBuilder();
				
				for(int i = 0; i < offset; ++i) {	// 前
					preRank.add(nums[i] + "");
				}
				
				for(int i = offset; i < offset + combinationNum; ++i) {	// 中
					buffer.append(nums[i]);
				}
				preRank.add(buffer.toString());
				
				// 獲取後面的字元陣列,然後遞迴組合
				char[] suffix = new char[nums.length - (offset + combinationNum)];
				for(int i = offset + combinationNum, index = 0; i < nums.length; ++i, ++index) {	// 後
					suffix[index] = nums[i];
				}
				// 例如:12組合的後面 [[3,4,5,6,7...],[34,5,6...],[345...]]
				List<List<String>> sufArray = sort(suffix);
				// 為裡面的所有List<String>新增前面的數字組合,
				// 例如:新增12到上面的例子中,使之成為[[12,3,4,...],[12,34...]....]
				if(sufArray.size() != 0)
					for(List<String> sufRank : sufArray) {
						// 組合前後的List
						List<String> allRank = new ArrayList<String>();
						for(int i = 0; i < preRank.size(); ++i) allRank.add(preRank.get(i));
						for(int i = 0; i < sufRank.size(); ++i) allRank.add(sufRank.get(i));
						// 新增到all中去
						all.add(allRank);
					}
				else
					all.add(preRank);	// 說明到末尾了
			}
		}
		return all;
	}

	private static void printEstablishEquation(List<String> ls) {
		char[] operators = {'+', '-'};
		StringBuilder buff = new StringBuilder();
		
		// 轉換為數字
		int[] nums = new int[ls.size()];
		for(int i = 0; i < ls.size(); ++i) {
			nums[i] = Integer.parseInt(ls.get(i));
		}
		// 對應的操作符是否變化的陣列
		boolean[] isOperChanges = new boolean[nums.length - 1];
		// 計算每一個isOperChange的變化週期
		int[] perOperChangeCounts = new int[isOperChanges.length];
		for(int index = 0; index < isOperChanges.length; ++index) {
			perOperChangeCounts[index] = (int) Math.pow(2, index);
		}
		// 可能性的計算次數 2^(nums.length - 1)
		int computeCount = (int) Math.pow(2, nums.length -1);
		for(int i = 1; i <= computeCount; ++i) {
			// 迭代計算
			int sum = nums[0];
			buff.append(nums[0]);
			for(int index = 0; index < nums.length - 1; ++index) {
				sum = isOperChanges[index] ? sum - nums[index + 1] : sum + nums[index + 1];
				buff.append(isOperChanges[index] ? operators[1] : operators[0]);
				buff.append(nums[index + 1]);
			}
			// 列印
			if(sum == RESULT)	// 輸出等式成立的表示式
				System.out.println("成功:" + buff.toString() + " = " + sum);
//			else
//				System.out.println("失敗:"  + buff.toString() + " = " + sum);
			buff.delete(0, buff.length());
			
			// 操作符交替變化陣列的迭代計算。
			// 第1操作符,每次交替變化;第2操作符,i每 2^2次變化一次;第3操作符,i每2^3次變化一次
			for(int index = 0; index < isOperChanges.length; ++index) {
				if(i % perOperChangeCounts[index] == 0) 
					isOperChanges[index] = !isOperChanges[index];	// 交替
			}
		}
		
	}
}