Learn how to write an algorithm that checks if two strings are anagrams of each other in JavaScript, Kotlin, Python, and Go with our straightforward examples.
Contents
- Problem Statement
- Anagrams Explained
- Approach Explanation and Pseudocode
- JavaScript Implementation
- Python Implementation
- Kotlin Implementation
- Go Implementation
- Round Up
Problem Statement
Write a function that checks if two strings of text are anagrams of each other. The function should take as input a source
and target
string and return a boolean - true
if the words are anagrams or false
if the words are not anagrams.
Anagrams Explained
Let’s first cover what an anagram is for those unsure. An anagram is a word or phrase that is formed by rearranging the letters of another word or phrase. Anagrams can either be a perfect anagram that uses all letters of the existing word exactly once or a smaller substring of the existing word.
For example, “smile”, “slime”, “limes”, and “miles” are all perfect anagrams of each other as each letter is used once across all words. Similarly, “large” and “glare” would fit this definition too.
For this exercise, we’ll make some assumptions on the problem statement.
- Firstly, we’ll be checking for perfect anagrams only.
- Secondly, we will only consider letters A-Z.
- Finally, we will treat upper and lower case letters as not equal.
Approach Explanation and Pseudocode
To find out if two strings are anagrams of each other, we need to count how many times the letters in each string are used (aka the letter frequency). Then, we’ll check if each string uses the same characters the same number of times. If they do, great we have an anagram, otherwise we do not.
The pseudocode for this algorithm would be:
- If the length of the source word does not equal the length of the target word: return
false
. - Initialise a map data structure whose keys are the characters of the string and values the count of that character within the string.
- For each letter in the source word, set its initiate count to 1 or increment its value by 1 if it has already been seen.
- For each letter of the target word, use the character to index into the map of letter counts.
- If the count is 0, return
false
as the character was not present in the source word. - Otherwise, decrease the count by 1.
- If the count is 0, return
- For each value in the map, if the count does not equal 0, return
false
as the frequency of characters doesn’t match. - If all values were 0, return
true
as the strings were perfect anagrams.
Let’s turn this pseudocode into concrete examples in a few programming languages. Below are implementations of an anagramChecker
function in JavaScript, Python, Kotlin, and Go.
JavaScript Implementation
export const anagramChecker = (source, target) => {
if (source.length !== target.length) {
return false;
}
const charCounter = new Map();
for (let i = 0; i < source.length; i++) {
const currentCount = charCounter.get(source[i]) ?? 0;
charCounter.set(source[i], currentCount + 1);
}
for (let i = 0; i < target.length; i++) {
const currentCount = charCounter.get(target[i]) ?? 0;
if (currentCount === 0) {
return false;
}
charCounter.set(target[i], currentCount - 1);
}
for (const value of charCounter.values()) {
if (value !== 0) {
return false;
}
}
return true;
};
Python Implementation
Our Python implementation takes advantage of the Counter object from the Python standard collections library. This can take as input an iterable like a string and automatically creates a dictionary containing the strings characters as keys and counts as values.
from collections import Counter
def anagram_checker(source: str, target: str) -> bool:
if len(source) != len(target):
return False
char_counter = Counter(source)
for char in target:
current_count = char_counter[char]
if current_count == 0:
return False
char_counter[char] = current_count - 1
for value in char_counter.values():
if value != 0:
return False
return True
Kotlin Implementation
fun anagramChecker(source: String, target: String): Boolean {
if (source.length != target.length) {
return false;
}
val charCounter = source
.split("")
.groupingBy { it }
.eachCount()
.toMutableMap()
for (char in target.split("")) {
val currentCount = charCounter.getOrDefault(char, 0)
if (currentCount == 0) {
return false
}
charCounter[char] = currentCount.minus(1)
}
for (value in charCounter.values) {
if (value != 0) {
return false
}
}
return true
}
Go Implementation
func anagramChecker(source string, target string) bool {
if len(source) != len(target) {
return false
}
sourceMap := make(map[rune]int)
targetMap := make(map[rune]int)
for _, letter := range source {
sourceMap[letter]++
}
for _, letter := range target {
targetMap[letter]++
}
for sourceLetter, sourceCount := range sourceMap {
if targetCount, ok := targetMap[sourceLetter]; !ok || sourceCount != targetCount {
return false
}
}
return true
}
Round Up
That’s all of our implementations finished. Hopefully, you are now able to take these examples away to extend off or use them in your projects. A great example that uses a implementation similar to those in this article is our Anagram Checker.
Looking for more tutorials on anagrams? Check out our website developer section where we publish useful information for software engineers in the word game space.
Did you find this article helpful?