From c4896b92d986fd8e80e119cb8182e54309cb75ba Mon Sep 17 00:00:00 2001 From: fatima-malik99 <7223fatimamalik@gmail.com> Date: Sat, 11 Jan 2025 11:23:38 +0500 Subject: [PATCH 01/15] Added solution in function file --- solutions/valid_anagram.py | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 solutions/valid_anagram.py diff --git a/solutions/valid_anagram.py b/solutions/valid_anagram.py new file mode 100644 index 000000000..e48d94f31 --- /dev/null +++ b/solutions/valid_anagram.py @@ -0,0 +1,21 @@ +def valid_anagram(str1: str, str2: str) -> bool: + + assert isinstance(str1, str), "First argument must be a string" + assert isinstance(str2, str), "Second argument must be a string" + + if len(str1) != len(str2): + return False + + char_count = {} + + for char in str1: + char_count[char] = char_count.get(char, 0) + 1 + + for char in str2: + if char not in char_count: + return False + char_count[char] -= 1 + if char_count[char] == 0: + del char_count[char] + + return len(char_count) == 0 From 07d517503cfed3f8393afb55c52554f90b25f38c Mon Sep 17 00:00:00 2001 From: fatima-malik99 <7223fatimamalik@gmail.com> Date: Sat, 11 Jan 2025 12:51:36 +0500 Subject: [PATCH 02/15] Added function docstring with doctests and comments --- solutions/valid_anagram.py | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/solutions/valid_anagram.py b/solutions/valid_anagram.py index e48d94f31..bef727b96 100644 --- a/solutions/valid_anagram.py +++ b/solutions/valid_anagram.py @@ -1,16 +1,42 @@ def valid_anagram(str1: str, str2: str) -> bool: - + """ + Determines if two strings are anagrams of each other. + + Args: + str1: First string to compare + Must be a string containing any characters + str2: Second string to compare + Must be a string containing any characters + + Returns: + bool: True if strings are anagrams, False otherwise + + Raises: + AssertionError: If either input is not a string + + Examples: + >>> valid_anagram("listen", "silent") + True + >>> valid_anagram("hello", "world") + False + >>> valid_anagram("", "") + True + """ assert isinstance(str1, str), "First argument must be a string" assert isinstance(str2, str), "Second argument must be a string" + # Quick check for length equality if len(str1) != len(str2): return False + # Create character frequency dictionary char_count = {} + # Count characters in first string for char in str1: char_count[char] = char_count.get(char, 0) + 1 + # Check characters in second string for char in str2: if char not in char_count: return False From 50deab6bba97b29804d07f13c92bb798989b869c Mon Sep 17 00:00:00 2001 From: fatima-malik99 <7223fatimamalik@gmail.com> Date: Sat, 11 Jan 2025 13:36:20 +0500 Subject: [PATCH 03/15] Added module docstring --- solutions/valid_anagram.py | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/solutions/valid_anagram.py b/solutions/valid_anagram.py index bef727b96..e13e2f640 100644 --- a/solutions/valid_anagram.py +++ b/solutions/valid_anagram.py @@ -1,3 +1,14 @@ +""" +Module for checking if two strings are valid anagrams. + +This module provides functionality to determine if two strings are anagrams +of each other (contain exactly the same characters with the same frequency). + +Created on: 2025-01-11 +@author: Fatima +""" + + def valid_anagram(str1: str, str2: str) -> bool: """ Determines if two strings are anagrams of each other. @@ -22,21 +33,23 @@ def valid_anagram(str1: str, str2: str) -> bool: >>> valid_anagram("", "") True """ + + # Ensure both inputs are strings assert isinstance(str1, str), "First argument must be a string" assert isinstance(str2, str), "Second argument must be a string" - # Quick check for length equality + # Anagrams must be of equal length if len(str1) != len(str2): return False # Create character frequency dictionary char_count = {} - # Count characters in first string + # Count occurrences of each character in str1 for char in str1: char_count[char] = char_count.get(char, 0) + 1 - # Check characters in second string + # Decrease character counts and check if any character is missing or overused for char in str2: if char not in char_count: return False @@ -44,4 +57,5 @@ def valid_anagram(str1: str, str2: str) -> bool: if char_count[char] == 0: del char_count[char] + # If all character counts are zero, the strings are anagrams return len(char_count) == 0 From f8a91b2a2a1e8c45821af72c59c7a6eeeaa40e88 Mon Sep 17 00:00:00 2001 From: fatima-malik99 <7223fatimamalik@gmail.com> Date: Sat, 11 Jan 2025 13:58:06 +0500 Subject: [PATCH 04/15] Added test file with some tests --- solutions/tests/test_valid_anagram.py | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 solutions/tests/test_valid_anagram.py diff --git a/solutions/tests/test_valid_anagram.py b/solutions/tests/test_valid_anagram.py new file mode 100644 index 000000000..3a603a5b0 --- /dev/null +++ b/solutions/tests/test_valid_anagram.py @@ -0,0 +1,22 @@ +import unittest +from solutions.valid_anagram import valid_anagram + + +class Testvalidanagram(unittest.TestCase): + """Test cases for valid_anagram function.""" + + def test_basic_anagram(self): + """It should identify basic anagrams correctly.""" + self.assertTrue(valid_anagram("listen", "silent")) + + def test_not_anagram(self): + """It should return False for non-anagram strings.""" + self.assertFalse(valid_anagram("hello", "world")) + + def test_same_word(self): + """It should identify same words as anagrams.""" + self.assertTrue(valid_anagram("word", "word")) + + +if __name__ == "__main__": + unittest.main() From 01637863b276856c82f640eda7ac07ea9a25fae4 Mon Sep 17 00:00:00 2001 From: fatima-malik99 <7223fatimamalik@gmail.com> Date: Sat, 11 Jan 2025 14:58:58 +0500 Subject: [PATCH 05/15] Added 8 more tests --- solutions/tests/test_valid_anagram.py | 33 +++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/solutions/tests/test_valid_anagram.py b/solutions/tests/test_valid_anagram.py index 3a603a5b0..0296b6ef8 100644 --- a/solutions/tests/test_valid_anagram.py +++ b/solutions/tests/test_valid_anagram.py @@ -17,6 +17,39 @@ def test_same_word(self): """It should identify same words as anagrams.""" self.assertTrue(valid_anagram("word", "word")) + def test_empty_string(self): + """It should identify empty strings as amagrams.""" + self.assertTrue(valid_anagram("", "")) + + def test_case_sensitive(self): + """It should be case sensitive in comparison""" + self.assertFalse(valid_anagram("fatima", "Fatima")) + + def test_string_with_numbers(self): + """It should identify numbers in a string as anagram""" + self.assertTrue(valid_anagram("mad1ha", "aah1dm")) + + def test_repeated_characters(self): + """It should handle strings with repeated characters.""" + self.assertTrue(valid_anagram("aaccbb", "ccaabb")) + + def test_special_characters(self): + """It should handle special characters correctly.""" + self.assertTrue(valid_anagram("a!b@", "b@a!")) + + def test_spaces(self): + """It should handle spaces as regular characters.""" + self.assertTrue(valid_anagram("a b", "b a")) + + def test_non_string_first_arg(self): + """It should raise AssertionError for non-string first argument.""" + with self.assertRaises(AssertionError): + valid_anagram(123, "hello") + + def test_non_string_second_arg(self): + """It should raise AssertionError for non-string second argument.""" + with self.assertRaises(AssertionError): + valid_anagram("hello", None) if __name__ == "__main__": unittest.main() From c008a28371531ee7fb55541d10d8653d9d8f7ca6 Mon Sep 17 00:00:00 2001 From: fatima-malik99 <7223fatimamalik@gmail.com> Date: Sat, 11 Jan 2025 15:12:06 +0500 Subject: [PATCH 06/15] Added module docstring and formating with ruff --- solutions/tests/test_valid_anagram.py | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/solutions/tests/test_valid_anagram.py b/solutions/tests/test_valid_anagram.py index 0296b6ef8..9d807da23 100644 --- a/solutions/tests/test_valid_anagram.py +++ b/solutions/tests/test_valid_anagram.py @@ -1,3 +1,23 @@ +""" +Unit tests for validating the valid_anagram function. + +Test Categories: + - Standard Cases: Basic anagram checking with various words + - Edge Cases: Empty strings and repeated characters + - Special Cases: Strings with numbers, spaces, and special characters + - Defensive Cases: Invalid input handling + +The tests verify that the function: + - Correctly identifies anagrams + - Handles case sensitivity + - Processes special characters and numbers + - Validates input types + - Manages empty strings and spaces + +Created on: 2025-01-11 +@author: Fatima +""" + import unittest from solutions.valid_anagram import valid_anagram @@ -51,5 +71,6 @@ def test_non_string_second_arg(self): with self.assertRaises(AssertionError): valid_anagram("hello", None) + if __name__ == "__main__": unittest.main() From d345f070fc5cefe5513b999034b19f8843ab3e95 Mon Sep 17 00:00:00 2001 From: fatima-malik99 <7223fatimamalik@gmail.com> Date: Sun, 12 Jan 2025 05:42:49 +0500 Subject: [PATCH 07/15] Reorganized test cases --- solutions/tests/test_valid_anagram.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/solutions/tests/test_valid_anagram.py b/solutions/tests/test_valid_anagram.py index 9d807da23..84824cb13 100644 --- a/solutions/tests/test_valid_anagram.py +++ b/solutions/tests/test_valid_anagram.py @@ -64,12 +64,12 @@ def test_spaces(self): def test_non_string_first_arg(self): """It should raise AssertionError for non-string first argument.""" with self.assertRaises(AssertionError): - valid_anagram(123, "hello") + valid_anagram(1998, "Jola") def test_non_string_second_arg(self): """It should raise AssertionError for non-string second argument.""" with self.assertRaises(AssertionError): - valid_anagram("hello", None) + valid_anagram("Evan", None) if __name__ == "__main__": From fa7c5222f7e5cc792c2ecac5fc1d852224330d38 Mon Sep 17 00:00:00 2001 From: fatima-malik99 <7223fatimamalik@gmail.com> Date: Mon, 13 Jan 2025 00:41:16 +0500 Subject: [PATCH 08/15] Test class name changed to PascalCase --- solutions/tests/test_valid_anagram.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/solutions/tests/test_valid_anagram.py b/solutions/tests/test_valid_anagram.py index 84824cb13..9b3805b1d 100644 --- a/solutions/tests/test_valid_anagram.py +++ b/solutions/tests/test_valid_anagram.py @@ -22,7 +22,7 @@ from solutions.valid_anagram import valid_anagram -class Testvalidanagram(unittest.TestCase): +class TestvalidAnagram(unittest.TestCase): """Test cases for valid_anagram function.""" def test_basic_anagram(self): From 6c055c9f55740b0780192c856b9467fbef04de66 Mon Sep 17 00:00:00 2001 From: fatima-malik99 <7223fatimamalik@gmail.com> Date: Mon, 13 Jan 2025 00:48:04 +0500 Subject: [PATCH 09/15] Corrected docstring typo in test_empty_string --- solutions/tests/test_valid_anagram.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/solutions/tests/test_valid_anagram.py b/solutions/tests/test_valid_anagram.py index 9b3805b1d..fe6bd0862 100644 --- a/solutions/tests/test_valid_anagram.py +++ b/solutions/tests/test_valid_anagram.py @@ -38,7 +38,7 @@ def test_same_word(self): self.assertTrue(valid_anagram("word", "word")) def test_empty_string(self): - """It should identify empty strings as amagrams.""" + """It should identify empty strings as anagrams.""" self.assertTrue(valid_anagram("", "")) def test_case_sensitive(self): From 054703a812d760ad45fa0be7132381d0c55a6487 Mon Sep 17 00:00:00 2001 From: fatima-malik99 <7223fatimamalik@gmail.com> Date: Mon, 13 Jan 2025 01:21:38 +0500 Subject: [PATCH 10/15] Added test for long strings --- solutions/tests/test_valid_anagram.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/solutions/tests/test_valid_anagram.py b/solutions/tests/test_valid_anagram.py index fe6bd0862..2abddda47 100644 --- a/solutions/tests/test_valid_anagram.py +++ b/solutions/tests/test_valid_anagram.py @@ -60,6 +60,12 @@ def test_special_characters(self): def test_spaces(self): """It should handle spaces as regular characters.""" self.assertTrue(valid_anagram("a b", "b a")) + + def test_long_strings(self): + """It should handle long strings with repeated characters efficiently.""" + first_string = "a" * 10000 + "b" * 5000 + "c" * 3000 + second_string = "c" * 3000 + "a" * 10000 + "b" * 5000 + self.assertTrue(valid_anagram(first_string, second_string)) def test_non_string_first_arg(self): """It should raise AssertionError for non-string first argument.""" From 0a87597746b759c5cc766cdb481a17211f549e4d Mon Sep 17 00:00:00 2001 From: fatima-malik99 <7223fatimamalik@gmail.com> Date: Mon, 13 Jan 2025 01:25:37 +0500 Subject: [PATCH 11/15] Resolved errors with ruff formating --- solutions/tests/test_valid_anagram.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/solutions/tests/test_valid_anagram.py b/solutions/tests/test_valid_anagram.py index 2abddda47..40c6aea7b 100644 --- a/solutions/tests/test_valid_anagram.py +++ b/solutions/tests/test_valid_anagram.py @@ -60,7 +60,7 @@ def test_special_characters(self): def test_spaces(self): """It should handle spaces as regular characters.""" self.assertTrue(valid_anagram("a b", "b a")) - + def test_long_strings(self): """It should handle long strings with repeated characters efficiently.""" first_string = "a" * 10000 + "b" * 5000 + "c" * 3000 From 069d25bee3db4155e9c662b9ee3e8cbab28d87b4 Mon Sep 17 00:00:00 2001 From: fatima-malik99 <7223fatimamalik@gmail.com> Date: Mon, 13 Jan 2025 01:33:29 +0500 Subject: [PATCH 12/15] Resolved errors with ruff formating --- solutions/tests/test_valid_anagram.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/solutions/tests/test_valid_anagram.py b/solutions/tests/test_valid_anagram.py index 40c6aea7b..c40f36505 100644 --- a/solutions/tests/test_valid_anagram.py +++ b/solutions/tests/test_valid_anagram.py @@ -60,7 +60,7 @@ def test_special_characters(self): def test_spaces(self): """It should handle spaces as regular characters.""" self.assertTrue(valid_anagram("a b", "b a")) - + def test_long_strings(self): """It should handle long strings with repeated characters efficiently.""" first_string = "a" * 10000 + "b" * 5000 + "c" * 3000 From 208dffd26514253b9dad94a782d3308354eb7f18 Mon Sep 17 00:00:00 2001 From: fatima-malik99 <7223fatimamalik@gmail.com> Date: Mon, 13 Jan 2025 01:50:17 +0500 Subject: [PATCH 13/15] Improved function's docstring --- solutions/valid_anagram.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/solutions/valid_anagram.py b/solutions/valid_anagram.py index e13e2f640..6a0523b96 100644 --- a/solutions/valid_anagram.py +++ b/solutions/valid_anagram.py @@ -11,7 +11,7 @@ def valid_anagram(str1: str, str2: str) -> bool: """ - Determines if two strings are anagrams of each other. + Returns True if two strings are anagrams, otherwise False. Args: str1: First string to compare From 4f6b34b9cac588d376f5c4e77286883609f5a54f Mon Sep 17 00:00:00 2001 From: fatima-malik99 <7223fatimamalik@gmail.com> Date: Mon, 13 Jan 2025 02:21:22 +0500 Subject: [PATCH 14/15] Improved variable names --- solutions/valid_anagram.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/solutions/valid_anagram.py b/solutions/valid_anagram.py index 6a0523b96..835f25386 100644 --- a/solutions/valid_anagram.py +++ b/solutions/valid_anagram.py @@ -9,14 +9,14 @@ """ -def valid_anagram(str1: str, str2: str) -> bool: +def valid_anagram(first_word: str, second_word: str) -> bool: """ Returns True if two strings are anagrams, otherwise False. Args: - str1: First string to compare + first_word: First string to compare Must be a string containing any characters - str2: Second string to compare + second_word: Second string to compare Must be a string containing any characters Returns: @@ -35,22 +35,22 @@ def valid_anagram(str1: str, str2: str) -> bool: """ # Ensure both inputs are strings - assert isinstance(str1, str), "First argument must be a string" - assert isinstance(str2, str), "Second argument must be a string" + assert isinstance(first_word, str), "First argument must be a string" + assert isinstance(second_word, str), "Second argument must be a string" # Anagrams must be of equal length - if len(str1) != len(str2): + if len(first_word) != len(second_word): return False # Create character frequency dictionary char_count = {} # Count occurrences of each character in str1 - for char in str1: + for char in first_word: char_count[char] = char_count.get(char, 0) + 1 # Decrease character counts and check if any character is missing or overused - for char in str2: + for char in second_word: if char not in char_count: return False char_count[char] -= 1 From ea58a60d4b97484617fa072197e9551baeb4913c Mon Sep 17 00:00:00 2001 From: fatima-malik99 <7223fatimamalik@gmail.com> Date: Mon, 13 Jan 2025 02:30:40 +0500 Subject: [PATCH 15/15] Improved order or test cases --- solutions/tests/test_valid_anagram.py | 34 +++++++++++++++------------ 1 file changed, 19 insertions(+), 15 deletions(-) diff --git a/solutions/tests/test_valid_anagram.py b/solutions/tests/test_valid_anagram.py index c40f36505..476c342bd 100644 --- a/solutions/tests/test_valid_anagram.py +++ b/solutions/tests/test_valid_anagram.py @@ -22,9 +22,10 @@ from solutions.valid_anagram import valid_anagram -class TestvalidAnagram(unittest.TestCase): +class TestValidAnagram(unittest.TestCase): """Test cases for valid_anagram function.""" + # Standard Cases def test_basic_anagram(self): """It should identify basic anagrams correctly.""" self.assertTrue(valid_anagram("listen", "silent")) @@ -37,22 +38,30 @@ def test_same_word(self): """It should identify same words as anagrams.""" self.assertTrue(valid_anagram("word", "word")) - def test_empty_string(self): - """It should identify empty strings as anagrams.""" - self.assertTrue(valid_anagram("", "")) - def test_case_sensitive(self): - """It should be case sensitive in comparison""" + """It should be case sensitive in comparison.""" self.assertFalse(valid_anagram("fatima", "Fatima")) - def test_string_with_numbers(self): - """It should identify numbers in a string as anagram""" - self.assertTrue(valid_anagram("mad1ha", "aah1dm")) + # Edge Cases + def test_empty_string(self): + """It should identify empty strings as anagrams.""" + self.assertTrue(valid_anagram("", "")) def test_repeated_characters(self): """It should handle strings with repeated characters.""" self.assertTrue(valid_anagram("aaccbb", "ccaabb")) + def test_long_strings(self): + """It should handle long strings with repeated characters efficiently.""" + first_string = "a" * 10000 + "b" * 5000 + "c" * 3000 + second_string = "c" * 3000 + "a" * 10000 + "b" * 5000 + self.assertTrue(valid_anagram(first_string, second_string)) + + # Special Cases + def test_string_with_numbers(self): + """It should identify numbers in a string as anagram.""" + self.assertTrue(valid_anagram("mad1ha", "aah1dm")) + def test_special_characters(self): """It should handle special characters correctly.""" self.assertTrue(valid_anagram("a!b@", "b@a!")) @@ -61,12 +70,7 @@ def test_spaces(self): """It should handle spaces as regular characters.""" self.assertTrue(valid_anagram("a b", "b a")) - def test_long_strings(self): - """It should handle long strings with repeated characters efficiently.""" - first_string = "a" * 10000 + "b" * 5000 + "c" * 3000 - second_string = "c" * 3000 + "a" * 10000 + "b" * 5000 - self.assertTrue(valid_anagram(first_string, second_string)) - + # Defensive Cases def test_non_string_first_arg(self): """It should raise AssertionError for non-string first argument.""" with self.assertRaises(AssertionError):