It’s basically creating a list of the number of presences of each letter and increment on the first word and decrement on the second, the result should be that first there’s no negative numbers, and second the sum should be zero.

ifelse loop logic within the function:

# 1) if length of the two strings do not match, then the strings are NOT anagrams. Stop checking. (iteration = 1) # 2) if the number of unique letters in the two strings are NOT equal, then strings are NOT anagrams. Stop checking. (iteration = 2) # 3) Convert to upper case and Sort the strings. The two strings should match at every index. If not, they are not anagrams. Stop checking. (iteration = 2 + length(string1) )

Like last week, I thought I would take a slightly more functional approach to this challenge, and like most people, I figured comparing two sorted lists is the way to go. While a lot of people just used Python’s sorted() function, I figured that if I want to make things more interesting, I could implement my own quicksort function. The quicksort I used is inspired by the elegant Haskell implementation of quicksort. Here it is:

First, I define the quickSort function, which takes a pivot (the first element in a word or list) and then creates two lists, one of which contains all the values in the list after the pivot greater than or equal to the pivot, and one of those values less than the pivot. Then, it puts the pivot between these lists and sorts both of these lists using the same method recursively.

The actual anagram function is pretty straightforward. All that this does is convert the supplied words into a usable format, sorts them, and compares them to see if they are the same. If they are, then they are anagrams, otherwise they are not.

Finally, let’s talk about efficiency. I realize that this is definitely not O(M + N), since it uses quicksort, which is at best O(NlogN). This program is probably slower than this, though, due to the other stuff involved, but the purpose of this exercise for me is to practice my functional programming skills with Python, so I don’t mind the slowness.

A solution in Python which has a O(n+m) time complexity. It iterates through the first string and counts up the occurences of each character, and then does the same for the second string but decrements the count instead. If the two strings are anagrams then the count for every character should be 0.

Decided to handle all 128 ASCII codes so that the function works with all ASCII characters and not just capital letters, and it removes the need to subtract a base value from each of the ASCII values to convert it to a 0-based index.

def is_anagram(s1, s2):
# can return 0 immediately if the strings are different lengths
if len(s1) != len(s2):
return 0
# for counting the ASCII characters 0 to 127
counts = [0]*128
# increment the count for each character in the first string
for c in s1:
counts[ord(c)] += 1
# decrement the count for each character in the second string
for c in s2:
counts[ord(c)] -= 1
# the strings are anagrams if all the counts cancel each other out
return 0 if any(counts) else 1

There is a simple optimisation to check that the strings are the same length at the start of the function; if the strings are different lengths then they cannot be anagrams. Would be significant improvement for very big strings.

A totally inconsequential optimisation (but why not) is the use of the any() function instead of sum(). It is ever so slightly faster as it only needs to do a comparison with 0 instead of addition, and it does lazy evaluation, meaning it will return as soon as a non-zero value is found.

Out of interest, I compared the runtime with a solution that use sorting to compare the strings (shown below). The time complexity for sorting is O(n log(n)), but for short strings the function below is faster. The point where the function above is faster is about strings of length 70 on my laptop.

I had this idea as well, but I don't think it works! Just adding up the ASCII values would mean it would see these two strings as anagrams, "AD" and "BC".

I thought maybe you can use the product but it would only work if each letter was represented by a prime number and the calculation of that product would probably make the function slow compared to the other methods, especially for large strings.

My first bit of thinking was to be sure to get the input from the user and prompt them as to what words they would like to compare. I then assigned another set of variables equal to the original input ran through the built-in .upper() function, to guarantee that the function would be handling uppercase letters, as per the challenge rules. Next up was converting the strings into lists with a for loop to iterate through each of the words and append each iterated item to the appropriate list. After assigning the lists to sorted versions of themselves, I then compared the sorted lists to each other and returned 1 for anagrams, and 0 for not anagrams.
Code below for those who do not wish to follow links:

def anagram():
#ask the user for words to compare
print('What two words would you like to compare and see if they are anagrams?')
print('First word: ')
word1 = str(input())
print('Second word: ')
word2 = str(input())
#converts the strings from the user to uppercase
word1Upper = word1.upper()
word2Upper = word2.upper()
#creation of empty lists for conversion from strings to lists
word1u = []
word2u = []
#for loops do the work of making lists from the strings
for char in word1Upper:
word1u.append(char)
for char in word2Upper:
word2u.append(char)
#sorting the letters into sequential order so that Python can compare the lists
word1u = sorted(word1u)
word2u = sorted(word2u)
#condition that compares the sorted lists to each other to see if they match
if word1u == word2u:
#returns 1 if they match
""" print('anagram')"""
return 1
else:
""" print('not an anagram')"""
#returns 0 if they don't
return 0
#print(word1u, word2u)

Time complexity was not taken into consideration when devising this solution as I’m still definitely a beginner.

My function takes two strings as arguments. It loops through first one and creates a Map object to store frequencies of each letter in string (“letter => occurance” pairs).

Then the function loops through second string decreasing these values - if any value is not already in our Map or the value becomes less than 0, then loop stops because we know the words can’t be anagrams.

In worst case scenario the loop finishes and then function checks if any value in our Map is left greater than 0 - if yes, then the words are not anagrams. Otherwise they are.

I chose Map object, because i needed (key, value) pairs and hence i knew I wanted to iterate over the values it was easier to use Map rather than regular Object. It also provides quick access of values which was exactly what i needed.
The function takes into account that anagrams can have different space character counts. The second for loop stops immediatly if it finds a letter that does not occur in our Map or frequency of this particular letter became greater than it was in the first string.
Time complexity is O(n+m). Tests provided. Thanks for reading!

I decided to use a dictionary to keep track of the letters used in each of the two candidate strings.
For the first candidate string, I increment the letter count,
and for the second candidate string, I decrement the letter count.
If the two candidates are actually anagrams of each other, then all the counts should end up zero.
This can be easily checked with the any() function.

This is my code in python. Anagram detection is made simply counting letters in each string, and if the same letters are equal in both strings, they are anagrams.

I'm using arrays because accessing an array member is faster than accessing a hash member. And using the ascii of the letter made it direct into the array. So, when I find an 'C' in the string, for example, I modify the 3rd element in the array (ord('C') - ord('A')), incrementing it for the first string, and decrementing it for the second. At the end, if the array of counters sums 0, the strings are anagrams.