Search code examples
pythonanagram

anagram code returning wrong answers


I wrote a simple program to test if two words are anagrams(can be rearranged into another word). It seems to work at first, when I tested very different words, like "julio" and "cesar"(Those are my names) and it returned "false", but then I tested words with a difference of only one letter, like "julio" and "julis", but it returned "true". I would like to know what I did wrong. thanks in advance. Sorry for not being too specific in the title, I don't know how to get much more specific than that

PS: The code is written in python if that helps

import time, os

def detector():

    os.system('cls')
    input_1 = input("Enter the First word: \n")
    print("=" * 3 * len(input_1))
    input_2 = input("Enter the second word: \n")
    print("=" * 3 * len(input_1))

    win_index = 0

    input_1 = input_1.lower()
    input_2 = input_2.lower()

    if len(input_1) < len(input_2):
        print("This is not a anagram")
        return False
    else:
        print("\nLoading...\n")
        time.sleep(1)
        for i in range(len(input_1)):
            if input_1[letter_index] in input_2:
                letter_index += 1
                print("This is a anagram")
                return True
                break
            else:
                print("This is not a anagram")
                return False

detector()

Solution

  • Your biggest problem is here:

    if input_1[letter_index] in input_2:
        letter_index += 1
        print("This is a anagram")
        return True
        break
    

    As soon as any letter in input_1 is found in input_2, you're going to print out This is an anagram and then return True, without checking the rest of the letters. So, julio and julis match because j is in julis. In fact, jordan and julis also match because j is in julis.

    The right logic here is that the words are only anagrams if, after you've checked all of them, none of them failed. Since you're going to return False on the first failure, you can just move that to the end of the loop—the only way you'll get past the loop is if you didn't return False.

    Also, letter_index isn't defined anywhere. You probably wanted to use i?

    So, replace your loop with this:

    for i in range(len(input_1)):
        if input_1[i] not in input_2:
            print("This is not a anagram")
            return False
    print("This is an anagram")
    return True
    

    … or, better:

    for letter in input_1:
        if letter not in input_2:
            print("This is not a anagram")
            return False
    print("This is an anagram")
    return True
    

    However, this still isn't right. For example, consider what happens if there are duplicate letters?

    If you check apple against aple, it's going to pass. After all, apple isn't shorter than aple, and every letter in apple is also in aple. To fix that, you need to replace the < check with a != check:

    if len(input_1) != len(input_2):
    

    But this still isn't right. What if you try apple vs. aplee? They're the same length, and every letter in apple is in aplee, and yet they aren't anagrams.

    The only way around this is to make sure you only use each letter from input_2 once.

    You could do that by removing one copy of letter each time you use it:

    for letter in input_1:
        if letter not in input_2:
            print("This is not a anagram")
            return False
        else:
            input_2 = input_2.replace(letter, '', 1)
    print("This is an anagram")
    return True
    

    This now works. But it's pretty clunky. It would be a lot better if you used a better data structure, like a Counter, that's designed for looking up values and decrementing counts:

    from collections import Counter
    
    counts = Counter(input_2)
    for letter in input_1:
        if not counts[letter]:
            print("This is not an anagram")
            return False
        else:
            counts[letter] -= 1
    

    But once you're using a Counter, you can make this even simpler:

    counts_1 = Counter(input_1)
    counts_2 = Counter(input_2)
    if counts_1 == counts_2:
        print("This is an anagram")
        return True
    else:
        print("This is not an anagram")
        return False