In my first attempt awhile back which you can find posted, I first lowercased all the proper names and then used isEqualToString to compare with the lower cased words. Some time has passed and now I am working back through the book and came up with this 2nd solution which I think is more elegant:
// Interesting names
//
// Created by Adam G on 5/17/14.
//
#import <Foundation/Foundation.h>
int main(int argc, const char * argv[])
{
@autoreleasepool {
// Read in a file as a huge string(ignoring the possibility of an error)
NSString *nameString = [NSString stringWithContentsOfFile:@"/usr/share/dict/propernames"
encoding:NSUTF8StringEncoding
error:NULL];
NSString *wordString = [NSString stringWithContentsOfFile:@"/usr/share/dict/words"
encoding:NSUTF8StringEncoding
error:NULL];
// Break it into an array of strings
NSArray *names = [nameString componentsSeparatedByString:@"\n"];
NSArray *words = [wordString componentsSeparatedByString:@"\n"];
int iterations = 0;
for (NSString *n in names) {
for (NSString *w in words) {
// iteration count of inner loop
iterations++;
// first compare name with the word to see if they are the same regardless of case and
// then compare them again with isEqualToString to make sure they are not the same case
// if both conditions are true then print the Name and Word to the log
if (([n caseInsensitiveCompare:w] == NSOrderedSame) && ([n isEqualToString:w] == NO))
{
NSLog(@"Name: %@ Word: %@", n, w);
// find the first occurrence and then break to the outer loop
// iterations are initially 308776083. When you add the break then iterations fall to 273861512
// if the same word/name combination appears twice then they are not printed
break;
}
}
}
NSLog(@"Iterations: %d", iterations);
}
return 0;
}
My approach was to lowercase the propernames list like your first attempt.
So what’s the best way to solve this challenge? It seems like there are more than 2, 3 ways to do it…
The most “elegant” way would be an approach that is short and gets the job done most efficiently?
#import <Foundation/Foundation.h>
int main(int argc, const char * argv[])
{
@autoreleasepool {
// (1) Read in propernames file as a huge string
// convert *namesList to lowercaseString so that I can find the matched words
NSString *namesList = [[NSString stringWithContentsOfFile:@"/usr/share/dict/propernames"
encoding:NSUTF8StringEncoding
error:NULL] lowercaseString];
// (2) Read in words file as a huge string
NSString *wordsList = [NSString stringWithContentsOfFile:@"/usr/share/dict/words"
encoding:NSUTF8StringEncoding
error:NULL];
// (3) Break them into arrays of strings
NSArray *names = [namesList componentsSeparatedByString:@"\n"];
NSArray *words = [wordsList componentsSeparatedByString:@"\n"];
// (4) Use 'fast enumeration' to check the duplicates
for (NSString *n in names ) {
for (NSString *i in words) {
// Look for duplicates
if ([n isEqualToString:i] == YES) {
// Print them if found
NSLog(@"\n%@ is a duplicate.\n", i);
}
}
}
return 0;
}
}
I added a code at the end that prints how many matches are there. I’m getting 294, but I think the correct answer is 293.
I noticed that I get a “[blank] is a duplicate” at the very end. Why is it doing that? Here’s the last three output:
2014-05-30 16:39:27.972 17_NSArray_Challenge2[46960:303] wolf is a duplicate.
2014-05-30 16:39:27.994 17_NSArray_Challenge2[46960:303] woody is a duplicate.
2014-05-30 16:39:28.013 17_NSArray_Challenge2[46960:303] is a duplicate.
[code] #import <Foundation/Foundation.h>
int main(int argc, const char * argv[])
{
@autoreleasepool {
// (1) Read in propernames file as a huge string
// convert *namesList to lowercaseString so that I can find the matched words
NSString *namesList = [[NSString stringWithContentsOfFile:@"/usr/share/dict/propernames"
encoding:NSUTF8StringEncoding
error:NULL] lowercaseString];
// (2) Read in words file as a huge string
NSString *wordsList = [NSString stringWithContentsOfFile:@"/usr/share/dict/words"
encoding:NSUTF8StringEncoding
error:NULL];
// (3) Break them into arrays of strings
NSArray *names = [namesList componentsSeparatedByString:@"\n"];
NSArray *words = [wordsList componentsSeparatedByString:@"\n"];
// (4) Use 'fast enumeration' to check the duplicates
long matches = 0;
for (NSString *n in names ) {
for (NSString *i in words) {
// Look for duplicates
if ([n isEqualToString:i]) {
// Print them if found
NSLog(@"%@ is a duplicate.\n", i);
matches++;
}
// How do I get the count of the matches?
}
}
NSLog(@"There were %lu matches", matches);
return 0;
Though I don’t print out every matching word, it can be easily done as in my case the result is a new array containing all the words, that have pairs.[/quote]
Excellent!! Wonder why the book doesn’t show some good examples like this of NSSet or MutableSet.
[quote=“hahndrew”]I added a code at the end that prints how many matches are there. I’m getting 294, but I think the correct answer is 293.
I noticed that I get a “[blank] is a duplicate” at the very end. Why is it doing that? Here’s the last three output:
2014-05-30 16:39:27.972 17_NSArray_Challenge2[46960:303] wolf is a duplicate.
2014-05-30 16:39:27.994 17_NSArray_Challenge2[46960:303] woody is a duplicate.
2014-05-30 16:39:28.013 17_NSArray_Challenge2[46960:303] is a duplicate.
[code] #import <Foundation/Foundation.h>
int main(int argc, const char * argv[])
{
@autoreleasepool {
// (1) Read in propernames file as a huge string
// convert *namesList to lowercaseString so that I can find the matched words
NSString *namesList = [[NSString stringWithContentsOfFile:@"/usr/share/dict/propernames"
encoding:NSUTF8StringEncoding
error:NULL] lowercaseString];
// (2) Read in words file as a huge string
NSString *wordsList = [NSString stringWithContentsOfFile:@"/usr/share/dict/words"
encoding:NSUTF8StringEncoding
error:NULL];
// (3) Break them into arrays of strings
NSArray *names = [namesList componentsSeparatedByString:@"\n"];
NSArray *words = [wordsList componentsSeparatedByString:@"\n"];
// (4) Use 'fast enumeration' to check the duplicates
long matches = 0;
for (NSString *n in names ) {
for (NSString *i in words) {
// Look for duplicates
if ([n isEqualToString:i]) {
// Print them if found
NSLog(@"%@ is a duplicate.\n", i);
matches++;
}
// How do I get the count of the matches?
}
}
NSLog(@"There were %lu matches", matches);
return 0;
This is my solution that uses a “for” loop inside a “for” loop. What do you think?
#import <Foundation/Foundation.h>
int main (int argc, const char * argv[]) {
@autoreleasepool {
NSString *nameString = [NSString stringWithContentsOfFile:@"/usr/share/dict/propernames"
encoding:NSUTF8StringEncoding
error:NULL];
NSArray *names = [nameString componentsSeparatedByString:@"\n"];
NSString *wordsString = [NSString stringWithContentsOfFile:@"/usr/share/dict/words"
encoding:NSUTF8StringEncoding
error:NULL];
NSArray *words = [wordsString componentsSeparatedByString:@"\n"];
for (NSString *p in names) { // This makes the array of "propernames" into organized strings
for (NSString *w in words) { // This makes the array of "words" into organized strings
NSRange r = [w rangeOfString:p options:NSCaseInsensitiveSearch]; // This looks for "propernames" inside "words" with a Case Insensitive Search
if (r.location != NSNotFound) {
NSLog(@"%@",w); // Prints the result
}
}
}
} return 0;
}
From what I found, if I am correct. There are actually 293 words. I just added another if check inside of the second loop to check for the empty word (…[word isNotEqualTo: @""]…). It will not work if you create a space, like so (@" "). I’m fairly new to this so I’m not certain as to why it that empty string has made its way into the array but my solution seems to keep it from being added into the mutable array and its count. Hope this helps.
That’s because, when breaking up the string read from the file, you are using “\n” (newline) as the delimiter. There is a newline at the end of each line in the file; since the last line consists of a word and a newline at the end, you also get a null word (word of length 0) as an undesirable bonus.
[Become a competent programmer faster than you can imagine: pretty-function.org]