-
-
Save jonathanpenn/4612637 to your computer and use it in GitHub Desktop.
@implementation SomeGenerater | |
- (NSArray *)generateAThousandRandomStrings | |
{ | |
NSMutableArray *strings = [[NSMutableArray alloc] initWithCapacity:1000]; | |
for (int count = 0; count < 1000; count++) { | |
int length = arc4random_uniform(10) + 4; | |
unichar buf[length]; | |
for (int idx = 0; idx < length; idx++) { | |
buf[idx] = (unichar)('a' + arc4random_uniform(26)); | |
} | |
[strings addObject:[NSString stringWithCharacters:buf length:length]]; | |
} | |
return strings; | |
} | |
@end |
- (NSArray *)generateAThousandRandomStrings
{
NSRange ranges[1000];
int totalLength = 0;
for (int i = 0; i < 1000; i++) {
int length = 4 + arc4random_uniform(10);
ranges[i] = NSMakeRange(totalLength, length);
totalLength += length;
}
int const len = totalLength + 1;
char bytes[len];
for (int i = 0; i < totalLength; i++) {
bytes[i] = 'a' + arc4random_uniform(26);
}
bytes[totalLength] = '\0';
// I *think* this will copy out of bytes.
NSString *string = [NSString stringWithCString:bytes encoding:NSASCIIStringEncoding];
NSMutableArray *substrings = [NSMutableArray arrayWithCapacity:1000];
for (int i = 0; i < 1000; i++) {
// I *think* this will reuse the backing store of the string for all the substrings.
[substrings addObject:[string substringWithRange:ranges[i]]];
}
return substrings;
}
And then I saw your comment about speed not mattering… but this is more about storage :)
Here's what I came up with. Not purer, but definitely funner. Based on the fact that the count of each length should be pretty close.
- (NSArray *)generateAThousandStrings
{
int characters_per_cycle = 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13;
int total_characters = 10*characters_per_cycle;
NSMutableString *data = [[NSMutableString alloc] initWithCapacity:1000 + total_characters];
for (int i = 0; i < total_characters; ++i) {
[data appendFormat:@"%c", arc4random_uniform(26) + 'a'];
switch (i%characters_per_cycle) {
case 4-1:
case 4+5-1:
case 4+5+6-1:
case 4+5+6+7-1:
case 4+5+6+7+8-1:
case 4+5+6+7+8+9-1:
case 4+5+6+7+8+9+10-1:
case 4+5+6+7+8+9+10+11-1:
case 4+5+6+7+8+9+10+11+12-1:
case 4+5+6+7+8+9+10+11+12+13-1:
[string appendString:@"/"];
}
}
return [data componentsSeparatedByString:@"/"];
}
FWIW here's the array-of-unichar code I tested with:
NSTimeInterval timeBefore = [NSDate timeIntervalSinceReferenceDate];
NSMutableArray *strings = [[NSMutableArray alloc] initWithCapacity:1000];
for (NSUInteger count = 0; count < 1000; count++)
{
NSUInteger length = arc4random_uniform(10) + 4;
unichar buf[length];
for (NSUInteger idx = 0; idx < length; idx++)
{
buf[idx] = (unichar)('a' + arc4random_uniform(26));
}
[strings addObject:[NSString stringWithCharacters:buf length:length]];
}
NSTimeInterval timeAfter = [NSDate timeIntervalSinceReferenceDate];
NSLog(@"time 1: %f", (timeAfter - timeBefore));
@kconner ha! If I was going for speed I might even try to use malloc()
instead. :) I'm going for purity more as part of an exercise in readable, idiomatic Objective C. The speed and memory concerns didn't matter. I just didn't want to bog down the reader of the example with extra stuff.
@aglee, this is MUCH better! It's just enough C that it won't detract from the larger concept I'm trying to get at. I think I'm going with this.
Shortest solution:
t(a,b) { return arc4random_uniform(a)+b; }
- (NSArray *)generateAThousandStrings
{
NSMutableString *data = [[NSMutableString alloc] initWithCapacity:1000*15];
for (int i = 1000, e = t(10,5); i || e; --e || --i)
[data appendFormat:@"%c", e ? t(26,'a') : (e = t(10,5), '/')];
return [data componentsSeparatedByString:@"/"];
}
@eraserhd you have proven yourself with this one. :)
@jonathanpenn There, I extracted a function. Shorter now. :)
I was going to suggest using an array of unichar, along with stringWithCharacters:length:, but it's no "purer" than your approach, and the speed difference in my test was like 0.003 seconds, and besides you said speed doesn't matter.