为了好玩,我决定写一个简单的程序来解决《10只猫中有8只做倒数计算》数字谜题,链接来自于Countdown节目的这里,但规则相同。我的程序简单地遍历AxBxCxDxExF的所有可能组合,其中字母代表数字,“x”代表加、减、除和乘法。以下是代码:
private void combineRecursive( int step, int[] numbers, int[] operations, int combination[]){
if( step%2==0){//even steps are numbers
for( int i=0; i<numbers.length; i++){
combination[ step] = numbers[ i];
if(step==10){//last step, all 6 numbers and 5 operations are placed
int index = Solution.isSolutionCorrect( combination, targetSolution);
if( index>=0){
solutionQueue.addLast( new Solution( combination, index));
}
return;
}
combineRecursive( step+1, removeIndex( i, numbers), operations, combination);
}
}else{//odd steps are operations
for( int i=0; i<operations.length; i++){
combination[ step] = operations[ i];
combineRecursive( step+1, numbers, operations, combination);
}
}
}
这是我用来测试组合是否符合要求的方法。
public static int isSolutionCorrect( int[] combination, int targetSolution){
double result = combination[0];
//just a test
if( Arrays.equals( combination, new int[]{100,'*',7,'-',8,'*',3,'+',7,'+',50})){
System.out.println( "found");
}
for( int i=1; i<combination.length; i++){
if(i%2!=0){
switch( (char)combination[i]){
case '+': result+= combination[++i];break;
case '-': result-= combination[++i];break;
case '*': result*= combination[++i];break;
case '/': result/= combination[++i];break;
}
}
if( targetSolution==result){
return i;
}
}
return targetSolution==result?0:-1;
}
在上一集中,我发现了我的代码中存在的一个问题。这是其中一个谜题的解决方案。
(10*7)-(8*(3+7))
我注意到我找到了这个组合"10*7-8*3+7"(两次),但是因为我从左向右进行运算来查找解决方案,实际上我并没有找到所有的答案。我只检查这样的解决方案((((10*7)-8)*3)+7)。所以即使我找到了这个组合,我也没有正确的顺序。现在的问题是如何测试所有可能的数学顺序,例如(10*7)-(8*(3+7)), (10*7)-((8*3)+7)或10*(7-8)*(3+7)? 我想可以使用操作作为平衡节点的平衡树,但仍然不知道如何通过不移动公式来遍历所有可能的组合。
(10*7)-(8*(3+7))
-
/ \
* *
/ \ / \
700 7 8 +
/ \
7 3
(10*7)-((8*3)+7)
-
/ \
* +
/ \ / \
700 7 * 7
/ \
8 3
10*(7-8)*(3+7)
*
/ \
*
/ \ 10
- +
/ \ / \
7 8 3 7
我应该如何在代码中实现这个?我不是在寻找解决方案,而是想了解如何改变思路来解决问题。我不知道为什么我会卡在这个问题上。
关于我:我是计算机科学专业的四年级学生,在编程方面并不是新手(至少我愿意这样认为 ;))