diff --git a/problems/medium/group-anagrams/solution.py b/problems/medium/group-anagrams/solution.py new file mode 100644 index 0000000..1b0a1d0 --- /dev/null +++ b/problems/medium/group-anagrams/solution.py @@ -0,0 +1,38 @@ +""" +Group Anagrams + +You're building a word game assistant that groups words which are +anagrams of each other. Two words are anagrams if they contain +the same letters in any order. + +Given a list of strings, group the anagrams together. Each group +should be a sorted list of words, and the groups themselves should +be sorted by their first element. + +Example 1: + Input: words = ["eat", "tea", "tan", "ate", "nat", "bat"] + Output: [["ate", "eat", "tea"], ["bat"], ["nat", "tan"]] + Explanation: "eat", "tea", and "ate" are all anagrams of each other + +Example 2: + Input: words = ["hello", "world"] + Output: [["hello"], ["world"]] + Explanation: No words are anagrams of each other + +Example 3: + Input: words = ["", ""] + Output: [["", ""]] + Explanation: Empty strings are anagrams of each other + +Constraints: + - 0 <= len(words) <= 10^4 + - 0 <= len(words[i]) <= 100 + - Words consist of lowercase English letters + - Each group is sorted alphabetically + - Groups are sorted by their first element +""" + + +def group_anagrams(words: list[str]) -> list[list[str]]: + """Return a list of anagram groups, each sorted, groups sorted by first element.""" + pass # Your implementation here diff --git a/problems/medium/group-anagrams/tests.py b/problems/medium/group-anagrams/tests.py new file mode 100644 index 0000000..4ec0c84 --- /dev/null +++ b/problems/medium/group-anagrams/tests.py @@ -0,0 +1,45 @@ +"""Tests for group-anagrams.""" +import pytest +from solution import group_anagrams + + +class TestBasicCases: + """Test basic functionality with typical inputs.""" + + def test_example_one(self): + """Test first example from problem description.""" + assert group_anagrams(["eat", "tea", "tan", "ate", "nat", "bat"]) == [ + ["ate", "eat", "tea"], ["bat"], ["nat", "tan"] + ] + + def test_example_two(self): + """Test second example with no anagrams.""" + assert group_anagrams(["hello", "world"]) == [["hello"], ["world"]] + + def test_example_three(self): + """Test third example with empty strings.""" + assert group_anagrams(["", ""]) == [["", ""]] + + def test_single_word(self): + """Test with a single word.""" + assert group_anagrams(["abc"]) == [["abc"]] + + +class TestEdgeCases: + """Test edge cases and boundary conditions.""" + + def test_empty_list(self): + """Test with no words.""" + assert group_anagrams([]) == [] + + def test_all_same_word(self): + """Test with identical words.""" + assert group_anagrams(["abc", "abc", "abc"]) == [["abc", "abc", "abc"]] + + def test_single_character_words(self): + """Test with single character strings.""" + assert group_anagrams(["a", "b", "a"]) == [["a", "a"], ["b"]] + + def test_different_lengths_not_grouped(self): + """Test that words of different lengths are never grouped.""" + assert group_anagrams(["ab", "abc", "ba"]) == [["ab", "ba"], ["abc"]] diff --git a/problems/medium/merge-intervals/solution.py b/problems/medium/merge-intervals/solution.py new file mode 100644 index 0000000..84a6f12 --- /dev/null +++ b/problems/medium/merge-intervals/solution.py @@ -0,0 +1,35 @@ +""" +Merge Intervals + +You're building a calendar app that needs to consolidate overlapping +meetings. Given a list of time intervals represented as [start, end] +pairs, merge all overlapping intervals and return the resulting list +of non-overlapping intervals sorted by start time. + +Two intervals overlap if one starts before the other ends. + +Example 1: + Input: intervals = [[1, 3], [2, 6], [8, 10], [15, 18]] + Output: [[1, 6], [8, 10], [15, 18]] + Explanation: [1, 3] and [2, 6] overlap, merged into [1, 6] + +Example 2: + Input: intervals = [[1, 4], [4, 5]] + Output: [[1, 5]] + Explanation: Intervals sharing an endpoint are considered overlapping + +Example 3: + Input: intervals = [[1, 4], [0, 4]] + Output: [[0, 4]] + Explanation: Input is not necessarily sorted + +Constraints: + - 0 <= len(intervals) <= 10^4 + - Each interval is [start, end] where start <= end + - Start and end are non-negative integers +""" + + +def merge(intervals: list[list[int]]) -> list[list[int]]: + """Return a list of merged non-overlapping intervals sorted by start.""" + pass # Your implementation here diff --git a/problems/medium/merge-intervals/tests.py b/problems/medium/merge-intervals/tests.py new file mode 100644 index 0000000..6f41609 --- /dev/null +++ b/problems/medium/merge-intervals/tests.py @@ -0,0 +1,47 @@ +"""Tests for merge-intervals.""" +import pytest +from solution import merge + + +class TestBasicCases: + """Test basic functionality with typical inputs.""" + + def test_example_one(self): + """Test first example from problem description.""" + assert merge([[1, 3], [2, 6], [8, 10], [15, 18]]) == [[1, 6], [8, 10], [15, 18]] + + def test_example_two(self): + """Test second example from problem description.""" + assert merge([[1, 4], [4, 5]]) == [[1, 5]] + + def test_example_three(self): + """Test third example with unsorted input.""" + assert merge([[1, 4], [0, 4]]) == [[0, 4]] + + def test_no_overlaps(self): + """Test intervals with no overlaps.""" + assert merge([[1, 2], [5, 6], [9, 10]]) == [[1, 2], [5, 6], [9, 10]] + + +class TestEdgeCases: + """Test edge cases and boundary conditions.""" + + def test_empty_list(self): + """Test with no intervals.""" + assert merge([]) == [] + + def test_single_interval(self): + """Test with exactly one interval.""" + assert merge([[1, 5]]) == [[1, 5]] + + def test_all_overlapping(self): + """Test when all intervals merge into one.""" + assert merge([[1, 4], [2, 5], [3, 6]]) == [[1, 6]] + + def test_contained_interval(self): + """Test when one interval is fully inside another.""" + assert merge([[1, 10], [3, 5]]) == [[1, 10]] + + def test_unsorted_input(self): + """Test with input not sorted by start time.""" + assert merge([[5, 6], [1, 3], [2, 4]]) == [[1, 4], [5, 6]] diff --git a/problems/medium/valid-parentheses/solution.py b/problems/medium/valid-parentheses/solution.py new file mode 100644 index 0000000..5814a85 --- /dev/null +++ b/problems/medium/valid-parentheses/solution.py @@ -0,0 +1,37 @@ +""" +Valid Parentheses + +You're building a syntax checker for a code editor. Before running +any code, the editor needs to verify that all brackets are properly +matched and nested. Given a string containing only parentheses, +square brackets, and curly braces, determine if the input is valid. + +A string is valid if: + - Open brackets are closed by the same type of bracket + - Open brackets are closed in the correct order + - Every close bracket has a corresponding open bracket + +Example 1: + Input: s = "([]){}" + Output: True + Explanation: All brackets are properly matched and nested + +Example 2: + Input: s = "([)]" + Output: False + Explanation: The square bracket closes before the parenthesis + +Example 3: + Input: s = "{{" + Output: False + Explanation: Opening braces are never closed + +Constraints: + - 0 <= len(s) <= 10^4 + - s consists only of characters '(){}[]' +""" + + +def is_valid(s: str) -> bool: + """Return True if the bracket string is valid, False otherwise.""" + pass # Your implementation here diff --git a/problems/medium/valid-parentheses/tests.py b/problems/medium/valid-parentheses/tests.py new file mode 100644 index 0000000..8d43c64 --- /dev/null +++ b/problems/medium/valid-parentheses/tests.py @@ -0,0 +1,51 @@ +"""Tests for valid-parentheses.""" +import pytest +from solution import is_valid + + +class TestBasicCases: + """Test basic functionality with typical inputs.""" + + def test_example_one(self): + """Test first example from problem description.""" + assert is_valid("([]){}") is True + + def test_example_two(self): + """Test second example from problem description.""" + assert is_valid("([)]") is False + + def test_example_three(self): + """Test third example from problem description.""" + assert is_valid("{{") is False + + def test_simple_pairs(self): + """Test simple matched pairs.""" + assert is_valid("()") is True + assert is_valid("[]") is True + assert is_valid("{}") is True + + +class TestEdgeCases: + """Test edge cases and boundary conditions.""" + + def test_empty_string(self): + """Test with empty input.""" + assert is_valid("") is True + + def test_single_bracket(self): + """Test with a single unmatched bracket.""" + assert is_valid("(") is False + assert is_valid("]") is False + + def test_deeply_nested(self): + """Test with deeply nested brackets.""" + assert is_valid("{[({[]})]}") is True + + def test_close_before_open(self): + """Test closing bracket appearing before any opener.""" + assert is_valid(")(") is False + + def test_mismatched_types(self): + """Test opening one type and closing another.""" + assert is_valid("{)") is False + assert is_valid("[}") is False