Skip to content

Commit 36cacfd

Browse files
authored
Create valid_anagram.cpp
1 parent ba0d3ff commit 36cacfd

File tree

1 file changed

+123
-0
lines changed

1 file changed

+123
-0
lines changed

hashing/valid_anagram.cpp

Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
/**
2+
* @file
3+
* @brief Implementation of [Anagram
4+
* Checker](https://en.wikipedia.org/wiki/Anagram) using a hash table.
5+
* @details
6+
* An anagram is a word or phrase formed by rearranging the letters of a
7+
* different word or phrase, typically using all the original letters exactly
8+
* once. This implementation is case-sensitive and considers spaces and
9+
* punctuation as characters.
10+
*
11+
* ### Algorithm
12+
* To check if two strings are anagrams, we first perform a quick check on their
13+
* lengths. If the lengths are different, they cannot be anagrams.
14+
*
15+
* We then use a hash table (std::unordered_map) to store the character counts
16+
* of the first string. We iterate through the first string, mapping each
17+
* character to its frequency.
18+
*
19+
* Next, we iterate through the second string. For each character, we decrement
20+
* its count in the hash table. If a character's count drops below zero, or if
21+
* the character is not found in the map, the strings are not anagrams.
22+
*
23+
* If we successfully iterate through the second string without any issues, the
24+
* two strings are valid anagrams.
25+
*/
26+
27+
#include <cassert> /// for assert
28+
#include <iostream> /// for I/O operations
29+
#include <string> /// for std::string
30+
#include <unordered_map> /// for std::unordered_map (hash table)
31+
32+
/**
33+
* @namespace string_algorithms
34+
* @brief String manipulation algorithms
35+
*/
36+
namespace string_algorithms {
37+
/**
38+
* @namespace anagram_checker
39+
* @brief Functions for checking anagrams
40+
*/
41+
namespace anagram_checker {
42+
43+
/**
44+
* @brief Checks if two strings are valid anagrams of each other.
45+
* @param[in] s1 first string to compare.
46+
* @param[in] s2 second string to compare.
47+
* @return `true` if the strings are anagrams.
48+
* @return `false` if the strings are not anagrams.
49+
*/
50+
bool are_anagrams(const std::string& s1, const std::string& s2) {
51+
// Anagrams must have the same length.
52+
if (s1.length() != s2.length()) {
53+
return false;
54+
}
55+
56+
// Use a hash map to store character frequencies.
57+
std::unordered_map<char, int> counts;
58+
59+
// Count characters in the first string.
60+
for (char c : s1) {
61+
counts[c]++;
62+
}
63+
64+
// Decrement counts using characters from the second string.
65+
for (char c : s2) {
66+
// If a char is not found or its count is already zero, they're not
67+
// anagrams.
68+
if (counts.find(c) == counts.end() || counts[c] == 0) {
69+
return false;
70+
}
71+
counts[c]--;
72+
}
73+
74+
// If we get here, the strings are anagrams.
75+
return true;
76+
}
77+
78+
} // namespace anagram_checker
79+
} // namespace string_algorithms
80+
81+
/**
82+
* @brief Self-test implementations for the anagram checker.
83+
* @returns void
84+
*/
85+
static void test() {
86+
// Test case 1: Basic valid anagrams
87+
assert(string_algorithms::anagram_checker::are_anagrams("listen", "silent"));
88+
assert(string_algorithms::anagram_checker::are_anagrams("triangle",
89+
"integral"));
90+
91+
// Test case 2: Valid anagrams with spaces
92+
assert(string_algorithms::anagram_checker::are_anagrams("a gentleman",
93+
"elegant man"));
94+
95+
// Test case 3: Invalid anagrams (different characters)
96+
assert(!string_algorithms::anagram_checker::are_anagrams("hello", "world"));
97+
98+
// Test case 4: Invalid anagrams (different lengths)
99+
assert(!string_algorithms::anagram_checker::are_anagrams("apple", "apples"));
100+
101+
// Test case 5: Invalid anagrams (different character counts)
102+
assert(!string_algorithms::anagram_checker::are_anagrams("aabbc", "aaabc"));
103+
104+
// Test case 6: Case-sensitive check (should be false)
105+
assert(!string_algorithms::anagram_checker::are_anagrams("Listen", "silent"));
106+
107+
// Test case 7: Empty strings (should be true)
108+
assert(string_algorithms::anagram_checker::are_anagrams("", ""));
109+
110+
// Test case 8: Strings with numbers and symbols
111+
assert(string_algorithms::anagram_checker::are_anagrams("123!!", "!1!23"));
112+
113+
std::cout << "All tests have successfully passed!" << std::endl;
114+
}
115+
116+
/**
117+
* @brief Main function
118+
* @returns 0 on exit
119+
*/
120+
int main() {
121+
test(); // run self-test implementations
122+
return 0;
123+
}

0 commit comments

Comments
 (0)