13. Anagrams Problem

Screen Link:

My Code:

test1_string1 = 'gainly'
test1_string2 = 'laying'
# Expected output: True

test2_string1 = 'banana'
test2_string2 = 'bacana'
# Expected output: False

def are_anagrams(string1, string2):
    empty_string = ''
    output = False
    for i in string1:
        empty_string+=i
        for j in string2:
            if j in empty_string and len(string2) == len(empty_string):
                output = True
    return output

print(are_anagrams(test1_string1,test1_string2))
print(are_anagrams(test2_string1,test2_string2))

My output:

True
True

Can someone explain to me what’s wrong with my code, why is it not outputting the correct boolean?

@TravisBob: what is your purpose of comparing the length of the strings here knowing that they are already equal? Why not you create a dictionary and compare the frequencies of the individual characters instead?

I’ve modified the code to the following & was correct in when i hit Submit Answer:

test1_string1 = 'gainly'
test1_string2 = 'laying'
# Expected output: True

test2_string1 = 'banana'
test2_string2 = 'bacana'
# Expected output: False

def are_anagrams(string1,string2):
    if len(string1)!=len(string2):
        return False
    def string_char_freq(string): 
        string_char_dict = {}
        for i in string:
            if i not in string_char_dict:
                string_char_dict[i] = 0
            string_char_dict[i]+=1
        return string_char_dict #MAKE SURE YOU DECLARE THIS LINE
    freq1 = string_char_freq(string1)
    freq2 = string_char_freq(string2)
    for c in freq1:
        if c not in freq2 or freq1[c] != freq2[c]:
            return False
        return True  

print(are_anagrams(test2_string1,test2_string2))

My question is that in the solutions, the return True statement is indented like this:

test1_string1 = 'gainly'
test1_string2 = 'laying'
# Expected output: True

test2_string1 = 'banana'
test2_string2 = 'bacana'
# Expected output: False
def character_freq(string):
    """
    Auxiliary function to compute the frequency
    table of the characters in a string.
    """
    freq = {}
    for c in string:
        if c not in freq:
            freq[c] = 0
        freq[c] += 1
    return freq

def are_anagrams(string1, string2):
    # String of different lengths cannot be anagrams
    if len(string1) != len(string2):
        return False
    # Compute the frequency of characters in both strings
    freq1 = character_freq(string1)
    freq2 = character_freq(string2)
    for c in freq1:
        if c not in freq2 or freq1[c] != freq2[c]:
            return False
    # Because we checked the length, we don't need to check the other way
    return True

# Solution testing
print(are_anagrams('gainly', 'laying'))
print(are_anagrams('banana', 'bacana'))

return True is lined up below the for loop before it. Does it matter the indentation? My updated code still works.

Yes, of course the indentation matters. Before you can return True (i.e. before you decide the 2 strings are anagrams), you must check that all the characters have the same frequency in the 2 strings. Your indentation of the “return True” line puts it inside the for loop, so you return True after checking the frequency only for 1 character, the first character in the string.

Here’s an example where your indentation causes the issue:
string1 = ‘aab’
string2 = ‘aabb’

Your for loop will start by testing if the character ‘a’ appears in both strings and if it has the same frequency in both strings. It does and it has (frequency is 2 in both strings), so the if statement will not be verified and the code within it will not be executed (it will not return False).

Then, your loop moves to the next line of code: “return True”. So your code returns True just because the first character ‘a’ has the same frequency in both strings. Obviously, that’s wrong. It should not return True since ‘aab’ and ‘aabb’ are not anagrams. Instead, it should test the next character: ‘b’, so you must stay inside the loop and iterate to all the characters in the string. Only after you test all the characters and find no False return (all characters have the same frequency), then can you return True.

You fix this simply by indenting “return True” to the left, at the same indentation level as the for loop, which puts the “return True” code outside the loop:

    for c in freq1:
        if c not in freq2 or freq1[c] != freq2[c]:
            return False
    return True  

Now “return True” is executed only after the loop made sure there is no False return, i.e. after it verified all the characters have the same frequency in the 2 strings, i.e. the 2 strings are anagrams,