diff --git a/logic_building_problems/__init__.py b/logic_building_problems/__init__.py new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/logic_building_problems/array_traversal.py b/logic_building_problems/array_traversal.py new file mode 100644 index 000000000000..8a57dd8ab917 --- /dev/null +++ b/logic_building_problems/array_traversal.py @@ -0,0 +1,96 @@ +"""Array Traversal. + +This module contains functions for common array traversal operations, +including finding maximum, minimum, and sum of elements. +""" + + +def find_max(arr: list[int | float]) -> int | float: + """ + Find the maximum element in an array. + + Args: + arr: List of numbers + + Returns: + The maximum value in the array + + Raises: + ValueError: If the array is empty + + Examples: + >>> find_max([1, 5, 3, 9, 2]) + 9 + >>> find_max([-1, -5, -3]) + -1 + >>> find_max([42]) + 42 + >>> find_max([1.5, 2.7, 1.2]) + 2.7 + >>> find_max([]) + Traceback (most recent call last): + ... + ValueError: Array cannot be empty + """ + if not arr: + raise ValueError("Array cannot be empty") + return max(arr) + + +def find_min(arr: list[int | float]) -> int | float: + """ + Find the minimum element in an array. + + Args: + arr: List of numbers + + Returns: + The minimum value in the array + + Raises: + ValueError: If the array is empty + + Examples: + >>> find_min([1, 5, 3, 9, 2]) + 1 + >>> find_min([-1, -5, -3]) + -5 + >>> find_min([42]) + 42 + >>> find_min([]) + Traceback (most recent call last): + ... + ValueError: Array cannot be empty + """ + if not arr: + raise ValueError("Array cannot be empty") + return min(arr) + + +def array_sum(arr: list[int | float]) -> int | float: + """ + Calculate the sum of all elements in an array. + + Args: + arr: List of numbers + + Returns: + The sum of all values in the array + + Examples: + >>> array_sum([1, 2, 3, 4, 5]) + 15 + >>> array_sum([-1, 1, -2, 2]) + 0 + >>> array_sum([1.5, 2.5, 3.0]) + 7.0 + >>> array_sum([]) + 0 + """ + return sum(arr) + + +if __name__ == "__main__": + import doctest + + doctest.testmod() diff --git a/logic_building_problems/bubble_sort.py b/logic_building_problems/bubble_sort.py new file mode 100644 index 000000000000..1f2385e0788c --- /dev/null +++ b/logic_building_problems/bubble_sort.py @@ -0,0 +1,64 @@ +"""Bubble Sort Algorithm. + +This module implements the bubble sort algorithm, a simple sorting technique +that repeatedly steps through the list, compares adjacent elements and swaps +them if they are in the wrong order. +""" + + +def bubble_sort(arr: list[int | float]) -> list[int | float]: + """ + Sort an array using the bubble sort algorithm. + + Bubble sort works by repeatedly swapping adjacent elements if they are + in the wrong order. This process continues until no more swaps are needed. + + Args: + arr: List of numbers to be sorted + + Returns: + The sorted list in ascending order + + Examples: + >>> bubble_sort([64, 34, 25, 12, 22, 11, 90]) + [11, 12, 22, 25, 34, 64, 90] + >>> bubble_sort([5, 2, 8, 1, 9]) + [1, 2, 5, 8, 9] + >>> bubble_sort([1]) + [1] + >>> bubble_sort([]) + [] + >>> bubble_sort([3, 3, 3, 3]) + [3, 3, 3, 3] + >>> bubble_sort([5, 4, 3, 2, 1]) + [1, 2, 3, 4, 5] + >>> bubble_sort([1.5, 2.3, 0.8, 1.1]) + [0.8, 1.1, 1.5, 2.3] + """ + # Create a copy to avoid modifying the original list + arr_copy = arr.copy() + n = len(arr_copy) + + # Traverse through all array elements + for i in range(n): + # Flag to optimize by detecting if array is already sorted + swapped = False + + # Last i elements are already in place + for j in range(n - i - 1): + # Swap if the element found is greater than the next element + if arr_copy[j] > arr_copy[j + 1]: + arr_copy[j], arr_copy[j + 1] = arr_copy[j + 1], arr_copy[j] + swapped = True + + # If no swapping occurred, array is sorted + if not swapped: + break + + return arr_copy + + +if __name__ == "__main__": + import doctest + + doctest.testmod() diff --git a/logic_building_problems/fizz_buzz.py b/logic_building_problems/fizz_buzz.py new file mode 100644 index 000000000000..114f62e28d4a --- /dev/null +++ b/logic_building_problems/fizz_buzz.py @@ -0,0 +1,54 @@ +def fizz_buzz(num: int) -> list[str]: + """FizzBuzz Problem. + + - Return "Fizz" if the number is divisible by 3 + - Return "Buzz" if the number is divisible by 5 + - Return "FizzBuzz" if the number is divisible by both 3 and 5 + - Return the number as a string otherwise + + Args: + num: Positive integer representing the range + + Returns: + A list of strings containing FizzBuzz results + + Raises: + ValueError: If num is not a positive integer + + Examples: + >>> fizz_buzz(5) + ['1', '2', 'Fizz', '4', 'Buzz'] + >>> fizz_buzz(15) # doctest: +NORMALIZE_WHITESPACE + ['1', '2', 'Fizz', '4', 'Buzz', 'Fizz', '7', '8', + 'Fizz', 'Buzz', '11', 'Fizz', '13', '14', 'FizzBuzz'] + >>> fizz_buzz(0) + Traceback (most recent call last): + ... + ValueError: num must be a positive integer + >>> fizz_buzz(-5) + Traceback (most recent call last): + ... + ValueError: num must be a positive integer + """ + + if not isinstance(num, int) or num <= 0: + raise ValueError("num must be a positive integer") + + result = [] + for i in range(1, num + 1): + if i % 15 == 0: + result.append("FizzBuzz") + elif i % 3 == 0: + result.append("Fizz") + elif i % 5 == 0: + result.append("Buzz") + else: + result.append(str(i)) + + return result + + +if __name__ == "__main__": + import doctest + + doctest.testmod() diff --git a/logic_building_problems/palindrome.py b/logic_building_problems/palindrome.py new file mode 100644 index 000000000000..9fb5b6375ff3 --- /dev/null +++ b/logic_building_problems/palindrome.py @@ -0,0 +1,46 @@ +"""Palindrome Checker. + +This module contains functions to check if a string is a palindrome. +A palindrome is a word, phrase, or sequence that reads the same backward as forward. +""" + + +def is_palindrome(text: str) -> bool: + """ + Check if a given string is a palindrome. + + A palindrome is a string that reads the same forward and backward, + ignoring case, spaces, and punctuation. + + Args: + text: The string to check + + Returns: + True if the string is a palindrome, False otherwise + + Examples: + >>> is_palindrome("racecar") + True + >>> is_palindrome("hello") + False + >>> is_palindrome("A man a plan a canal Panama") + True + >>> is_palindrome("race a car") + False + >>> is_palindrome("") + True + >>> is_palindrome("a") + True + >>> is_palindrome("Madam") + True + """ + # Remove non-alphanumeric characters and convert to lowercase + cleaned = "".join(char.lower() for char in text if char.isalnum()) + # Check if the cleaned string equals its reverse + return cleaned == cleaned[::-1] + + +if __name__ == "__main__": + import doctest + + doctest.testmod() diff --git a/logic_building_problems/pangram.py b/logic_building_problems/pangram.py new file mode 100644 index 000000000000..cf10b4c955d4 --- /dev/null +++ b/logic_building_problems/pangram.py @@ -0,0 +1,45 @@ +"""Pangram Checker. + +This module contains functions to check if a string is a pangram. +A pangram is a sentence that contains every letter of the alphabet at least once. +""" + + +def is_pangram(text: str) -> bool: + """ + Check if a given string is a pangram. + + A pangram is a string that contains every letter of the alphabet + at least once, ignoring case and non-alphabetic characters. + + Args: + text: The string to check + + Returns: + True if the string is a pangram, False otherwise + + Examples: + >>> is_pangram("The quick brown fox jumps over the lazy dog") + True + >>> is_pangram("Hello World") + False + >>> is_pangram("Pack my box with five dozen liquor jugs") + True + >>> is_pangram("abcdefghijklmnopqrstuvwxyz") + True + >>> is_pangram("") + False + >>> is_pangram("ABCDEFGHIJKLMNOPQRSTUVWXYZ") + True + """ + # Convert text to lowercase and get all unique letters + letters = {char.lower() for char in text if char.isalpha()} + + # Check if all 26 letters of the alphabet are present + return len(letters) == 26 + + +if __name__ == "__main__": + import doctest + + doctest.testmod()