Python Fundamentals: 13. Anagrams (alternative solution?)

I’ve tried finding a solution without having to rely on a dictionary. So, I found out about the set() function which seemed to work when clicking the ‘Run Code’ button but not with the ‘Submit Answer’ button. Any idea why? Would it be possible to do this without using a dictionary in the first place? Thanks for your comments.

Screen Link:

My Code:

def are_anagrams(string1,string2):
    
    if len(string1) != len(string2):
        return False
    
    for char in string1:
        if char not in string2:
            return False
        elif set(string1) != set(string2):
            return False  
        else:
            return True

What actually happened:

Function are_anagrams did not return the expected value.

But it did work for both examples below:

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

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

Wait “aaabb” and “aabbb” will return True with your code, right ? Think the issue lies in your if + elif + else statements

set only insures you that the 2 words contain the same letters but you didn’t check the numbers of occurrences for each different letter contained in the 2 words.

This code should work:

def are_anagrams(string1: str, string2: str):
    
    if len(string1) != len(string2):
        return False
    if set(string1) != set(string2):
        return False 
    for char in set(string1):
        freq1=0
        freq2=0
        for letter in string1:
            freq1+=letter==char           
        for letter in string2:
            freq2+=letter==char  
        if freq1!=freq2:
            return False
    return True 
2 Likes

Hello @boemer00,

Technically, the answer checking should fail if you happen to mix case, but it doesn’t for now!

This modified version works for mixed-cases:

test1_string1 = 'aabbb'
test1_string2 = 'aAbbb'

def are_anagrams(string1, string2):
    if len(string1) != len(string2):
        return False

    s1 = string1.lower()
    s2 = string2.lower()
    
    for c in set(s1):  # One set is enough.
        if s1.count(c) != s2.count(c):  # Find/compare all occurences of character "c"
            return False
    return True

are_anagrams(test1_string1, test1_string2)

2 Likes

Very nice, @veena.sanjeeve.line ! I did not think about using count !
I thought to lower the strings before too, but I finally removed thinking it would have been maybe “too much”. But you are absolutly right. If we want to cover definitively all cases, there is another exception (false positive) we could be aware of:

s1 = string1.lower()
s2 = string2.lower()
if s1==s2:
  return False

Of course technically a word is always an anagram to iself, but don’t you think we should discard it as false positive ? (Or force the function to only accept two different words.)

1 Like

@WilfriedF I’m glad you pointed that out!
I’m thinking that should be an early false positive check as an anagram should yield another word.

Apparently, there’s a nice explanation on english.stackexchange.

2 Likes

Good link !

I think there is not any unanimous consensus on whether to include or exclude the trivial examples.

No clear consensus! Finally, up to the coder to decide if he wants to exclude the trivial anagram or not.

1 Like