I am working on another challenge from CodeEval.com and this is a bit harder. I would like to get some feedback on my logic of solving the challenge. Also there is probably one edge case that I missed because when I submit it to CodeEval I get different results. Once I received 95% correct and another time 100%.

The Ministry of Truth

It's 1984, and you are working as an official at the Ministry of Truth. You have intersected a message subjected to Big Brother's doctrine.

Your task is to delete letters from certain "utterances" in order to replace them with an "utterance" approved by the Ministry.

A "word" is a single sequence of Latin letters, and an "utterance" is a sequence of multiple words and spaces.

To compare two "utterances," you have to replace all blocks of spaces with one space. Utterances are considered to be identical when resulting expressions match.

One line contains two different expressions separated by semicolon ';'. The first expression is the original utterance, and the second one is the utterance you want to get.

If you cannot fulfill the order, print a single line «I cannot fix history». Otherwise, output the original utterance by replacing the letters that must be erased with underscore and by replacing all blocks of white spaces with a single white space.

Input Sample:

Higher meaning;Hi mean
this is impossible;im possible
twenty   two minutes;two minutes
Higher meaning;e

Output Sample:

Print the results, or "I cannot fix history" in case there is no match. E.g.:

Hi____ mean___ 
I cannot fix history
 ______ two minutes
 ____e_ _______

Here is my solution:

    NSString *line = @"ifcf hesaddasd  asdajds dsd f;";
    NSArray *lineArray = [line componentsSeparatedByString:@";"]; //separate the original from approved
    NSArray *originalUtteranceWithSpaces= [[lineArray objectAtIndex:0] componentsSeparatedByString:@" "]; //separate the words from spaces
    NSMutableArray *originalUtterance  = [[NSMutableArray alloc]init];
    for (NSString *word in originalUtteranceWithSpaces){
        //get rid of the spaces
        if (![word isEqual:@""]) {
            [originalUtterance addObject:word];

    NSArray *approvedUtterance = [[lineArray objectAtIndex:1] componentsSeparatedByString:@" "]; //separate the approved
    NSMutableArray *resultArray = [[NSMutableArray alloc]init];
    NSUInteger pos = 0;
    BOOL isWordFound = NO;
    if ([[approvedUtterance objectAtIndex:0] isEqual:@""]) {
        isWordFound = NO;
        for(NSString *approvedWord in approvedUtterance){
            //itterate through the approved utterances
            isWordFound = NO;
            while (pos < [originalUtterance count]) {
                //itterate through the words until you find the word that contains the approved word or goes through all the words
                NSString *originalWord = [originalUtterance objectAtIndex:pos];

                NSRange approvedWordLocation = [originalWord rangeOfString:approvedWord]; //check if the word contains approved word
                if (approvedWordLocation.location !=NSNotFound) {
                    isWordFound = YES;
                    int letterPos = 0;
                    NSMutableString *tempOriginalWord = [originalWord mutableCopy];
                    //if approved word found then create a mutable copy of it and replace all chars in originalWord that are not the word with _
                    while (letterPos < [originalWord length]) {
                        if ((letterPos < approvedWordLocation.location) || (letterPos >= approvedWordLocation.location + approvedWordLocation.length)) {
                            //check if letterPos is before the found word or after
                            [tempOriginalWord replaceCharactersInRange:NSMakeRange(letterPos, 1) withString:@"_"];
                    //add to result array
                    [resultArray addObject:tempOriginalWord];
                    pos+=1; // move to the next original word
                    break; //get out of the while loop and check the next approved word
                    isWordFound = NO;
                    //approvedWord not found set the whole word to _ and add it to the result array
                    NSMutableString *tempOriginalWord = [originalWord mutableCopy];
                    for (int letterPos = 0; letterPos < [originalWord length]; letterPos++) {
                        [tempOriginalWord replaceCharactersInRange:NSMakeRange(letterPos, 1) withString:@"_"];
                    [resultArray addObject:tempOriginalWord];
                    pos+=1; //move to the next original word

            if (!isWordFound) {
                //if approved word is not found then break out of the for loop and we are done.  I cannot fix history

        if (pos<[originalUtterance count] && isWordFound) {
            //if all approved words are found and we still have word from origingal utterance then replace all charcters with _
            NSMutableString *tempString = nil;
            for (NSUInteger i = pos; i<[originalUtterance count]; i++) {
                tempString = [[originalUtterance objectAtIndex:i] mutableCopy];
                NSUInteger tempStringLength = [tempString length];
                for (NSUInteger i = 0; i<tempStringLength; i++) {
                    [tempString replaceCharactersInRange:NSMakeRange(i,1) withString:[NSString stringWithFormat:@"_"]];
                [resultArray addObject:tempString];

    if (isWordFound) {
        //Print results if all  approved words found
        NSString *resultString = [resultArray componentsJoinedByString:@" "]; //create NSString from array and put space between the words
        NSLog(@"resultArray %@",resultString);
        NSLog(@"I cannot fix history");

1 Answer 1


Your code is nice, but could use a few improvements:

[array objectAtIndex:pos]

From what I can see, array[pos] is valid syntax for Objective-C, and is much better.

You're missing, in more than a few places, whitespace. For example:

  • }else{ should be } else {,
  • @"resultArray %@",resultString should have whitespace after the comma
  • NSMakeRange(i,1) same as above: NSMakeRange(i, 1)
  • i<tempStringLength: needs whitespace between the operator: i < tempStringLength
  • pos+=1: same as above: pos += 1 (which could be pos++, right?)

You have two main for loops in your code, and in one, you use the data type int and in the other NSUInteger.
I would suggest keeping them the same, and also their names the same as one is letterPos and the other i.

for (int letterPos = 0
for (NSUInteger i = 0

You have quite a few empty lines that could be removed, also.

Other than that, your code looks nice.


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.