生成半填充阵列的所有可能的排列/组合

时间:2016-10-01 12:52:18

标签: objective-c

生成所有可能的NSArray的最佳方法是什么,因为NSArray中只有2个可能的条目(X或Y)。在开始之前已经分配了数组中的某些值,并且无法更改。

例如,此处的数组具有16种可能的排列,使得位置1和2已经锁定到X& Y分别不能改变。位置0可以采用X或Y,但不能为空。像明智的职位3,4,5。

0:[ ] 1:[X] 2:[Y] 3:[ ] 4:[ ] 5:[ ]

[]表示没有分配给数组中该位置的任何内容,因此在计算所有排列时需要分配X或Y.它是单维数组或大小6。 我在Objective-C中为iOS设备编码。这里的任何指导将不胜感激。

谢谢 - C

1 个答案:

答案 0 :(得分:0)

我想我明白你的目的:产生从一组长度为2(@“X”和“Y”)中选出的6个对象的排列,排除那些具有给定模式的对象。

这里有一个很好的速度/空间权衡,因为从一组长度2中选择的6个对象只有64个排列。整个集合足够小,可以提前计算并保存在手边。有了这个,算法就变成了对“固定”位置模式的简单过滤。

我们需要一种方法来表示这种模式。 NSArrays不像C数组那样定位。计数数组6必须在每个索引1..5处包含一个对象,因此一个简单的方法是选择另一个对象来表示“未固定”位置,(OP相当于“[]”)。例如,如果我们使用@"*",(NSNull个实例也是一个不错的选择),OP排除的模式看起来就像这个文字:

 @[ @"*", @"X", @"Y", @"*", @"*", @"*" ]

让我们从完整的排列开始。懒惰地计算这些(在第一次调用时计算和缓存,然后返回缓存的结果):

@property(strong,nonatomic) NSArray *permutations;

- (NSArray *)permutations {
    if (!_permutations) {
        NSSet *set = [NSSet setWithArray:@[ @"X", @"Y"]];
        _permutations = [self permute:set count:6];
    }
    return _permutations;
}

// simple recursive algorithm to permute
- (NSArray *)permute:(NSSet *)set count:(NSInteger)count {
    NSMutableArray *result = [@[] mutableCopy];
    if (count == 1) {
        for (id object in [set allObjects]) [result addObject:@[object]];
        return result;
    } else {
        NSArray *smaller = [self permute:set count:count-1];
        for (id object in [set allObjects]) {
            for (NSArray *array in smaller) {
                NSMutableArray *m = [array mutableCopy];
                [m insertObject:object atIndex:0];
                [result addObject:m];
            }
        }
        return  result;
    }
}

这将产生类似......的排列。

@[ @[ @"X", @"X", @"X", @"X", @"X", @"X" ],
   @[ @"X", @"X", @"X", @"X", @"X", @"Y" ], // ... and so on

您甚至可以在编译时执行此操作,并将该结果作为64元素数组文字包含在您的应用中。

有了这个,问题就变成了过滤器。这是测试给定数组是否匹配模式(使用@“*”作为外卡)的测试:

- (BOOL)array:(NSArray *)array matchesPattern:(NSArray *)pattern {
    for (NSInteger i=0; i<array.count; i++) {
        if (![pattern[i] isEqualToString:@"*"] && ![array[i] isEqualToString:pattern[i]]) return NO;
    }
    return YES;
}

将该过滤器应用为谓词:

NSArray *pattern =@[ @"*", @"X", @"Y", @"*", @"*", @"*" ];
NSPredicate *predicate = [NSPredicate predicateWithBlock:^BOOL(id evaluatedObject, NSDictionary * bindings) {
    NSArray *a = (NSArray *)evaluatedObject;
    return [self array:a matchesPattern:pattern];
}];

并进行过滤:

NSArray *permutations = [self permutations];
NSArray *result = [permutations filteredArrayUsingPredicate:predicate];

我用OP参数和一些变化进行了测试。