Challenge 2 Solution


#1

I’m sure there’s a way to make it faster, but it gets the job done. 293 entries get logged.

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

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

@autoreleasepool {
    
    // Turn lists of names and words into strings
    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 up names and words and put them into arrays
    NSArray *names = [nameString componentsSeparatedByString:@"\n"];
    NSArray *words = [wordString componentsSeparatedByString:@"\n"];
    
    // Use int variable to track name/word matches.
    // For each name in name array, iterate through words array.
    // If the word and name are the same on case-insensitive basis
    // and the word isn't a duplicate of the uppercase name
    // increment match variable, then print the name and the word as a valid match.
    int match = 0;
    for (NSString *n in names) {
        for (NSString *w in words) {
            if (([n caseInsensitiveCompare:w] == NSOrderedSame) && ![n isEqualToString:w]) {
                match++;
                NSLog(@"#%i Name: %@  Word: %@", match, n, w);
            }
        }
    }
    
}
return 0;

}

[/code]


#2

Love your solution


#3

Thanks! :slight_smile:


#4

Awesome solution.
Mine is longer.
Yours is neat.

Essentially, you first compare if the words and names match regardless of case.
Then, you add another condition which checks if the word and name are NOT equal.
Which is correct, because you do not want them to be the same.
You want Wolf = wolf and NOT Wolf=Wolf or wolf=wolf.

Nice addition of a match value to keep the track of the entries logged! 293 entries is correct indeed.

This is awesome. I just wrote the above out to grasp your brilliant solution in my mind better.

Thank you.


#5

Boy did it take me (too much) time to figure out that the words file contained all those names !
A bit simplistic check if the name is in the words list without capital but it does the job :slight_smile:

#import <Foundation/Foundation.h>

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

@autoreleasepool {
    
    // read propernames and words files as strings and then dump into an array
    NSString *nameString =
    [NSString stringWithContentsOfFile:@"/usr/share/dict/propernames" encoding:NSUTF8StringEncoding error:NULL];
    NSArray *names = [nameString componentsSeparatedByString:@"\n"];
    
    NSString *wordString =
    [NSString stringWithContentsOfFile:@"/usr/share/dict/words" encoding:NSUTF8StringEncoding error:NULL];
    NSArray *words = [wordString componentsSeparatedByString:@"\n"];
   
    // go over all the words for each name
    
    for (NSString *name in names)
    {
        for (NSString *word in words)
        {
            
            // here we compare if the word and name match (case insensitive)
            if ( [word caseInsensitiveCompare:name] == NSOrderedSame)
            {
                // we found a match between a name and an entry in the properwords list
                // but we have to check if the first letter of the word is a capital.
                // The check is done simplistic, look if the ASCII value, below 90 it are all
                // capitals.
                
                if ([word characterAtIndex:0] > 90)
                    NSLog(@"Found a word %@ !", word);
            }
        }
    }
    

    
}
return 0;

}


#6

[quote]Boy did it take me (too much) time to figure out that the words file contained all those names !
A bit simplistic check if the name is in the words list without capital but it does the job :slight_smile:[/quote]

[quote]if ([word characterAtIndex:0] > 90) NSLog (@"Found a word %@ !", word); [/quote]
But that piece of code is very yucky!

Write it like this:

if ([word length] && isupper ([word characterAtIndex:0])) {
     NSLog (@"Found a name %@ !", word);
}

[Accelerate your learning and become a competent programmer: pretty-function.org]


#7

Awesome work, krskrft!

After logging out your match, you should add a break statement so that quits iterating through the remainder of the words list and moves onto the next name. The difference in speed probably isn’t noticeable, but it will definitely give you peace of mind. :slight_smile:

for (NSString *n in names) {
            for (NSString *w in words) {
                if (([n caseInsensitiveCompare:w] == NSOrderedSame) && ![n isEqualToString:w]) {
                    match++;
                    NSLog(@"#%i Name: %@  Word: %@", match, n, w);
                    break;
                }
            }
        }

#8

I took very similar approach as OP but wondering if there are any advantages/disavantages to my method as follows:

1.- The framework reference recommends using localizedCaseInsensitiveCompare:. Any disadvantages/advantages of this method over caseInsensitiveCompare aside from using users locale?

2.- I am using [w isEqualToString:n.lowercaseString] to compare against lower case version of name in the words, instead of ![n isEqualToString:w]. This seems to work except for that it generates an additional NSLOG at the very end with empty values, thus throwing off the count. Why does this happen if there are no more matches? I am having trouble wrapping my head around that.

thanks!

------MY CODE-----

//
//  main.m
//  ObjC_NSArray|NSRange_interesting_names_Challenge
//
//  Created by EvilKernel on 9/11/14.
//  Copyright (c) 2014 Zerogravity. All rights reserved.
//

#import <Foundation/Foundation.h>

int main(int argc, const char * argv[])
{
    
    @autoreleasepool {
        
        // **** INTERESTING NAMES CHALLENGE - NSARRAY - Locate lower case name [only] matches in words file **** //
        
        // Read in file inputs and build giant strings with file
        NSString *namesFile = [NSString stringWithContentsOfFile:@"/usr/share/dict/propernames" encoding:NSUTF8StringEncoding error:NULL];
        NSString *wordsFile = [NSString stringWithContentsOfFile:@"/usr/share/dict/words" encoding:NSUTF8StringEncoding error:NULL];
        
        // build arrays, breaking down the lumped strings above into an array of strings so that we can compare one by one string item.
        NSArray *names = [namesFile componentsSeparatedByString:@"\n"]; // method of NSString which returns an array with items from above string + separator, in this case, a line break.
        NSArray *words = [wordsFile componentsSeparatedByString:@"\n"];
        
        
        // iterate through array
        int i = 0;
        for (NSString *w in words){
            for (NSString *n in names) {
                
                // search for equivalent string in 'names' array  in 'words' array
                NSComparisonResult match = [w localizedCaseInsensitiveCompare:n]; 
                BOOL isMatch = match == NSOrderedSame && [w isEqualToString:n.lowercaseString]; 
                if (isMatch) {
                    i++; //increment log count
                    NSLog (@"%d.Match Found %@ ----------- %@", i, n, w);
                    break;
                }
            }
        }
        
        NSLog(@"Processed %lu name againts %lu words with %d matches found", names.count, words.count, i);
        
    }
    return 0;
    
}