#import <Foundation/Foundation.h>
//This function takes an array and a string to look up in it. It will iterate through the array and return true (and exit quickly) if found.
BOOL stringInArray( NSArray *stringArray, NSString *s ){
for (NSString *arrayString in stringArray){
if ([arrayString caseInsensitiveCompare:s] != NSOrderedSame) {
return TRUE;
}
}
//Will never get here if it returns true
return FALSE;
}
int main(int argc, const char * argv[])
{
@autoreleasepool {
//Load up propernames
NSString *nameString = [NSString stringWithContentsOfFile:@"/usr/share/dict/propernames" encoding:NSUTF8StringEncoding error:NULL];
//load up words list
NSString *wordString = [NSString stringWithContentsOfFile:@"/usr/share/dict/words" encoding:NSUTF8StringEncoding error:NULL];
//Break into arrays
NSArray *names = [nameString componentsSeparatedByString:@"\n"];
NSArray *words = [wordString componentsSeparatedByString:@"\n"];
//Init counter (just for output reasons)
int matchesCounter = 0;
//go through one string at a time
for (NSString *n in names) {
//Call function above to see if it is in the words array
if ( stringInArray(words, n) ) {
matchesCounter++;
NSLog(@"%i %@", matchesCounter, n);
}
}
}
return 0;
}
I felt that creating a function makes the code easy to read and simplistic.
Your solution doesn’t actually work. When I run it, it returns 1,309 matches which is how many names are in the names array. Realistically it should be returning around 293 matches out of the 1,309 names.
I thought your solution was promising because it ran pretty quickly, however when I updated it to do a case-sensitive compare against a lowercase name it took over 10 seconds to run, which is how long it took to run my own program. I’m trying to come up with a more efficient solution, any ideas?
// Get the contents of the names and words files
NSString *nameString = [NSString stringWithContentsOfFile:@"/usr/share/dict/propernames"
encoding:NSUTF8StringEncoding
error:NULL];
NSString *wordString = [NSString stringWithContentsOfFile:@"/usr/share/dict/words"
encoding:NSUTF8StringEncoding
error:NULL];
// Split all of the words and names into an array
NSArray *names = [nameString componentsSeparatedByString:@"\n"];
NSArray *words = [wordString componentsSeparatedByString:@"\n"];
int matchCounter = 0;
// Iterate over the names and search for them in the words array
for (NSString *n in names) {
// If a match is found, output it to the console and increment the counter
if ([words indexOfObject:[n lowercaseString]] != NSNotFound && [n length] > 0) {
NSLog(@"%i %@", ++matchCounter, n);
}
}
NSDate *endTime = [[NSDate alloc] init];
NSLog(@"There were %i matches out of the %lu possibilities in %.2f seconds.",
matchCounter, [names count], [endTime timeIntervalSinceDate:startTime]);
}
return 0;
This way provides the fastest solution possible… It requires the lists to be sorted, which they are, so in theory, theres no reason to search through the prior results. Ive done routines like this is the past in other languages and always sort first.
The function now takes a startAT parameter which is passed back to main by reference, and can pick up where you left off in the words list. See comments in code for details
#import <Foundation/Foundation.h>
//This function takes an array and a string to look up in it. It will iterate through the array and return true (and exit quickly) if found. It also incorperates a startAT parameter that allws you to start at a certain point in the array
BOOL stringInArray( NSArray *stringArray, NSString *s, int *startAt ){
for (int i = *startAt; i <= stringArray.count-1; i++ ){
if ([stringArray[i] compare:s options:NSCaseInsensitiveSearch] == NSOrderedSame) {
*startAt = i;
if ( i+1 == stringArray.count )
break;
if ([stringArray[i+1] caseInsensitiveCompare:s] == NSOrderedSame)
{
if([stringArray[i+1] isEqualToString:s] == FALSE)
return TRUE;
else
return FALSE;
}
return FALSE;
}
}
//Will never get here if it returns true
return FALSE;
}
int main(int argc, const char * argv[])
{
@autoreleasepool {
//Load up propernames
NSString *nameString = [NSString stringWithContentsOfFile:@"/usr/share/dict/propernames" encoding:NSUTF8StringEncoding error:NULL];
//load up words list
NSString *wordString = [NSString stringWithContentsOfFile:@"/usr/share/dict/words" encoding:NSUTF8StringEncoding error:NULL];
//Break into arrays
NSArray *names = [nameString componentsSeparatedByString:@"\n"];
NSArray *words = [wordString componentsSeparatedByString:@"\n"];
//Init counter (just for output reasons)
int matchesCounter = 0;
//Since list is sorted, Only continue on iterating through words list by picking up where you left off last.
//stringInArray passes back the last search position by reference through the startAT parameter
int startRange = 0;
//go through one string at a time
for (NSString *n in names) {
//Call function above to see if it is in the words array
if ( stringInArray(words, n, &startRange) ) {
matchesCounter++;
NSLog(@"%i %@", matchesCounter, n);
}
}
}
return 0;
}