Re: NSString, scramble
Re: NSString, scramble
- Subject: Re: NSString, scramble
- From: Fritz Anderson <email@hidden>
- Date: Sun, 1 Jul 2001 09:45:58 -0500
At 2:38 PM +0200 7/1/2001, Michel M.J. Haver wrote:
I want to read a couple of string and then scramble the strings by mixing
the characters in the strings to new ad random positions.
Problem Description by Example
I want to convert a string like for example "heart" to "retah"
or the next time you run the program the example string "heart" will be
converted in an other random scramble string like "tarhe".
How I can implement such a random string scramble functionality with the
cocoa objects NSString, NSMutableString is something of a riddle to me which
I am working to find out.
Does someone has some tips for solving this riddle?
A solution appears at the end of this message. It is the complete
source for a Foundation tool that makes an anagram of each argument
passed to the tool.
I prefer to do it in Cocoa or is it should this kind of string manipulation
be done in C or C++?
That's a separate question. The NSString solution works for any
Unicode string, and handles dynamic-memory issues in a
guaranteed-safe fashion. If called repeatedly, the overhead of
dynamic allocation (I'm thinking particularly of the single-unichar
substrings) would become a performance problem. In the unlikely
event makeAnagram is called a huge number of times without releasing
the current autorelease pool, there would be a memory problem (which,
under Mac OS X, shows up first as a performance problem).
The memory problem could be lessened by allocating an
NSAutoreleasePool before the huge number of calls to makeAnagram, and
periodically releasing and reallocating it.
You could improve performance inside makeAnagram by calling [self
getCharacters:] to get a copy of the string's characters in a C array
of unichar, scrambling the array, and then passing the array to
[NSString stringWithCharacters: length:] to produce the returned
string. With this approach, my [swapCharacterAtIndex: withIndex:] is
unnecessary, and [makeAnagram] can return NSString *.
I didn't do this because (1) the "more efficient" way only just
occurred to me; and (2) my example does have the advantage of being a
close translation of your own.
Absolutely ruthless optimization might drive you to give up Unicode
support and work directly with ASCII C strings.
-- F
#import <Foundation/Foundation.h>
#import <stdlib.h>
#import <time.h>
unsigned randRange(unsigned lowIncluded, unsigned highExcluded);
// Return an unsigned integer in the range [low .. high)
inline
unsigned randRange(unsigned lowIncluded,
unsigned highExcluded)
{
return lowIncluded + ((unsigned) random()) % (highExcluded - lowIncluded);
}
@interface NSMutableString (Anagrams)
- (void) swapCharacterAtIndex: (unsigned) indexOne
withIndex: (unsigned) indexTwo;
@end
@interface NSString (Anagrams)
- (NSMutableString *) makeAnagram;
@end
@implementation NSMutableString (Anagrams)
- (void) swapCharacterAtIndex: (unsigned) indexOne
withIndex: (unsigned) indexTwo
{
unichar firstCharacter = [self characterAtIndex: indexOne],
secondCharacter = [self characterAtIndex: indexTwo];
NSString * firstString = [NSString stringWithCharacters: &firstCharacter
length: 1];
NSString * secondString = [NSString stringWithCharacters: &secondCharacter
length: 1];
[self replaceCharactersInRange: NSMakeRange(indexOne, 1)
withString: secondString];
[self replaceCharactersInRange: NSMakeRange(indexTwo, 1)
withString: firstString];
}
@end
@implementation NSString (Anagrams)
- (NSMutableString *) makeAnagram
{
NSMutableString * retval = [self mutableCopy];
unsigned i;
for (i = 0; i < [self length]; i++) {
[retval swapCharacterAtIndex: i withIndex: randRange(0, [self
length])];
}
return [retval autorelease];
}
@end
int main (int argc, const char * argv[])
{
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
NSArray * arguments = [[NSProcessInfo processInfo] arguments];
int i;
// Seed the random number generator
srandom(time(NULL));
for (i = 1; i < [arguments count]; i++) {
NSString * fromString = [arguments objectAtIndex: i];
NSString * anagram = [fromString makeAnagram];
printf("%s\n", [anagram cString]);
}
[pool release];
return 0;
}
--
Fritz Anderson <email@hidden>
Parallel Software, Inc <
http://www.parallel.com/>
Naperville, Illinois