A completely different approach that is fast


#1

So this probably isn’t strictly the correct answer to the challenge as it doesn’t use the methods we have just learnt (or been shown), but it is FAST. Isn’t that the point of programming? :sunglasses:

Tell me what you all think? The one downside is the resulting array is not sorted, but that was not a requirement so I am ignoring that :slight_smile:

[code]#import <Foundation/Foundation.h>

int main(int argc, const char * argv[])
{

@autoreleasepool

{
    NSDate *startTime = [[NSDate alloc] init];  //Records when the program starts
    
    //read in the propernames file as a huge string (ignoring the possibility of an error)
    NSString *nameString = [NSString stringWithContentsOfFile:@"/usr/share/dict/propernames"
                                                     encoding:NSUTF8StringEncoding
                                                        error:NULL];
    
    //convert the uppercase to lowercase in the propernames data
    
    NSString *nameLowerString = [nameString lowercaseString];
    
    //remove the pesky last \n at the end of the string but do it in a way that checks if there are no characters to delete (to prevent a crash) and if there are no characters to log an error to the console
    
    if ([nameLowerString length] > 0)
    {
        NSString *nameLowerStringTrimmed = [nameLowerString substringToIndex:[nameLowerString length] - 1];
        
        //Turn the propernames string into an array
        
        NSArray *nameArray = [nameLowerStringTrimmed componentsSeparatedByString:@"\n"];
        
        //read in the words file as a huge string (ignoring the possibility of an error)
        NSString *wordString = [NSString stringWithContentsOfFile:@"/usr/share/dict/words"
                                                         encoding:NSUTF8StringEncoding
                                                            error:NULL];
        
        //Turn the words string into an array
        
        NSArray *wordArray = [wordString componentsSeparatedByString:@"\n"];
        
        //Use NSMutableSet to find the intersection between the two Arrays
        
        NSMutableSet *matchSet = [NSMutableSet setWithArray:nameArray];
        [matchSet intersectSet:[NSSet setWithArray:wordArray]];
        
        //Turn the results back into an Array
        
        NSArray *matchArray = [matchSet allObjects];
        
        //Log the number of matches and the contents of the Array to the console
        
        for (NSString *item in matchArray)
        {
            NSLog(@"%@", item);
        }
        NSLog(@"There are %lu matches", [matchArray count]);
    }
    else
    {
        
        NSLog(@"There were no characters in the original file");  //This output is shown if there are no characters to delete.  Which in this example is not the case
    }
    NSDate *endTime = [[NSDate alloc] init]; //Records when the program is almost finished
    NSLog(@"This took %.2f seconds to run", [endTime timeIntervalSinceDate:startTime]); //Logs the amount of time elapsed
}
return 0;

}

[/code]

The other thing I noticed is that everyone else has logged the matches to the console as they found them, I didn’t initially do this which is why I added the extra loop to display the contents of the array that contains the matches.


#2

I also created a version of this challenge that used the methods we have been taught and shown. Again I would appreciate any comments/thoughts.

[code]#import <Foundation/Foundation.h>

int main(int argc, const char * argv[])
{

@autoreleasepool

{
    NSDate *startTime = [[NSDate alloc] init];  //Records when the program starts
    
    //read in the propernames file as a huge string (ignoring the possibility of an error)
    NSString *nameString = [NSString stringWithContentsOfFile:@"/usr/share/dict/propernames"
                                                     encoding:NSUTF8StringEncoding
                                                        error:NULL];
    
    //convert the uppercase to lowercase in the propernames data
    
    NSString *nameLowerString = [nameString lowercaseString];
    
    //remove the pesky last \n at the end of the string but do it in a way that checks if there are no characters to delete (to prevent a crash) and if there aren't log an error to the console
    
    if ([nameLowerString length] > 0)
    {
        NSString *nameLowerStringTrimmed = [nameLowerString substringToIndex:[nameLowerString length] - 1];
        
        //Turn the propernames string into an array
        
        NSArray *nameArray = [nameLowerStringTrimmed componentsSeparatedByString:@"\n"];
        
        //read in the words file as a huge string (ignoring the possibility of an error)
        NSString *wordString = [NSString stringWithContentsOfFile:@"/usr/share/dict/words"
                                                         encoding:NSUTF8StringEncoding
                                                            error:NULL];
        
        //Turn the words string into an array
        
        NSArray *wordArray = [wordString componentsSeparatedByString:@"\n"];
        
        //Create an array to place the matches in
        
        NSMutableArray *matchArray = [[NSMutableArray alloc]init];
        
        //Go through the words array one word at a time
        for (NSString *w in wordArray)
        {
            //Go through the names array one name at a time
            for (NSString *n in nameArray)
            {
                if ([n isEqualToString:w]) //Is there a match?
                {
                     [matchArray addObject:w]; //Add the match to the array
                }
            }
        }
        
        //Log the number of matches and the contents of the Array to the console
        
        for (NSString *item in matchArray)
        {
            NSLog(@"%@", item);
        }
        NSLog(@"There are %lu matches", [matchArray count]);
    }
    else
    {
        
        NSLog(@"There were no characters in the original file");  //This output is shown if there are no characters to delete.
    }
    NSDate *endTime = [[NSDate alloc] init]; //Records when the program is almost finished
    NSLog(@"This took %.2f seconds to run", [endTime timeIntervalSinceDate:startTime]); //Logs the amount of time elapsed
    
}
return 0;

}
[/code]

One other thing I noticed when looking at other peoples results was the apparent importance of creating the ‘inner’ and ‘outer’ loops with the correct arrays to search through. I reversed my loops and didn’t notice a massive difference in speed? This is my third version with the loops reversed…

[code]#import <Foundation/Foundation.h>

int main(int argc, const char * argv[])
{

@autoreleasepool

{
    NSDate *startTime = [[NSDate alloc] init];  //Records when the program starts
    
    //read in the propernames file as a huge string (ignoring the possibility of an error)
    NSString *nameString = [NSString stringWithContentsOfFile:@"/usr/share/dict/propernames"
                                                     encoding:NSUTF8StringEncoding
                                                        error:NULL];
    
    //convert the uppercase to lowercase in the propernames data
    
    NSString *nameLowerString = [nameString lowercaseString];
    
    //remove the pesky last \n at the end of the string but do it in a way that checks if there are no characters to delete (to prevent a crash) and if there aren't log an error to the console
    
    if ([nameLowerString length] > 0)
    {
        NSString *nameLowerStringTrimmed = [nameLowerString substringToIndex:[nameLowerString length] - 1];
        
        //Turn the propernames string into an array
        
        NSArray *nameArray = [nameLowerStringTrimmed componentsSeparatedByString:@"\n"];
        
        //read in the words file as a huge string (ignoring the possibility of an error)
        NSString *wordString = [NSString stringWithContentsOfFile:@"/usr/share/dict/words"
                                                         encoding:NSUTF8StringEncoding
                                                            error:NULL];
        
        //Turn the words string into an array
        
        NSArray *wordArray = [wordString componentsSeparatedByString:@"\n"];
        
        //Create an array to place the matches in
        
        NSMutableArray *matchArray = [[NSMutableArray alloc]init];
        
        //Go through the names array one name at a time
        for (NSString *n in nameArray)
        {
            //Go through the words array one word at a time
            for (NSString *w in wordArray)
            {
                if ([n isEqualToString:w]) //Is there a match?
                {
                    [matchArray addObject:n]; //Add the match to the array
                }
            }
        }
        
        //Log the number of matches and the contents of the Array to the console
        
        for (NSString *item in matchArray)
        {
            NSLog(@"%@", item);
        }
        NSLog(@"There are %lu matches", [matchArray count]);
    }
    else
    {
        
        NSLog(@"There were no characters in the original file");  //This output is shown if there are no characters to delete.
    }
    NSDate *endTime = [[NSDate alloc] init]; //Records when the program is almost finished
    NSLog(@"This took %.2f seconds to run", [endTime timeIntervalSinceDate:startTime]); //Logs the amount of time elapsed
}
return 0;

}

[/code]

And lastly I just wanted to say thanks to the authors of this book, this is my first go at programming in 30 something years and the book is great to learn from :smiley:


#3

That is so much faster, I did it the normal way, it took 3 minutes and 9 seconds, then I added in a break in the loop once a match was found and it ran in 2 minutes and 31 seconds.

This way took 0.43 seconds