3

Does anyone know of an existing way to change the order of an existing NSString or NSMutableString's characters? I have a workaround in mind anyway but it would be great if there was an existing method for it.

For example, given the string @"HORSE", a method which would return @"ORSEH", @"SORHE", @"ROHES", etc?

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
Bob-ob
  • 1,560
  • 4
  • 18
  • 34

2 Answers2

5

Consider this code:
.h File:

@interface NSString (Scrambling)

+ (NSString *)scrambleString:(NSString *)toScramble;

@end

.m File:

@implementation NSString (Scrambling)

+ (NSString *)scrambleString:(NSString *)toScramble {
   for (int i = 0; i < [toScramble length] * 15; i ++) {
      int pos = arc4random() % [toScramble length];
      int pos2 = arc4random() % ([toScramble length] - 1);
      char ch = [toScramble characterAtIndex:pos];
      NSString *before = [toScramble substringToIndex:pos];
      NSString *after = [toScramble substringFromIndex:pos + 1];
      NSString *temp = [before stringByAppendingString:after];
      before = [temp substringToIndex:pos2];
      after = [temp substringFromIndex:pos2];
      toScramble = [before stringByAppendingFormat:@"%c%@", ch, after];
   }
   return toScramble;
}

@end

Not the most beautiful code or execution, but gets the job done. There's probably a (const char *) way to do this, but this works fine for me. A quick test shows a 0.001021 second length for execution on my Mac.

Usage:

NSString *scrambled = [NSString scrambleString:otherString];

Code adapted from another language / pseudocode

Glenn Smith
  • 912
  • 1
  • 17
  • 37
  • arc4random_uniform(maxIntIndex) is a better random number generator if you're running the code on 10.7 or iOS 4.3+. arc4random() is still good though if you need to support anything older. – Jack Lawrence Jan 26 '12 at 00:35
  • 1
    Ah, as I was compiling for 10.5, it did not appear in the "suggestions" menu. Good to know. – Glenn Smith Jan 26 '12 at 00:37
  • @HiGuy'CouleeApps'Smith thanks for your comment, I am having an issue with getting it to work though: **Semantic Issue: Class method '+scrambleString:' not found (return type defaults to 'id')** Any idea how I can fix it? I've placed it in header and implementation files – Bob-ob Jan 29 '12 at 21:10
  • That means it cannot find the method. Make sure you #import-ed the .h file and that the method is specified in the .h under "@interface NSString (Scrambling)" – Glenn Smith Jan 29 '12 at 23:21
  • 1
    To make this work better, with more characters, replace the `%c` with `%C` and change the type of `ch` to `unichar` (which is the return type of `characterAtIndex:`). – rmaddy Sep 01 '13 at 22:44
  • Is this a category or a class extension? I am noob. – temporary_user_name Dec 03 '14 at 00:38
3

You can use Durstenfeld's variation of the Fisher-Yates Shuffle.

For a very long string, you could save a lot of CPU time and allocations by copying the unichars to a unichar buffer, then performing the transform using a c or c++ approach to swap characters. Note that the UTF8String is not the buffer you want to take, nor should you mutate it. Then create (or set) a new NSString from the shuffled buffer.

More info on the Fisher Yates algo and C and C++ implementations can be found here.

Community
  • 1
  • 1
justin
  • 104,054
  • 14
  • 179
  • 226