#objective-c
#objective-c
Вопрос:
Каков наилучший метод генерации всех возможных NSArrays, учитывая, что в NSArray есть только 2 возможных записи (X или Y). Некоторые значения в массиве уже будут назначены перед запуском и не могут быть изменены.
Например, в приведенном здесь массиве 16 возможных перестановок дают, что позиции 1 и 2 уже привязаны к X amp; Y соответственно и не могут быть изменены. Позиция 0 может принимать X или Y, но не может быть пустой. Например, мудрые позиции 3,4,5.
0:[ ]
1:[X]
2:[Y]
3:[ ]
4:[ ]
5:[ ]
[ ] просто обозначает, что этой позиции в массиве ничего не назначено, поэтому при вычислении всех перестановок необходимо назначить либо X, либо Y. Это одномерный массив или размер 6. Я пишу на Objective-C для устройства iOS. Любые рекомендации здесь будут оценены.
Спасибо — C
Комментарии:
1.Я не уверен, что понимаю полупустой. Это C-массив или это NSArray, содержащий экземпляры NSNull? Кроме того, я не понимаю обозначения в вопросе — имеют
[
]
ли смысл квадратные скобки, например, как массив массивов?2. Кроме того, я думаю, вы, вероятно, имеете в виду только перестановки (а не комбинации), потому что вопрос, похоже, заключается в создании разных порядков?
3. Привет @dahn, отредактировал вопрос для уточнения.
Ответ №1:
Я думаю, я понимаю, к чему вы стремитесь: сгенерируйте перестановки из 6 объектов, выбранных из набора длины 2 (@»X» и @»Y»), исключая объекты с заданным шаблоном.
Здесь есть хороший компромисс между скоростью и пространством, потому что существует только 64 перестановки из 6 объектов, выбранных из набора длины 2. Полный набор достаточно мал, чтобы его можно было вычислить заранее и держать под рукой. При этом алгоритм оказывается простым фильтром по шаблону «фиксированных» позиций.
Нам нужен способ представления этого шаблона. NSArrays не являются позиционными, как массивы C. Массив с числом 6 должен содержать объект с каждым индексом 1 ..5, поэтому простой подход заключается в выборе другого объекта для представления «нефиксированных» позиций (операционный эквивалент «[ ]»).). Например, если мы используем @"*"
, ( NSNull
экземпляры тоже являются достойным выбором), шаблон, исключенный из операции, будет выглядеть следующим образом:
@[ @"*", @"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 resu<
} 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 resu<
}
}
Это приведет к таким перестановкам, как…
@[ @[ @"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:@"*"] amp;amp; ![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 и несколькими вариантами.
Комментарии:
1. Привет, Дань, так вот как это работает. Он создает все возможные перестановки массива, а затем удаляет все перестановки, которые не соответствуют have и X в позиции массива 1 и Y в позиции массива 2? Итак, у вас осталось подмножество массивов нужных вам перестановок?
2. ДА. Это то, что я понимаю из вопроса, и что дает ответ.
3. Почему вы используете
allObjects
?4. О, я забыл, что вы можете быстро перечислить набор напрямую. Я думаю, вы можете это опустить. я не рядом с компьютером для тестирования, но я уверен, что это правильно.