24点游戏是一种益智游戏,24点是把4个整数(一般是正整数)通过加减乘除以及括号运算,使最后的计算结果是24的一个数学游戏. 平时我也经常这样玩这个游戏,经常是在算出一个结果之后就结束了,后来就在想, 有的题目结果只有一个 ,但是大部分的结果通常是不止一个, 怎么列出所有的解呢, 在用脑子算 肯定是不全的 , 那就试试穷举法吧.
穷举法,思路上比较简单,
先把所有可能的数字组合列出来, 4*3*2*1总共有24种,
在处理符号的, 由于符号有优先级和括号,如果考虑括号的情况就比较多了,没有括号,1个括号,2个括号的情况.所以就不太想处理括号,所以对所有的符号进行全排列,然后按照排列顺序处理,不考虑符号间的优先级. 加减乘除,总共需要3个符号, 4*4*4有64种组合.
当然这是最初的想法, 回来在写测试用例的时候,发现了一种情况6,11,10,12 , 这种只有10/(11-6)*12, 这种必须有括号, 但是我又不想加括号, 就又加入了一种符号, 注意了10除以5是10/5 , 但是10除5 是5/10, 有了这种符号就可以处理这种情况了. 所以符号的全排列是 5*5*5=125种,
现在用24种数组组合和125种符号组合,相互叠加处理, 算出来的就是所有可能的解了.
还有一个, 用oc简单的封装了一个栈的数据结构
#import <Foundation/Foundation.h>
@interface Stack : NSObject<NSCopying>
@property (nonatomic,readonly,assign) NSUInteger count ;
- (void)push:(id)obj;
- (id)pop;
@end
------------------------
#import "Stack.h"
@interface Stack ()
@property (nonatomic,strong) NSMutableArray * array ;
@end
@implementation Stack
- (NSUInteger)count {
return self.array.count;
}
- (void)push:(id)obj {
[self.array addObject:obj];
}
- (id)pop {
id obj = self.array.lastObject ;
[self.array removeLastObject];
return obj;
}
- (NSMutableArray *)array {
if (_array == nil) {
_array = [NSMutableArray array];
}
return _array;
}
- (NSString *)description {
NSMutableString * str = [[NSMutableString alloc] init];
for (int i = self.array.count-1; i>=0; i--) {
[str appendFormat:@"%@ ", self.array[i]];
}
return str;
}
- (id)copyWithZone:(nullable NSZone *)zone {
Stack * newStack = [Stack new];
newStack.array = [self.array mutableCopy];
return newStack;
}
@end
算法的主体部分
#import "ViewController.h"
#import "Stack.h"
@interface ViewController ()
@property (nonatomic,strong) NSMutableArray * resultArray ;
@end
@implementation ViewController
- (void)test {
// int a[4] = {6,11,10,12};
int a[4] = {3,4,5,5};
NSArray * nums = [self getNums:a];
for (int i = 0; i<nums.count; i++) {
Stack * numStack = nums[i];
NSArray * symbolArray = [self getSymbol];
for (int j = 0; j<symbolArray.count; j++) {
Stack * symbolStack = symbolArray[j];
[self jiSuan:numStack withSymbolStack:symbolStack];
}
}
NSLog(@"%@",self.resultArray);
}
- (double)jiSuan:(Stack *)numStack withSymbolStack:(Stack *)symbolStack {
Stack * nums = [numStack copy];
Stack * symbols = [symbolStack copy];
while (nums.count>1) {
double firstNum = [[nums pop] doubleValue];
double secondtNum = [[nums pop] doubleValue];
NSString * symbol = [symbols pop];
if ([symbol isEqualToString:@"+"]) {
[nums push:@(firstNum + secondtNum)];
} else if ([symbol isEqualToString:@"-"]){
[nums push:@(firstNum - secondtNum)];
} else if ([symbol isEqualToString:@"*"]){
[nums push:@(firstNum * secondtNum)];
} else if ([symbol isEqualToString:@"/"]){
[nums push:@(firstNum / secondtNum)];
} else if ([symbol isEqualToString:@"#"]){
[nums push:@(secondtNum / firstNum)];
}
}
double result = [[nums pop] doubleValue];
NSLog(@"%@ %@ = %@",numStack,symbolStack,@(result));
if (result == 24) {
[self.resultArray addObject:[NSString stringWithFormat:@"%@ %@",numStack,symbolStack]];
}
return result;
}
/// 返回数字的全排列
- (NSArray *)getNums:(int *)a{
NSMutableArray * result = [NSMutableArray array];
for (int i=0; i<4; i++) {
for (int j=0; j<4; j++) {
if (i==j) {
continue;
}
for (int k = 0; k<4; k++) {
if (j==k || i==k) {
continue;
}
for (int m=0; m<4; m++) {
if (k==m || i==m | j==m) {
continue;
}
// 如果i,j,k,m4个数字各不相等,说明是一种组合,记录下来
NSLog(@"%d %d %d %d",a[i],a[j],a[k],a[m]);
Stack * stack = [Stack new];
[stack push:@(a[i])];
[stack push:@(a[j])];
[stack push:@(a[k])];
[stack push:@(a[m])];
[result addObject:stack];
}
}
}
}
return result;
}
/// 获取符号的全排列
- (NSArray *)getSymbol {
NSMutableArray * result = [NSMutableArray array];
// 加减乘除,最后一个是取倒数相乘
NSArray * array = @[@"+",@"-",@"*",@"/",@"#"];
for (int i=0; i<array.count; i++) {
for (int j=0; j<array.count; j++) {
for (int k = 0; k<array.count; k++) {
NSLog(@"%@ %@ %@",array[i],array[j],array[k]);
Stack * stack = [Stack new];
[stack push:array[i]];
[stack push:array[j]];
[stack push:array[k]];
[result addObject:stack];
}
}
}
return result;
}
- (NSMutableArray *)resultArray {
if (_resultArray == nil) {
_resultArray = [NSMutableArray array];
}
return _resultArray;
}
@end