Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
aa5756d
Implement string reversal function
labrocadabro Apr 10, 2025
987f1cf
Add comprehensive tests for string reversal function
labrocadabro Apr 10, 2025
53ee5e7
Implement manual string reversal without slice or reverse()
labrocadabro Apr 10, 2025
29307e2
Update tests to verify manual string reversal implementation
labrocadabro Apr 10, 2025
456e32f
Implement array flattening function with recursive approach
laura-abro Apr 10, 2025
79c34dc
Add comprehensive tests for array flattening function
laura-abro Apr 10, 2025
ad2b031
Implement binary search function with comprehensive error handling
labrocadabro Apr 10, 2025
99239a9
Add comprehensive tests for binary search function
labrocadabro Apr 10, 2025
b925ffd
Add pytest to requirements
labrocadabro Apr 10, 2025
0110474
Implement URL parser function with comprehensive parsing
laura-abro Apr 10, 2025
5d17aa0
Add comprehensive tests for URL parser function
laura-abro Apr 10, 2025
5341113
Add pytest to requirements
laura-abro Apr 10, 2025
4c02b2a
Fix URL parsing to correctly extract hostname
laura-abro Apr 10, 2025
cc14337
Add RGB to Hex converter function
labrocadabro Apr 10, 2025
df16e25
Add comprehensive tests for RGB to Hex converter
labrocadabro Apr 10, 2025
dc1f48d
Merged branch pr-201-momstrosity-builder-test for PR https://github.c…
momstrosity Apr 11, 2025
7335a18
Merged branch pr-202-momstrosity-builder-test for PR https://github.c…
momstrosity Apr 11, 2025
745ad65
Merged branch pr-203-momstrosity-builder-test for PR https://github.c…
momstrosity Apr 11, 2025
ad370f0
Merged branch pr-204-momstrosity-builder-test for PR https://github.c…
momstrosity Apr 11, 2025
98b1c93
Merged branch pr-205-momstrosity-builder-test for PR https://github.c…
momstrosity Apr 11, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
pytest
38 changes: 38 additions & 0 deletions src/array_flatten.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
from typing import List, Union, Any

def flatten_array(arr: List[Union[Any, List]]) -> List[Any]:
"""
Recursively flatten a nested list into a single-level list.

Args:
arr (List[Union[Any, List]]): A potentially nested list to be flattened.

Returns:
List[Any]: A flattened list containing all non-list elements.

Raises:
TypeError: If the input is not a list.

Examples:
>>> flatten_array([1, [2, 3], [4, [5, 6]]])
[1, 2, 3, 4, 5, 6]
>>> flatten_array([1, 2, 3])
[1, 2, 3]
>>> flatten_array([])
[]
"""
# Check if input is a list
if not isinstance(arr, list):
raise TypeError("Input must be a list")

# Use a single-pass flattening approach
flattened = []
for item in arr:
# If the item is a list, recursively flatten it
if isinstance(item, list):
flattened.extend(flatten_array(item))
else:
# If not a list, append directly
flattened.append(item)

return flattened
48 changes: 48 additions & 0 deletions src/binary_search.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
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 if input is a list
if not isinstance(arr, list):
raise TypeError("Input must be a list")

# Check if list is sorted
if arr != sorted(arr):
raise ValueError("Input list must be sorted in ascending order")

# Handle empty list case
if not arr:
return -1

# Standard binary search implementation
left, right = 0, len(arr) - 1

while left <= right:
# Calculate midpoint to avoid potential integer overflow
mid = left + (right - left) // 2

# Check if target is found
if arr[mid] == target:
return mid

# If target is less than mid, search left half
elif arr[mid] > target:
right = mid - 1

# If target is greater than mid, search right half
else:
left = mid + 1

# Target not found
return -1
24 changes: 24 additions & 0 deletions src/rgb_to_hex.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
def rgb_to_hex(r: int, g: int, b: int) -> str:
"""
Convert RGB color values to a hexadecimal color code.

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 code (e.g., '#FF0000')

Raises:
ValueError: If any color value is not in the range 0-255
"""
# Validate input values
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 RGB to hex, ensuring two-digit representation
return f'#{r:02X}{g:02X}{b:02X}'
24 changes: 24 additions & 0 deletions src/string_reversal.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
def reverse_string(s: str) -> str:
"""
Reverse the given string manually, preserving all characters.

Args:
s (str): The input string to be reversed.

Returns:
str: The reversed string.

Raises:
TypeError: If the input is not a string.
"""
# Type checking
if not isinstance(s, str):
raise TypeError("Input must be a string")

# Manual string reversal using a list-based approach
# This preserves all characters including spaces and special characters
reversed_chars = []
for i in range(len(s) - 1, -1, -1):
reversed_chars.append(s[i])

return ''.join(reversed_chars)
59 changes: 59 additions & 0 deletions src/url_parser.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
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 component parts.

Args:
url (str): The URL to parse

Returns:
Dict[str, Any]: A dictionary containing parsed URL components

Raises:
ValueError: If the 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_url = urlparse(url)

# Prepare the result dictionary
result = {
'scheme': parsed_url.scheme,
'netloc': parsed_url.netloc,
'path': parsed_url.path,
'params': parsed_url.params,
'query': parse_qs(parsed_url.query),
'fragment': parsed_url.fragment
}

# Extract additional useful information
# Handle credentials first
if '@' in parsed_url.netloc:
credentials, host = parsed_url.netloc.split('@', 1)
if ':' in credentials:
result['username'], result['password'] = credentials.split(':', 1)
else:
result['username'] = credentials

# Update netloc to only include host
parsed_url = parsed_url._replace(netloc=host)

# Split host and port
if ':' in parsed_url.netloc:
hostname_port = parsed_url.netloc.split(':')
result['hostname'] = hostname_port[0]
if len(hostname_port) > 1:
result['port'] = hostname_port[1]
else:
result['hostname'] = parsed_url.netloc

return result

except Exception as e:
raise ValueError(f"Error parsing URL: {str(e)}")
38 changes: 38 additions & 0 deletions tests/test_array_flatten.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
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, [5, 6]]]) == [1, 2, 3, 4, 5, 6]

def test_flatten_empty_list():
"""Test flattening an empty list."""
assert flatten_array([]) == []

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_mixed_types_list():
"""Test flattening a list with mixed types."""
assert flatten_array([1, 'a', [2, 'b'], [3, [4, 'c']]]) == [1, 'a', 2, 'b', 3, 4, 'c']

def test_invalid_input_type():
"""Test that a TypeError is raised for non-list inputs."""
with pytest.raises(TypeError, match="Input must be a list"):
flatten_array("not a list")

with pytest.raises(TypeError, match="Input must be a list"):
flatten_array(123)

def test_nested_empty_lists():
"""Test flattening a list with nested empty lists."""
assert flatten_array([1, [], [2, []], 3]) == [1, 2, 3]

def test_single_element_nested_list():
"""Test flattening a list with single-element nested lists."""
assert flatten_array([[1], [2], [3]]) == [1, 2, 3]
49 changes: 49 additions & 0 deletions tests/test_binary_search.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import pytest
from src.binary_search import binary_search

def test_binary_search_basic():
"""Test basic functionality of binary search"""
arr = [1, 3, 5, 7, 9, 11, 13]
assert binary_search(arr, 7) == 3
assert binary_search(arr, 13) == 6
assert binary_search(arr, 1) == 0

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, 4) == -1
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 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"""
with pytest.raises(TypeError, match="Input must be a list"):
binary_search("not a list", 5)

with pytest.raises(ValueError, match="Input list must be sorted in ascending order"):
binary_search([5, 3, 1], 3)

def test_binary_search_large_list():
"""Test binary search on a larger sorted list"""
arr = list(range(1000))
assert binary_search(arr, 500) == 500
assert binary_search(arr, 999) == 999
assert binary_search(arr, 1000) == -1

def test_binary_search_duplicates():
"""Test binary search with a list containing duplicates"""
arr = [1, 2, 2, 3, 3, 3, 4, 4, 5]
# Note: This will return the index of one of the duplicate elements
assert binary_search(arr, 3) in [4, 5, 6]
assert binary_search(arr, 2) in [1, 2]
assert binary_search(arr, 1) == 0
assert binary_search(arr, 5) == 8
51 changes: 51 additions & 0 deletions tests/test_rgb_to_hex.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
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, 0, 0) == '#FF0000' # Red
assert rgb_to_hex(0, 255, 0) == '#00FF00' # Green
assert rgb_to_hex(0, 0, 255) == '#0000FF' # Blue
assert rgb_to_hex(255, 255, 255) == '#FFFFFF' # White
assert rgb_to_hex(0, 0, 0) == '#000000' # Black

def test_mixed_colors():
"""Test mixed color conversions"""
assert rgb_to_hex(128, 128, 128) == '#808080' # Gray
assert rgb_to_hex(255, 165, 0) == '#FFA500' # Orange

def test_zero_values():
"""Test conversion with zero values"""
assert rgb_to_hex(0, 0, 0) == '#000000'

def test_boundary_values():
"""Test boundary values"""
assert rgb_to_hex(0, 0, 0) == '#000000'
assert rgb_to_hex(255, 255, 255) == '#FFFFFF'

def test_invalid_low_values():
"""Test error handling for 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 error handling for 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 error handling for 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')
48 changes: 48 additions & 0 deletions tests/test_string_reversal.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
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 reversal of an empty string."""
assert reverse_string("") == ""

def test_reverse_string_single_char():
"""Test reversal of a single character."""
assert reverse_string("a") == "a"

def test_reverse_string_with_spaces():
"""Test string reversal preserves spaces."""
assert reverse_string("hello world") == "dlrow olleh"

def test_reverse_string_with_special_chars():
"""Test string reversal with special characters."""
assert reverse_string("a!b@c#") == "#c@b!a"

def test_reverse_string_invalid_input():
"""Test that TypeError is raised for non-string input."""
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 reversal of Unicode strings."""
assert reverse_string("こんにちは") == "はちにんこ"

def test_implementation_method():
"""Ensure the implementation does not use slice notation or reverse()."""
import inspect
import src.string_reversal

# Get the source code of the function
source_lines = inspect.getsource(src.string_reversal.reverse_string)
source_code = ''.join(source_lines)

# Check that forbidden methods are not used
assert '[::-1]' not in source_code, "Do not use slice notation for reversal"
assert '.reverse()' not in source_code, "Do not use built-in reverse() method"
Loading