Interview puzzles in Objective-C

July 24th, 2011
#interviewing

It seems to be difficult (in Objective-C) to find a coherent post about those tricky puzzles that sometimes crop up so I thought I'd post one ๐Ÿ˜€.

Photo of a magic cube

String Puzzles

Reverse a string
- (NSString *)reverseString:(NSString *)originalString {
    int lengthOfString = [originalString length];
    NSMutableString *reorderedString = [[[NSMutableString alloc] initWithCapacity:lengthOfString] autorelease];
    
    while (lengthOfString > 0) {
        NSString *element = [NSString stringWithFormat:@"%C", [originalString characterAtIndex:--lengthOfString]];
        [reorderedString appendString:element];
    }
    
    return reorderedString;
}
Reverse a string 2
- (NSString *)reverseString:(NSString *)originalString {
    int lengthOfString = [originalString length];
    NSMutableString *reorderedString = [[[NSMutableString alloc] initWithCapacity:lengthOfString] autorelease];
    
    for (int x = 0; x < lengthOfString; x++) {
        NSString *element = [NSString stringWithFormat:@"%C", [originalString characterAtIndex:x]];
        [reorderedString insertString:element atIndex:0];
    }
    
    return reorderedString;
}
Reverse a string and keep word ordering
- (NSString *)reverseStringInOrder:(NSString *)originalString {
	NSArray *splitOriginalString = [originalString componentsSeparatedByString:@" "];
	NSMutableString *reorderedString = [[[NSMutableString alloc] initWithCapacity:[originalString length]] autorelease];

	for (int x = 0; x < [splitOriginalString count]; x++) {
		NSString *splitString = [splitOriginalString objectAtIndex:x];

		NSString *reorderedSplitString = [self reverseString:splitString]; //pick one of the above implementations

		if (x != 0) {
			[reorderedString appendString:@" "];
		}
		[reorderedString appendString:reorderedSplitString];
	}
  
	return reorderedString;
}
Sort words into alphabetical order
- (NSString *)sortWordsInStringIntoAlphabeticalOrder:(NSString *)originalString {
    NSMutableArray *wordArray = [[originalString componentsSeparatedByString:@" "] mutableCopy];

    [wordArray sortUsingSelector:@selector(caseInsensitiveCompare:)];

    NSMutableString *returnString = [[NSMutableString alloc] init];

    for (int x = 0; x < [wordArray count]; x++) {
        if (x != 0) {
            [returnString appendString:@" "];
        }

        [returnString appendString:[wordArray objectAtIndex:x]];
    }

    return returnString;
}
Determine if string can be reassembled to a Palindrome
- (BOOL)isPalindromic:(NSString *)string {
    NSString *caseInsensitiveString = [string lowercaseString];
    int lengthOfString = [string length];
    
    if (lengthOfString == 0) {
        return FALSE;
    }
    
    NSMutableDictionary *characterBin = [[[NSMutableDictionary alloc] init] autorelease];
    
    if (lengthOfString > 1) {
        //check properties
        for (int x = 0; x < lengthOfString; x++) {
            char charAtIndex = [caseInsensitiveString characterAtIndex:x];
            
            NSString *key = [NSString stringWithFormat:@"%C", charAtIndex];
            
            if ([characterBin valueForKey:key] != nil) {
                int countOfCharacter = [[characterBin objectForKey:key] intValue];
                [characterBin setObject:[[NSNumber alloc] initWithInt:++countOfCharacter] forKey:key];
            } else {
                [characterBin setObject:[[NSNumber alloc] initWithInt:1] forKey:key];
            }
        }
        
        BOOL foundOddCharacter = FALSE;
        
        for (NSString *key in [characterBin allKeys]) {
            if (([[characterBin objectForKey:key] intValue]%2) != 0) {
                if (foundOddCharacter) {
                    return FALSE;
                } else {
                    foundOddCharacter = TRUE;
                }
            }
        }
        
        return TRUE;
    } else {
        return TRUE;
    }
}
Find matching characters in two strings
- (NSString *)determineMatchingCaseInsensitiveCharactersInStringsOne:(NSString *)stringOne two:(NSString *)stringTwo {
    NSMutableDictionary *stringOneDict = [NSMutableDictionary dictionaryWithCapacity:[stringOne length]];
    
    for (NSUInteger index = 0; index < [stringOne length];  index++) {
        NSString *key = [[NSString stringWithFormat:@"%c", [stringOne characterAtIndex:index]] lowercaseString];
        
        if (![key isEqualToString:@" "]) {
            [stringOneDict setObject:[NSNumber numberWithBool:NO] forKey:key];
        }
    }
    
    NSMutableString *charactersFromBoth = nil;
    
    for (NSUInteger index = 0; index < [stringTwo length];  index++) {
        NSString *potentialKey = [[NSString stringWithFormat:@"%c", [stringTwo characterAtIndex:index]] lowercaseString];
        
        if (![potentialKey isEqualToString:@" "]) {
            NSNumber *characterExistsInBoth = [stringOneDict objectForKey:potentialKey];
            
            if (characterExistsInBoth) {
                if (!charactersFromBoth) {
                    charactersFromBoth = [NSMutableString string];
                }
                
                [charactersFromBoth appendString:potentialKey];
            }
        }
    }
    
    return charactersFromBoth;
}

Number Puzzles

Convert Decimal to Binary
- (NSString *)convertDecimalToBinary:(int)decimalNumber {
    if (decimalNumber > 1) {
        NSMutableString *binaryRepresentation = [[[NSMutableString alloc] init] autorelease];
        
        while (decimalNumber > 0) {
            int mod = decimalNumber % 2;
            [binaryRepresentation insertString:[NSString stringWithFormat:@"%d", mod] atIndex:0];
            decimalNumber = (decimalNumber/2);
        }
        
        return binaryRepresentation;
    } else {
        return [NSString stringWithFormat:@"%d", decimalNumber];
    }
}
Find GCD (Greatest Common Denominator) shared between two numbers
- (int)GCDBetweenLowest:(int)lowest highest:(int)highest {
    if (lowest == 0 || highest == 0) {
        return 0;
    }
    
    if (lowest == highest) {
        return lowest;
    }
    
    if (highest%lowest == 0) {
        return lowest;
    }
    
    if (!(lowest%2 == 0 && highest%2 == 0)) {
        return 1;
    }
    
    int lowestUpperBounds = lowest/2;
    
    //get lowest and highest factors
    for (int x = lowestUpperBounds; x >= 2; x--) {
        if (lowest%x == 0 && highest%x == 0) {
            return x;
        }
    }
    
    return 1;
}
Determine if a given value is a prime number
- (BOOL)isPrime:(long)possiblePrime {
    if (possiblePrime == 1) {
        return FALSE;
    }
    
    if (possiblePrime == 2) {
        return TRUE;
    }
    
    if (possiblePrime%2 == 0) {
        return FALSE;
    }
    
    double doubleSquareRoot = sqrt((double)possiblePrime);
    int intSquareRoot = (int)doubleSquareRoot;
    double outcomeOfSquareRoots = doubleSquareRoot - intSquareRoot;
    
    if (outcomeOfSquareRoots == 0) {
        return FALSE;
    }
    
    for (int x = 3; x < doubleSquareRoot; x+=2) {
        if (number%x == 0) {
            return FALSE;
        }
    }
    
    return TRUE;
}
Generate list of prime numbers
- (NSArray *)generateAllPrimeNumbersUntil:(long)max {
    
    NSMutableArray *primeArray = [[NSMutableArray alloc] init];
    
    if (max == 2) {
        [primeArray addObject:[[NSNumber alloc] initWithInt:2]];
    }
    
    for (int x = 3; x < max; x=x+2) {
        if ([self isPrime:x]) {
            [primeArray addObject:[[NSNumber alloc] initWithInt:x]];
        }
        
        return primeArray;
    }
}
Determine if number is power of 2
- (BOOL)isNumberPositivePowerOfTwo:(NSUInteger)possiblePower {
    if (possiblePower == 0 || possiblePower == 1 || possiblePower == 2) {
        return YES;
    }
    
    if (possiblePower % 2  != 0) {
        return NO;
    }
    
    while(possiblePower > 2) {
        possiblePower = possiblePower/2;
        
        if (possiblePower == 2) {
            return YES;
        }
    }
    
    return NO;
}
BuzzFizz

This used to be a favourite of Google. The problem is: given an upper boundary, print "Buzz" for every occurrence where the current index is divisible by 3, print "Fizz" for every occurrence where the current index is divisible by 3 and "BuzzFizz" for every occurrence where the current index is divisible by 3 and 5.

- (void)printBuzzFizzForMaximumUpperBoundary:(NSUInteger)upperBoundary {
    for (NSUInteger index = 1; index < upperBoundary; index++) {
        if (index % 3 == 0 && index % 5 == 0) {
            NSLog(@"BuzzFizz for index: %lu", (unsigned long)index);
        } else if (index % 3 == 0) {
            NSLog(@"Buzz for index: %lu", (unsigned long)index);
        } else if (index % 5 == 0) {
            NSLog(@"Fizz for index: %lu", (unsigned long)index);
        }
    }
}

What do you think? Let me know by getting in touch on Twitter - @wibosco