From 08038fb57ce7d90710b92fa17e6f4e73a85ca750 Mon Sep 17 00:00:00 2001 From: labrocadabro Date: Thu, 10 Apr 2025 13:19:39 -0300 Subject: [PATCH 01/16] Add string reversal function implementation --- src/string_reversal.py | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 src/string_reversal.py diff --git a/src/string_reversal.py b/src/string_reversal.py new file mode 100644 index 00000000..1b19e92a --- /dev/null +++ b/src/string_reversal.py @@ -0,0 +1,19 @@ +def reverse_string(s: str) -> str: + """ + Reverses the given string. + + Args: + s (str): The input string to be reversed. + + Returns: + str: The reversed string. + + Raises: + TypeError: If the input is not a string. + """ + # Check if input is a string + if not isinstance(s, str): + raise TypeError("Input must be a string") + + # Return the reversed string + return s[::-1] \ No newline at end of file From e7b54d94d091e16af7e013093186b2a254c55596 Mon Sep 17 00:00:00 2001 From: labrocadabro Date: Thu, 10 Apr 2025 13:19:48 -0300 Subject: [PATCH 02/16] Add comprehensive tests for string reversal function --- tests/test_string_reversal.py | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 tests/test_string_reversal.py diff --git a/tests/test_string_reversal.py b/tests/test_string_reversal.py new file mode 100644 index 00000000..ee59e347 --- /dev/null +++ b/tests/test_string_reversal.py @@ -0,0 +1,35 @@ +import pytest +from src.string_reversal import reverse_string + +def test_reverse_string_basic(): + """Test basic string reversal.""" + assert reverse_string("hello") == "olleh" + assert reverse_string("python") == "nohtyp" + +def test_reverse_string_empty(): + """Test reversing an empty string.""" + assert reverse_string("") == "" + +def test_reverse_string_single_char(): + """Test reversing a single character string.""" + assert reverse_string("a") == "a" + +def test_reverse_string_with_spaces(): + """Test reversing a string with spaces.""" + assert reverse_string("hello world") == "dlrow olleh" + +def test_reverse_string_with_special_chars(): + """Test reversing a string with special characters.""" + assert reverse_string("h3llo!") == "!0lleh" + +def test_reverse_string_invalid_input(): + """Test that TypeError is raised for non-string inputs.""" + with pytest.raises(TypeError, match="Input must be a string"): + reverse_string(123) + + with pytest.raises(TypeError, match="Input must be a string"): + reverse_string(None) + +def test_reverse_string_unicode(): + """Test reversing unicode strings.""" + assert reverse_string("café") == "éfac" \ No newline at end of file From b57d9d20fd8da6b5a5fa1b6d78cc39b2b68c0a55 Mon Sep 17 00:00:00 2001 From: labrocadabro Date: Thu, 10 Apr 2025 13:20:02 -0300 Subject: [PATCH 03/16] Fix test case for special characters string reversal --- tests/test_string_reversal.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_string_reversal.py b/tests/test_string_reversal.py index ee59e347..3523691d 100644 --- a/tests/test_string_reversal.py +++ b/tests/test_string_reversal.py @@ -20,7 +20,7 @@ def test_reverse_string_with_spaces(): def test_reverse_string_with_special_chars(): """Test reversing a string with special characters.""" - assert reverse_string("h3llo!") == "!0lleh" + assert reverse_string("h3llo!") == "!oll3h" def test_reverse_string_invalid_input(): """Test that TypeError is raised for non-string inputs.""" From 4896f70ba4352058c295a0c9276b4f48baf264f1 Mon Sep 17 00:00:00 2001 From: labrocadabro Date: Thu, 10 Apr 2025 13:20:40 -0300 Subject: [PATCH 04/16] Implement string reversal without using slice notation --- src/string_reversal.py | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/src/string_reversal.py b/src/string_reversal.py index 1b19e92a..c12c56cf 100644 --- a/src/string_reversal.py +++ b/src/string_reversal.py @@ -1,6 +1,6 @@ def reverse_string(s: str) -> str: """ - Reverses the given string. + Reverses the given string using a manual character-by-character approach. Args: s (str): The input string to be reversed. @@ -11,9 +11,22 @@ def reverse_string(s: str) -> str: Raises: TypeError: If the input is not a string. """ - # Check if input is a string + # Validate input if not isinstance(s, str): raise TypeError("Input must be a string") - # Return the reversed string - return s[::-1] \ No newline at end of file + # Convert string to list of characters for manipulation + chars = list(s) + + # Manual reversal using two-pointer technique + left, right = 0, len(chars) - 1 + while left < right: + # Swap characters + chars[left], chars[right] = chars[right], chars[left] + + # Move pointers + left += 1 + right -= 1 + + # Convert back to string and return + return ''.join(chars) \ No newline at end of file From fad30eae6a3b9bbab55531a34dea748ee4edf7ec Mon Sep 17 00:00:00 2001 From: labrocadabro Date: Thu, 10 Apr 2025 13:20:48 -0300 Subject: [PATCH 05/16] Update tests for comprehensive string reversal testing --- tests/test_string_reversal.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/tests/test_string_reversal.py b/tests/test_string_reversal.py index 3523691d..c0591259 100644 --- a/tests/test_string_reversal.py +++ b/tests/test_string_reversal.py @@ -32,4 +32,8 @@ def test_reverse_string_invalid_input(): def test_reverse_string_unicode(): """Test reversing unicode strings.""" - assert reverse_string("café") == "éfac" \ No newline at end of file + assert reverse_string("café") == "éfac" + +def test_reverse_string_mixed_characters(): + """Test reversing a string with mixed character types.""" + assert reverse_string("a1b2c3!@#") == "#@!3c2b1a" \ No newline at end of file From 5aa8f2447bb1213ee39f05bd1af36aa33e0d9984 Mon Sep 17 00:00:00 2001 From: laura-abro Date: Thu, 10 Apr 2025 13:21:47 -0300 Subject: [PATCH 06/16] Add array flattening function implementation --- src/array_flatten.py | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 src/array_flatten.py diff --git a/src/array_flatten.py b/src/array_flatten.py new file mode 100644 index 00000000..0c148ead --- /dev/null +++ b/src/array_flatten.py @@ -0,0 +1,35 @@ +from typing import List, Union + +def flatten_array(arr: List[Union[int, List]]) -> List[int]: + """ + Recursively flatten a nested list of integers. + + Args: + arr (List[Union[int, List]]): A potentially nested list of integers. + + Returns: + List[int]: A flattened list containing all integers. + + Raises: + TypeError: If the input contains non-integer and non-list elements. + + Examples: + >>> flatten_array([1, [2, 3], 4]) + [1, 2, 3, 4] + >>> flatten_array([1, [2, [3, 4]], 5]) + [1, 2, 3, 4, 5] + >>> flatten_array([]) + [] + """ + flattened = [] + + for item in arr: + if isinstance(item, int): + flattened.append(item) + elif isinstance(item, list): + # Recursively flatten nested lists + flattened.extend(flatten_array(item)) + else: + raise TypeError(f"Invalid input: {item}. Only integers and lists are allowed.") + + return flattened \ No newline at end of file From 3d335033eb30547d968bf55e8c534de11924f5fe Mon Sep 17 00:00:00 2001 From: laura-abro Date: Thu, 10 Apr 2025 13:21:55 -0300 Subject: [PATCH 07/16] Add comprehensive tests for array flattening function --- tests/test_array_flatten.py | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 tests/test_array_flatten.py diff --git a/tests/test_array_flatten.py b/tests/test_array_flatten.py new file mode 100644 index 00000000..9a58213a --- /dev/null +++ b/tests/test_array_flatten.py @@ -0,0 +1,34 @@ +import pytest +from src.array_flatten import flatten_array + +def test_flatten_simple_list(): + """Test flattening a simple list.""" + assert flatten_array([1, 2, 3]) == [1, 2, 3] + +def test_flatten_nested_list(): + """Test flattening a nested list.""" + assert flatten_array([1, [2, 3], 4]) == [1, 2, 3, 4] + +def test_flatten_deeply_nested_list(): + """Test flattening a deeply nested list.""" + assert flatten_array([1, [2, [3, 4]], 5]) == [1, 2, 3, 4, 5] + +def test_flatten_empty_list(): + """Test flattening an empty list.""" + assert flatten_array([]) == [] + +def test_flatten_multiple_nested_lists(): + """Test flattening multiple nested lists.""" + assert flatten_array([[1, 2], [3, [4, 5]], 6]) == [1, 2, 3, 4, 5, 6] + +def test_invalid_input_raises_error(): + """Test that non-integer and non-list inputs raise a TypeError.""" + with pytest.raises(TypeError): + flatten_array([1, 2, "3"]) + + with pytest.raises(TypeError): + flatten_array([1, 2, None]) + +def test_flatten_single_element_list(): + """Test flattening a list with a single nested list.""" + assert flatten_array([1, [2], 3]) == [1, 2, 3] \ No newline at end of file From da7a9ab01ba5836050bc678ac3e954250cd1b964 Mon Sep 17 00:00:00 2001 From: laura-abro Date: Thu, 10 Apr 2025 13:22:01 -0300 Subject: [PATCH 08/16] Add pytest to requirements --- requirements.txt | 1 + 1 file changed, 1 insertion(+) create mode 100644 requirements.txt diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 00000000..a6510db8 --- /dev/null +++ b/requirements.txt @@ -0,0 +1 @@ +pytest==7.3.1 \ No newline at end of file From 57a860734725e36e7739dd9d6c15310f5b446879 Mon Sep 17 00:00:00 2001 From: laura-abro Date: Thu, 10 Apr 2025 13:22:11 -0300 Subject: [PATCH 09/16] Update pytest version --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index a6510db8..b273c397 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1 +1 @@ -pytest==7.3.1 \ No newline at end of file +pytest==8.0.2 \ No newline at end of file From d0b1d56e6cfed5ee5df9ea50a733938dea6ff7ce Mon Sep 17 00:00:00 2001 From: labrocadabro Date: Thu, 10 Apr 2025 13:36:48 -0300 Subject: [PATCH 10/16] Implement binary search function with error handling --- src/binary_search.py | 47 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 src/binary_search.py diff --git a/src/binary_search.py b/src/binary_search.py new file mode 100644 index 00000000..c2758811 --- /dev/null +++ b/src/binary_search.py @@ -0,0 +1,47 @@ +def binary_search(arr, target): + """ + Perform binary search on a sorted array to find the target element. + + Args: + arr (list): A sorted list of comparable elements + target: The element to search for + + Returns: + int: Index of the target element if found, otherwise -1 + + Raises: + TypeError: If input is not a list + ValueError: If the input list is not sorted + """ + # Check input type + if not isinstance(arr, list): + raise TypeError("Input must be a list") + + # Check if list is sorted + if any(arr[i] > arr[i+1] for i in range(len(arr)-1)): + raise ValueError("Input list must be sorted in ascending order") + + # Empty list check + if not arr: + return -1 + + # Binary search implementation + left, right = 0, len(arr) - 1 + + while left <= right: + mid = (left + right) // 2 + + # Found the target + if arr[mid] == target: + return mid + + # Target is in the left half + elif arr[mid] > target: + right = mid - 1 + + # Target is in the right half + else: + left = mid + 1 + + # Target not found + return -1 \ No newline at end of file From 877c2b3c158266584f011d3d6fdd88aaae356fd3 Mon Sep 17 00:00:00 2001 From: labrocadabro Date: Thu, 10 Apr 2025 13:36:57 -0300 Subject: [PATCH 11/16] Add comprehensive tests for binary search function --- tests/test_binary_search.py | 48 +++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) create mode 100644 tests/test_binary_search.py diff --git a/tests/test_binary_search.py b/tests/test_binary_search.py new file mode 100644 index 00000000..074f2714 --- /dev/null +++ b/tests/test_binary_search.py @@ -0,0 +1,48 @@ +import pytest +from src.binary_search import binary_search + +def test_binary_search_normal_case(): + """Test binary search on a normal sorted list""" + arr = [1, 3, 5, 7, 9, 11, 13] + assert binary_search(arr, 7) == 3 + assert binary_search(arr, 1) == 0 + assert binary_search(arr, 13) == 6 + +def test_binary_search_not_found(): + """Test when target is not in the list""" + arr = [1, 3, 5, 7, 9, 11, 13] + assert binary_search(arr, 0) == -1 + assert binary_search(arr, 14) == -1 + +def test_binary_search_empty_list(): + """Test binary search on an empty list""" + assert binary_search([], 5) == -1 + +def test_binary_search_single_element(): + """Test binary search on a single-element list""" + assert binary_search([5], 5) == 0 + assert binary_search([5], 6) == -1 + +def test_binary_search_invalid_input(): + """Test error handling for invalid inputs""" + # Not a list + with pytest.raises(TypeError): + binary_search(123, 5) + + # Unsorted list + with pytest.raises(ValueError): + binary_search([5, 3, 1], 3) + +def test_binary_search_duplicate_elements(): + """Test binary search with duplicate elements""" + arr = [1, 2, 2, 3, 3, 3, 4, 5] + # Returns the first occurrence + assert binary_search(arr, 2) in [1, 2] + assert binary_search(arr, 3) in [3, 4, 5] + +def test_binary_search_negative_numbers(): + """Test binary search with negative numbers""" + arr = [-5, -3, 0, 2, 4, 6] + assert binary_search(arr, -3) == 1 + assert binary_search(arr, 0) == 2 + assert binary_search(arr, 6) == 5 \ No newline at end of file From d1a1cc4651820f2a364f98215f7eb3fb8cabe9f5 Mon Sep 17 00:00:00 2001 From: laura-abro Date: Thu, 10 Apr 2025 13:38:00 -0300 Subject: [PATCH 12/16] Add URL parser function implementation --- src/url_parser.py | 45 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 src/url_parser.py diff --git a/src/url_parser.py b/src/url_parser.py new file mode 100644 index 00000000..33822b31 --- /dev/null +++ b/src/url_parser.py @@ -0,0 +1,45 @@ +from urllib.parse import urlparse, parse_qs +from typing import Dict, Any, Optional + +def parse_url(url: str) -> Dict[str, Any]: + """ + Parse a given URL into its components. + + Args: + url (str): The URL to parse. + + Returns: + Dict[str, Any]: A dictionary containing parsed URL components. + + Raises: + ValueError: If the input URL is invalid or empty. + """ + # Check for empty or None input + if not url or not isinstance(url, str): + raise ValueError("Invalid URL: URL must be a non-empty string") + + try: + # Use urlparse to break down the URL + parsed = urlparse(url) + + # Extract query parameters using parse_qs + query_params = parse_qs(parsed.query) + # Flatten single-item lists to their values + query_params = {k: v[0] if len(v) == 1 else v for k, v in query_params.items()} + + # Construct and return the parsed URL dictionary + return { + 'scheme': parsed.scheme or None, + 'netloc': parsed.netloc or None, + 'path': parsed.path or None, + 'params': parsed.params or None, + 'query': query_params, + 'fragment': parsed.fragment or None, + 'username': parsed.username, + 'password': parsed.password, + 'hostname': parsed.hostname, + 'port': parsed.port + } + except Exception as e: + # Catch any unexpected parsing errors + raise ValueError(f"Error parsing URL: {str(e)}") \ No newline at end of file From 3d38aac5d19653896df53e67a7bcc7f6228e8179 Mon Sep 17 00:00:00 2001 From: laura-abro Date: Thu, 10 Apr 2025 13:38:12 -0300 Subject: [PATCH 13/16] Add comprehensive tests for URL parser function --- tests/test_url_parser.py | 63 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) create mode 100644 tests/test_url_parser.py diff --git a/tests/test_url_parser.py b/tests/test_url_parser.py new file mode 100644 index 00000000..5b32ec44 --- /dev/null +++ b/tests/test_url_parser.py @@ -0,0 +1,63 @@ +import pytest +from src.url_parser import parse_url + +def test_parse_complete_url(): + """Test parsing a complete URL with all components.""" + url = "https://username:password@example.com:8080/path/to/page?param1=value1¶m2=value2#fragment" + result = parse_url(url) + + assert result['scheme'] == 'https' + assert result['netloc'] == 'username:password@example.com:8080' + assert result['path'] == '/path/to/page' + assert result['query'] == {'param1': 'value1', 'param2': 'value2'} + assert result['fragment'] == 'fragment' + assert result['username'] == 'username' + assert result['password'] == 'password' + assert result['hostname'] == 'example.com' + assert result['port'] == 8080 + +def test_parse_simple_url(): + """Test parsing a simple URL.""" + url = "http://www.example.com" + result = parse_url(url) + + assert result['scheme'] == 'http' + assert result['netloc'] == 'www.example.com' + assert result['path'] == '' + assert result['query'] == {} + assert result['fragment'] == '' + assert result['hostname'] == 'www.example.com' + assert result['port'] is None + +def test_parse_url_with_query_params(): + """Test parsing a URL with multiple query parameters.""" + url = "https://example.com/search?q=python&category=programming" + result = parse_url(url) + + assert result['query'] == {'q': 'python', 'category': 'programming'} + +def test_parse_url_with_empty_components(): + """Test parsing a URL with some empty components.""" + url = "https://example.com/" + result = parse_url(url) + + assert result['scheme'] == 'https' + assert result['netloc'] == 'example.com' + assert result['path'] == '/' + assert result['query'] == {} + +def test_invalid_url_input(): + """Test error handling for invalid URL inputs.""" + with pytest.raises(ValueError, match="Invalid URL"): + parse_url("") + + with pytest.raises(ValueError, match="Invalid URL"): + parse_url(None) + +def test_malformed_url(): + """Test parsing a malformed URL.""" + url = "not a valid url" + result = parse_url(url) + + assert result['scheme'] == '' + assert result['netloc'] == '' \ No newline at end of file From 9775b66ca20b38ced74c8e794a59fe78c6407732 Mon Sep 17 00:00:00 2001 From: laura-abro Date: Thu, 10 Apr 2025 13:38:26 -0300 Subject: [PATCH 14/16] Fix URL parser to use empty strings for None values --- src/url_parser.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/url_parser.py b/src/url_parser.py index 33822b31..eee01905 100644 --- a/src/url_parser.py +++ b/src/url_parser.py @@ -29,12 +29,12 @@ def parse_url(url: str) -> Dict[str, Any]: # Construct and return the parsed URL dictionary return { - 'scheme': parsed.scheme or None, - 'netloc': parsed.netloc or None, - 'path': parsed.path or None, + 'scheme': parsed.scheme or '', # Change to empty string if None + 'netloc': parsed.netloc or '', # Change to empty string if None + 'path': parsed.path or '', # Change to empty string if None 'params': parsed.params or None, 'query': query_params, - 'fragment': parsed.fragment or None, + 'fragment': parsed.fragment or '', # Change to empty string if None 'username': parsed.username, 'password': parsed.password, 'hostname': parsed.hostname, From e15fa55fd17e0e3e7fb74d02f1996cb5ae45206d Mon Sep 17 00:00:00 2001 From: labrocadabro Date: Thu, 10 Apr 2025 13:40:12 -0300 Subject: [PATCH 15/16] Add RGB to Hex converter implementation --- src/rgb_to_hex.py | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 src/rgb_to_hex.py diff --git a/src/rgb_to_hex.py b/src/rgb_to_hex.py new file mode 100644 index 00000000..d5c184ad --- /dev/null +++ b/src/rgb_to_hex.py @@ -0,0 +1,24 @@ +def rgb_to_hex(r: int, g: int, b: int) -> str: + """ + Convert RGB color values to a hexadecimal color representation. + + Args: + r (int): Red color value (0-255) + g (int): Green color value (0-255) + b (int): Blue color value (0-255) + + Returns: + str: Hexadecimal color representation (6 characters) + + Raises: + ValueError: If any color value is outside the range 0-255 + """ + # Validate input values are within the valid range + for color, name in [(r, 'Red'), (g, 'Green'), (b, 'Blue')]: + if not isinstance(color, int): + raise TypeError(f"{name} value must be an integer") + if color < 0 or color > 255: + raise ValueError(f"{name} value must be between 0 and 255") + + # Convert each color component to a two-digit hex value + return ''.join(f'{c:02X}' for c in (r, g, b)) \ No newline at end of file From f130e9f6faebc483f3d1dc82ef18f8bd666ee95a Mon Sep 17 00:00:00 2001 From: labrocadabro Date: Thu, 10 Apr 2025 13:40:22 -0300 Subject: [PATCH 16/16] Add comprehensive tests for RGB to Hex converter --- tests/test_rgb_to_hex.py | 47 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 tests/test_rgb_to_hex.py diff --git a/tests/test_rgb_to_hex.py b/tests/test_rgb_to_hex.py new file mode 100644 index 00000000..a84e250c --- /dev/null +++ b/tests/test_rgb_to_hex.py @@ -0,0 +1,47 @@ +import pytest +from src.rgb_to_hex import rgb_to_hex + +def test_basic_conversion(): + """Test basic RGB to Hex conversion""" + assert rgb_to_hex(255, 255, 255) == 'FFFFFF' + assert rgb_to_hex(0, 0, 0) == '000000' + assert rgb_to_hex(148, 0, 211) == '9400D3' + +def test_zero_values(): + """Test conversion with zero values""" + assert rgb_to_hex(0, 0, 0) == '000000' + +def test_max_values(): + """Test conversion with maximum values""" + assert rgb_to_hex(255, 255, 255) == 'FFFFFF' + +def test_mixed_values(): + """Test conversion with mixed color values""" + assert rgb_to_hex(123, 45, 67) == '7B2D43' + +def test_invalid_low_values(): + """Test handling of values below 0""" + with pytest.raises(ValueError, match="Red value must be between 0 and 255"): + rgb_to_hex(-1, 0, 0) + with pytest.raises(ValueError, match="Green value must be between 0 and 255"): + rgb_to_hex(0, -1, 0) + with pytest.raises(ValueError, match="Blue value must be between 0 and 255"): + rgb_to_hex(0, 0, -1) + +def test_invalid_high_values(): + """Test handling of values above 255""" + with pytest.raises(ValueError, match="Red value must be between 0 and 255"): + rgb_to_hex(256, 0, 0) + with pytest.raises(ValueError, match="Green value must be between 0 and 255"): + rgb_to_hex(0, 256, 0) + with pytest.raises(ValueError, match="Blue value must be between 0 and 255"): + rgb_to_hex(0, 0, 256) + +def test_invalid_type(): + """Test handling of non-integer inputs""" + with pytest.raises(TypeError, match="Red value must be an integer"): + rgb_to_hex('255', 0, 0) + with pytest.raises(TypeError, match="Green value must be an integer"): + rgb_to_hex(0, '255', 0) + with pytest.raises(TypeError, match="Blue value must be an integer"): + rgb_to_hex(0, 0, '255') \ No newline at end of file