user1870869
user1870869

Reputation: 21

Anagram algorithm objective C

i have written the following code to check anagram want to know is this perfect & is there any better way to implement the same in objective C

-(BOOL) findAnagram :(NSString *) string1 :(NSString *) string2
{
    int len = string1.length;
    if (len != string2.length)
    {
        return false;
    }

    for (int i=0; i < len; i++)
    {
        int h = 0;
        int q = 0;
        for (int k = 0;  k < len ; k ++)
        {
            if ([string1 characterAtIndex:i] == [string1 characterAtIndex:k])
            {
                h++;
            }
            if ([string1 characterAtIndex:i] == [string2 characterAtIndex:k])
            {
                q++;
            }
        }

        if (h!=q)
        {
            return false;
        }
    }
    return TRUE;
}

Upvotes: 1

Views: 3925

Answers (6)

Warren G
Warren G

Reputation: 1

Another run of the mill algorithm:

- (BOOL) testForAnagramWithStrings:(NSString *)stringA andStringB: (NSString *)stringB{

    stringA = [stringA lowercaseString];

     stringB = [stringB lowercaseString];


     int counter = 0;

     for (int i=0; i< stringA.length; i++){


         for (int j=0; j<stringB.length;j++){


             if ([stringA characterAtIndex:i]==[stringB characterAtIndex:j]){

                 counter++;

             }


         }

     }

     if (counter!= stringA.length){

         return false;
     }

     return true;

}

Upvotes: 0

Manoj Singhal
Manoj Singhal

Reputation: 109

Check the following method which check Anagram strings.

-(BOOL)checkAnagramString:(NSString*)string1 WithAnotherString:(NSString*)string2{

  NSCountedSet *countSet1=[[NSCountedSet alloc]init];
  NSCountedSet *countSet2=[[NSCountedSet alloc]init];

  if (string1.length!=string2.length) {
    NSLog(@"NOT ANAGRAM String");
    return NO;
  }


  for (int i=0; i<string1.length; i++) {
      [countSet1 addObject:@([string1 characterAtIndex:i])];
      [countSet2 addObject:@([string2 characterAtIndex:i])];
  }

  if ([countSet1 isEqual:countSet2]) {
    NSLog(@"ANAGRAM String");
    return YES;
  } else {
    NSLog(@"NOT ANAGRAM String");
    return NO;
  }

}

Upvotes: 0

Ryan Heitner
Ryan Heitner

Reputation: 13632

This is an implementation on @zmbq suggestion of sorting and comparing.

You should consider the requirements of deleting spaces and being case insensitive.

- (BOOL)isAnagram:(NSString *)leftString and:(NSString *)rightString {
  NSString *trimmedLeft = [[leftString stringByReplacingOccurrencesOfString:@" " withString:@""] lowercaseString];
  NSString *trimmedRight = [[rightString stringByReplacingOccurrencesOfString:@" " withString:@""] lowercaseString];
  return [[self stringToCharArraySorted:trimmedLeft] isEqual:[self stringToCharArraySorted:trimmedRight]];
}

- (NSArray *)stringToCharArraySorted:(NSString *)string {
  NSMutableArray *array = [[NSMutableArray alloc] init];
  for (int i = 0 ; i < string.length ; i++) {
    [array addObject:@([string characterAtIndex:i])];
  }
  return [[array sortedArrayUsingSelector:@selector(compare:)] copy];
}

called like this

BOOL isAnagram = [self isAnagram:@"A BC" and:@"cba"];

Upvotes: 0

Richard J. Ross III
Richard J. Ross III

Reputation: 55573

A better performing version than yours, which is a O(n ^ 2) algorithm, is a O(n) algorithm:

BOOL anagrams(NSString *a, NSString *b)
{
    if (a.length != b.length)
        return NO;

    NSCountedSet *aSet = [[NSCountedSet alloc] init];
    NSCountedSet *bSet = [[NSCountedSet alloc] init];

    for (int i = 0; i < a.length; i++)
    {
        [aSet addObject:@([a characterAtIndex:i])];
        [bSet addObject:@([b characterAtIndex:i])];
    }

    return [aSet isEqual:bSet];
}

Upvotes: 23

mattjgalloway
mattjgalloway

Reputation: 34912

It looks fine to me. But the code style is slightly odd. I would write it like this:

- (BOOL)isStringAnagram:(NSString *)string1 ofString:(NSString *)string2 {
    int len = string1.length;
    if (len != string2.length) {
        return NO;
    }

    for (int i=0; i < len; i++) {
        int h = 0;
        int q = 0;
        for (int k = 0;  k < len; k++) {
            if ([string1 characterAtIndex:i] == [string1 characterAtIndex:k]) {
                h++;
            }
            if ([string1 characterAtIndex:i] == [string2 characterAtIndex:k]) {
                q++;
            }
        }

        if (h != q) {
            return NO;
        }
    }

    return YES;
}

The main issue I have is with the method name. While it's possible to have parameters that have nothing before them in the name, it is not advisable. i.e. you had findAnagram:: as the name whereas I've used isStringAnagram:ofString:.

Upvotes: 1

zmbq
zmbq

Reputation: 39013

You want to know if two strings contain exactly the same characters? Easiest way would probably be to sort both of them and compare the sorted version.

Another way would be to count the number of appearances of each letter (how many As, how many Bs, and so forth), then compare those counts.

(Note: The second way is just a variation of the first one, it's one efficient way to sort a string)

Upvotes: 1

Related Questions