diff --git a/src/bisearch/prefix.py b/src/bisearch/prefix.py index 93d612a..fa725b2 100644 --- a/src/bisearch/prefix.py +++ b/src/bisearch/prefix.py @@ -17,21 +17,29 @@ class NotFound(Exception): def bisect_right(origin: List[str], search: str = "") -> int: - """Return the most right one index matching the search value + """ + Return the most right one index matching the search value + + Current function implements common ``bisect_right`` algorithms. + The search value represents prefix the string should starts with, + that's why current string is trimmed before comparison operation. :param origin: a list of strings - :type origin: list[str] + :type origin: list :param search: a prefix to search :type search: str :return: the index after the last string starting with search prefix :rtype: int - :raise: NotFound + :raise NotFound: if the searched value isn't in the list - Current function implements common ``bisect_right`` algorithms. - The search value represents prefix the string should starts with, - that's why current string is trimmed before comparison operation. + Usage: + + >>> data = ["apple", "apple", "banana", "banana", "cherry"] + >>> assert bisect_right(data, "a") == 2 + >>> assert bisect_right(data, "b") == 4 + >>> assert bisect_right(data, "c") == 5 """ @@ -55,21 +63,29 @@ def bisect_right(origin: List[str], search: str = "") -> int: def bisect_left(origin: List[str], search: str = "") -> int: - """Return the most left one index matching the search value + """ + Return the most left one index matching the search value + + Current function implements common ``bisect_left`` algorithms. + The search value represents prefix the string should starts with, + that's why current string is trimmed before comparison operation. :param origin: a list of strings - :type origin: list[str] + :type origin: list :param search: a prefix to search :type search: str :return: the index of the first string starting with search prefix :rtype: int - :raise: NotFound + :raise NotFound: if the searched value isn't in the list - Current function implements common ``bisect_left`` algorithms. - The search value represents prefix the string should starts with, - that's why current string is trimmed before comparison operation. + Usage: + + >>> data = ["apple", "apple", "banana", "banana", "cherry"] + >>> assert bisect_left(data, "a") == 0 + >>> assert bisect_left(data, "b") == 2 + >>> assert bisect_left(data, "c") == 4 """ @@ -93,15 +109,23 @@ def bisect_left(origin: List[str], search: str = "") -> int: def find_all(origin: List[str], search: str = "") -> List[str]: - """Return strings starting with prefix + """ + Return strings starting with prefix :param origin: the list of strings - :type origin: list[str] + :type origin: list :param search: the prefix to search, defaults to empty string :type search: str :return: the list of strings starting with the search prefix - :rtype: list[str] + :rtype: list + + Usage: + + >>> data = ["apple", "apple", "banana", "banana", "cherry"] + >>> assert find_all(data, "a") == ["apple", "apple"] + >>> assert find_all(data, "b") == ["banana", "banana"] + >>> assert find_all(data, "c") == ["cherry"] """ diff --git a/src/calc/func.py b/src/calc/func.py index 744fd44..50decaa 100644 --- a/src/calc/func.py +++ b/src/calc/func.py @@ -5,7 +5,13 @@ def get_factorial(number: int, /) -> int: - """Return the factorial value for a given number + """ + Return the factorial value for a given number + + In mathematics the factorial is the product of all positive integers + less than or equal to given number. + E.g. 5! = 5 * 4! = 5 * 4 * 3 * 2 * 1 = 120. + The value of 0! = 1 according to the convention of an empty product. :param number: :type number: int @@ -13,12 +19,7 @@ def get_factorial(number: int, /) -> int: :return: the factorial value :rtype: int - In mathematics the factorial is the product of all positive integers - less than or equal to given number. - E.g. 5! = 5 * 4! = 5 * 4 * 3 * 2 * 1 = 120. - The value of 0! = 1 according to the convention of an empty product. - - Usage examples: + Usage: >>> assert get_factorial(0) == 1 >>> assert get_factorial(5) == 120 @@ -32,7 +33,12 @@ def get_factorial(number: int, /) -> int: def get_fibonacci_number(idx: int, /) -> int: - """Return a Fibonacci's sequence number at a specified index + """ + Return a Fibonacci's sequence number at a specified index + + The Fibonacci number is a number from the Fibonacci sequence, in which + each number is the sum of the two preceding ones. This sequence commonly + starts from 0 and 1: 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144... :param idx: a Fibonacci sequence index starting from 0 :type idx: int @@ -40,11 +46,7 @@ def get_fibonacci_number(idx: int, /) -> int: :return: a sequence's member :rtype: int - The Fibonacci number is a number from the Fibonacci sequence, in which - each number is the sum of the two preceding ones. This sequence commonly - starts from 0 and 1: 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144... - - Usage examples: + Usage: >>> assert get_fibonacci_number(0) == 0 >>> assert get_fibonacci_number(1) == 1 @@ -64,7 +66,11 @@ def get_fibonacci_number(idx: int, /) -> int: def get_fibonacci_number_nr(idx: int, /) -> int: - """Return a Fibonacci's sequence number at a specified index + """ + Return a Fibonacci's sequence number at a specified index + + This function implements the non-recursive algorithm, which is more + efficient, since it does not have multiple recursive calls. :param idx: a Fibonacci sequence index starting from 0 :type idx: int @@ -72,8 +78,13 @@ def get_fibonacci_number_nr(idx: int, /) -> int: :return: a sequence's member :rtype: int - This function implements the non-recursive algorithm, which is more - efficient, since it does not have multiple recursive calls. + Usage: + + >>> assert get_fibonacci_number(0) == 0 + >>> assert get_fibonacci_number(1) == 1 + >>> assert get_fibonacci_number(2) == 1 + >>> assert get_fibonacci_number(3) == 2 + >>> assert get_fibonacci_number(4) == 3 """ @@ -91,7 +102,11 @@ def get_fibonacci_number_nr(idx: int, /) -> int: def get_sum_of_strings(number_1: str, number_2: str, /) -> str: - """Return the sum of two numbers of string type as string + """ + Return the sum of two numbers of string type as string + + Valid input is a string of any length containing numeric characters from + 0 to 9. Empty strings are allowed as well and should be considered as 0. :param number_1: first number :type number_1: str @@ -101,10 +116,7 @@ def get_sum_of_strings(number_1: str, number_2: str, /) -> str: :return: the sum of two numbers :rtype: str - Valid input is a string of any length containing numeric characters from - 0 to 9. Empty strings are allowed as well and should be considered as 0. - - Usage examples: + Usage: >>> assert get_sum_of_strings("123", "456") == "579" >>> assert get_sum_of_strings("099", "001") == "100" diff --git a/src/chess/func.py b/src/chess/func.py index 686b80b..bdd675b 100644 --- a/src/chess/func.py +++ b/src/chess/func.py @@ -12,7 +12,8 @@ def within_board(position: Tuple[int, int]) -> bool: - """Check if position is within a chess board + """ + Check if position is within a chess board :param position: a position to check :type position: tuple @@ -20,6 +21,15 @@ def within_board(position: Tuple[int, int]) -> bool: :return: True if position is within a chess board, otherwise False :rtype: bool + Usage: + + >>> assert within_board((2, 2)) is True + >>> assert within_board((3, 3)) is True + >>> assert within_board((4, 4)) is True + >>> assert within_board((5, -5)) is False + >>> assert within_board((-5, 5)) is False + >>> assert within_board((5, 50)) is False + """ position_x, position_y = position @@ -29,7 +39,8 @@ def within_board(position: Tuple[int, int]) -> bool: def filter_can_move(pieces: List[Piece], position: Tuple[int, int]) -> List[Piece]: - """Filter the list of chess piece + """ + Filter the list of chess piece :param pieces: a list of chess pieces :type pieces: list diff --git a/src/chess/piece.py b/src/chess/piece.py index cceec70..1b6e1ce 100644 --- a/src/chess/piece.py +++ b/src/chess/piece.py @@ -13,7 +13,8 @@ class Piece: - """Chess piece model + """ + Chess piece model :ivar position: the position on a chess board :type position: tuple @@ -25,12 +26,13 @@ class Piece: def __init__(self, is_white: bool = True, position: Tuple[int, int] = (0, 0)) -> None: - """Initialize instance + """ + Initialize instance :param is_white: indicating if a piece is white. Defaults to True. - :type is_white: bool + :type is_white: bool, optional :param position: initial piece position. Defaults to (0, 0). - :type position: tuple + :type position: tuple, optional """ @@ -48,7 +50,8 @@ def swap_color(self) -> None: self.is_white = not self.is_white def set_position(self, position: Tuple[int, int]) -> None: - """Change piece position to a specified one + """ + Change piece position to a specified one :param position: new position for a piece :type position: tuple @@ -62,7 +65,8 @@ def set_position(self, position: Tuple[int, int]) -> None: logger.warning("Position %s is outside the board", position) def can_move(self, position: Tuple[int, int]) -> bool: - """Check if a move to a specified position is valid + """ + Check if a move to a specified position is valid :param position: a position to check :type position: tuple @@ -75,7 +79,8 @@ def can_move(self, position: Tuple[int, int]) -> bool: raise NotImplementedError def get_delta(self, position: Tuple[int, int]) -> Tuple[int, int]: - """Return the deltas between current position and the specified one + """ + Return the deltas between current position and the specified one :param position: a position to calculate delta with :type position: tuple diff --git a/src/chess/symbols.py b/src/chess/symbols.py index 49bb518..e2fa3a6 100644 --- a/src/chess/symbols.py +++ b/src/chess/symbols.py @@ -1,5 +1,6 @@ """ Chess pieces unicode symbols + """ WHITE_KING = chr(0x2654) diff --git a/src/conv_store/models.py b/src/conv_store/models.py index 56d0949..25982f5 100644 --- a/src/conv_store/models.py +++ b/src/conv_store/models.py @@ -7,7 +7,8 @@ class Product: - """Product model implementation + """ + Product model implementation Instances of this class represent a product available for purchase. @@ -25,7 +26,8 @@ def __init__(self, price: int, unit: Union[int, float] ) -> None: - """Initialize instance + """ + Initialize instance :param name: product name :type name: str @@ -158,8 +160,8 @@ def __iter__(self) -> Iterator[Tuple[Product, Union[int, float]]]: def remove_product(self, product: Product ) -> Tuple[Product, Union[int, float]]: - """Remove product from a cart instance - + """ + Remove product from a cart instance :param product: a product instance to add to cart :type product: :class: `Product` @@ -167,7 +169,7 @@ def remove_product(self, :return: a shopping cart product/quantity entry :rtype: tuple - :raise: ValueError + :raise ValueError: if the project isn't present in the shopping cart """ @@ -216,16 +218,16 @@ def sub_product(self, product: Product, quantity: Union[int, float] ) -> None: - """Subtract product from the shopping cart + """ + Subtract product from the shopping cart If quantity value is less or equal to 0 the product is to be removed from the shopping cart - :param product: a product instance to add to cart :type product: :class: `Product` :param quantity: a quantity of a product to add - :type quantity: int or float + :type quantity: int | float """ diff --git a/src/datasets/func.py b/src/datasets/func.py index 10df93d..d8f1d48 100644 --- a/src/datasets/func.py +++ b/src/datasets/func.py @@ -124,6 +124,28 @@ def get_low_student(students_data: StudentsList) -> StudentData: def get_both_top_low_students(students_data: StudentsList ) -> Tuple[StudentData, StudentData]: + """ + Return both top and low students data + + Given a list of student data, returns a tuple of the student with + the highest average score and the student with the lowest average score. + The student data is represented as a list of dictionaries, where each + dictionary contains the keys 'name' and 'scores', where 'name' is + a string and 'scores' is a list of floats representing the student's + scores on various exams. + + :param students_data: A list of dictionaries containing the student data. + :type students_data: list + + :return: A tuple of two dictionaries representing the student with + the highest average score and the student with the lowest average + score. Each dictionary contains the keys 'name' and 'scores', + where 'name' is a string and 'scores' is a list of floats + representing the student's scores on various exams. + :rtype: tuple + + """ + min_score_threshold, max_score_threshold = float("+inf"), float("-inf") top_student = {"name": "", "scores": []} low_student = {"name": "", "scores": []} @@ -141,15 +163,16 @@ def get_both_top_low_students(students_data: StudentsList def get_bricks_count(structure: List[List[int]]) -> int: - """Return number of bricks in the wall structure + """ + Return number of bricks in the wall structure :param structure: represents wall structure as sequences of integers - :type structure: list[list[int]] + :type structure: list :return: total number of bricks in the entire wall structure :rtype: int - Usage examples: + Usage: >>> assert get_bricks_count([[1], [1], [1]]) == 3 >>> assert get_bricks_count([[1, 1, 1], [1, 1, 1]]) == 6 @@ -161,15 +184,16 @@ def get_bricks_count(structure: List[List[int]]) -> int: def get_position_frequency(structure: List[List[int]]) -> Dict[int, int]: - """Return a matrix of position-bricks pairs for a structure + """ + Return a matrix of position-bricks pairs for a structure :param structure: represents wall structure as sequences of integers - :type structure: list[list[int]] + :type structure: list :return: the position - frequency matrix - :rtype: dict[int, int] + :rtype: dict - Usage examples: + Usage: >>> assert get_position_frequency([[1], [1], [1]]) == {} >>> assert get_position_frequency([[1, 2], [2, 1], [3]]) = {1: 1, 2: 1} @@ -191,18 +215,19 @@ def get_position_frequency(structure: List[List[int]]) -> Dict[int, int]: def get_least_bricks_position(structure: List[List[int]]) -> int: - """Return a pointer to the weakest line in the structure + """ + Return a pointer to the weakest line in the structure + + This function uses helper function ``get_structure_matrix`` to build + the matrix of distances from the left edge of the "wall". :param structure: represents wall structure as sequences of integers - :type structure: list[list[int]] + :type structure: list :return: the distance from the left edge to the weakest line location :rtype: int - This function uses helper function ``get_structure_matrix`` to build - the matrix of distances from the left edge of the "wall". - - Usage examples: + Usage: >>> assert get_least_bricks_position([[1], [1], [1]]) == 0 >>> assert get_least_bricks_position([[1, 1, 1], [1, 1, 1]]) == 1 @@ -217,15 +242,16 @@ def get_least_bricks_position(structure: List[List[int]]) -> int: def get_least_bricks_count(structure: List[List[int]]) -> int: - """Return the least number of bricks in a vertical line + """ + Return the least number of bricks in a vertical line :param structure: represents wall structure as sequences of integers - :type structure: list[list[int]] + :type structure: list :return: minimum number of bricks in a line :rtype: int - Usage examples: + Usage: >>> assert get_least_bricks_count([[1], [1], [1]]) == 3 >>> assert get_least_bricks_count([[1, 2], [2, 1], [3], [1, 1, 1]]) == 2 @@ -244,15 +270,8 @@ def get_least_bricks_count(structure: List[List[int]]) -> int: def filter_by_values(origin: List[Dict[str, Hashable]], keys: Optional[List[str]] = None ) -> List[Dict[str, Any]]: - """Return a filtered datasets by unique values in a given keys sets - - :param origin: an original dataset with entries to filter - :type origin: list - :param keys: a collection of keys to use for filtering - :type keys: list, optional - - :return: a filtered dataset - :rtype: list + """ + Return a filtered datasets by unique values in a given keys sets The origin dataset is a list of dictionaries. All the dictionaries have the same set of keys of a string type. All dictionaries values are of @@ -266,14 +285,17 @@ def filter_by_values(origin: List[Dict[str, Hashable]], function, all values (if any) are valid. In case this parameter is omitted - all available keys should be used. - Inputs are considered to be pre-validated as described above, - no need for additional checks. + :param origin: an original dataset with entries to filter + :type origin: list + :param keys: a collection of keys to use for filtering + :type keys: list, optional + + :return: a filtered dataset + :rtype: list - Usage examples: + Usage: >>> ds = [{"x": 1, "y": 2, "z": 3}, {"x": 0, "y": 2, "z": 3}] - >>> assert filter_by_values([]) == [] # no data to filter - >>> assert filter_by_values(ds) == ds # the same as origin >>> assert filter_by_values(ds, ["x"]) == ds # the same as origin >>> assert filter_by_values(ds, ["x", "z"]) == ds # the same as origin >>> assert filter_by_values(ds, ["y"]) == [{"x": 1, "y": 2, "z": 3}] @@ -289,18 +311,12 @@ def filter_by_values(origin: List[Dict[str, Hashable]], filtered_dataset: List[Dict[str, Hashable]] = [] filtered_values: Set[int] = set() - # in case no keys provided get all keys from the first one dictionary keys = keys or origin[0].keys() # type: ignore - - # iterate though the list and perform de-duplication task for entry in origin: entry_values = hash(tuple(map(entry.get, keys))) # type: ignore - # in case the values has been filtered already - # proceed to the next iteration if entry_values in filtered_values: continue - # update filtered values filtered_values.add(entry_values) filtered_dataset.append(entry) diff --git a/src/dynamic/memoization.py b/src/dynamic/memoization.py index a68946e..6799b91 100644 --- a/src/dynamic/memoization.py +++ b/src/dynamic/memoization.py @@ -10,11 +10,8 @@ def memoize(func: Callable) -> Callable: - """Memoization decorator implementation - - :param func: a function to decorate with memoization technique - - :return: the decorated function + """ + Memoization decorator The memoization technique helps to reduce the number of recursive calls by caching the results already calculated for some inputs. @@ -23,6 +20,10 @@ def memoize(func: Callable) -> Callable: so it has limitations for "un-hashable" inputs, that can not be stored in a cache dictionary. + :param func: a function to decorate with memoization technique + + :return: the decorated function + """ cache: Dict[Tuple[Any], int] = {} @@ -50,19 +51,29 @@ def get_fibonacci_number(idx): # pylint: disable=C0116 @memoize def get_grid_travels(height: int, width: int, /) -> int: - """Calculate the number of available route for a specified grid size + """ + Calculate the number of available route for a specified grid size + + The traveler starts the journey in the top-left corner of the grid + and trying to reach the opposite grid corner (bottom-right). + The only moves available are **move right** and **move down**. + The task is to calculate the number of all available routes to do + this. :param height: grid height + :type height: int :param width: grid width + :type width: int :return: the number of available routes :rtype: int - The traveler starts the journey in the top-left corner of the grid - and trying to reach the opposite grid corner (bottom-right). - The only moves available are **move right** and **move down**. - The task is to calculate the number of all available routes to do - this. + Usage: + + >>> assert get_grid_travels(1, 0) == 0 + >>> assert get_grid_travels(1, 1) == 1 + >>> assert get_grid_travels(2, 3) == 3 + >>> assert get_grid_travels(3, 2) == 3 """ @@ -78,19 +89,27 @@ def get_grid_travels(height: int, width: int, /) -> int: def can_get_target(target: int, numbers: List[int], cache: Optional[Dict[int, bool]] = None) -> bool: - """Check if the target value can be generated using given numbers + """ + Check if the target value can be generated using given numbers + + Numbers from the list can be used as many times as needed. :param target: the desired number :type target: int :param numbers: the sequence of numbers available for usage - :type numbers: list[int] + :type numbers: list :param cache: optional dictionary that stores already calculated results - :type cache: dict[int, bool] + :type cache: dict, optional :return: the check result :rtype: bool - Numbers from the list can be used as many times as needed. + Usage: + + >>> assert can_get_target(0, []) is True + >>> assert can_get_target(0, [1, 1, 1]) is True + >>> assert can_get_target(7, [2, 3]) is True + >>> assert can_get_target(7, [2, 4, 6]) is False """ diff --git a/src/dynamic/tabulation.py b/src/dynamic/tabulation.py index 1a31cb5..ec5c006 100644 --- a/src/dynamic/tabulation.py +++ b/src/dynamic/tabulation.py @@ -10,19 +10,20 @@ def get_fibonacci_sequence(size: int, /) -> List[int]: - """Return the Fibonacci numbers sequences of a given size + """ + Return the Fibonacci numbers sequences of a given size + + The Fibonacci numbers (aka the Fibonacci sequence) is a sequence in + which each number is the sum of the two preceding onces. The sequence + commonly starts with 0 and 1. :param size: the size of the requested sequence :type size: int :return: the Fibonacci sequence - :rtype: list[int] + :rtype: list - The Fibonacci numbers (aka the Fibonacci sequence) is a sequence in - which each number is the sum of the two preceding onces. The sequence - commonly starts with 0 and 1. - - Usage examples: + Usage: >>> assert get_fibonacci_sequence(0) == [] >>> assert get_fibonacci_sequence(1) == [0] @@ -47,19 +48,29 @@ def get_fibonacci_number(idx): # pylint:disable=C0116 def get_grid_travels(height: int, width: int, /) -> int: - """Calculate the number of available route for a specified grid size + """ + Calculate the number of available route for a specified grid size + + The traveler starts the journey in the top-left corner of the grid + The only moves available are **move right** and **move down**. + and trying to reach the opposite grid corner (bottom-right). + The task is to calculate the number of all available routes to do + this. :param height: grid height + :type height: int :param width: grid width + :type width: int :return: the number of available routes :rtype: int - The traveler starts the journey in the top-left corner of the grid - The only moves available are **move right** and **move down**. - and trying to reach the opposite grid corner (bottom-right). - The task is to calculate the number of all available routes to do - this. + Usage: + + >>> assert get_grid_travels(1, 0) == 0 + >>> assert get_grid_travels(1, 1) == 1 + >>> assert get_grid_travels(2, 3) == 3 + >>> assert get_grid_travels(3, 2) == 3 """ @@ -83,17 +94,25 @@ def get_grid_travels(height: int, width: int, /) -> int: def can_get_target(target: int, numbers: List[int]) -> bool: - """Check if the target value can be generated using given numbers + """ + Check if the target value can be generated using given numbers + + Numbers from the list can be used as many times as needed. :param target: the desired number :type target: int :param numbers: the sequence of numbers available for usage - :type numbers: list[int] + :type numbers: list :return: the check result :rtype: bool - Numbers from the list can be used as many times as needed. + Usage: + + >>> assert can_get_target(0, []) is True + >>> assert can_get_target(0, [1, 1, 1]) is True + >>> assert can_get_target(7, [2, 3]) is True + >>> assert can_get_target(7, [2, 4, 6]) is False """ @@ -127,22 +146,30 @@ def set_value(table_idx): def get_target_numbers(target: int, numbers: List[int]) -> Optional[List[int]]: - """Return a collection of numbers to get the target one if possible + """ + Return a collection of numbers to get the target one if possible + + This function returns the best collection of numbers to generate the + target one. If it's impossible to generate None will be returned. + + The shortest one available sequence is considered the best one. + + Numbers can be used as many times as it needed. :param target: the desired number :type target: int :param numbers: the sequence of numbers available for usage - :type numbers: list[int] + :type numbers: list :return: None if impossible, otherwise list of numbers - :rtype: list[int] | None + :rtype: list, optional - This function returns the best collection of numbers to generate the - target one. If it's impossible to generate None will be returned. + Usage: - The shortest one available sequence is considered the best one. - - Numbers can be used as many times as it needed. + >>> assert get_target_numbers(0, []) == [] + >>> assert get_target_numbers(0, [1, 1, 1]) == [] + >>> assert get_target_numbers(7, [1]) == [1, 1, 1, 1, 1, 1, 1] + >>> assert get_target_numbers(7, [1, 2, 3]) == [1, 3, 3] """ diff --git a/src/primes/func.py b/src/primes/func.py index e4c3c8e..83f9f29 100644 --- a/src/primes/func.py +++ b/src/primes/func.py @@ -8,7 +8,11 @@ def is_prime(number: int) -> bool: - """Return prime check result for a specified number + """ + Return prime check result for a specified number + + The result of this function is True if a number is prime, otherwise + False. :param number: number to check :type number: int @@ -16,10 +20,7 @@ def is_prime(number: int) -> bool: :return: prime check result :rtype: bool - The result of this function is True if a number is prime, otherwise - False. - - Usage examples: + Usage: >>> assert not is_prime(0) >>> assert not is_prime(1) @@ -41,15 +42,16 @@ def is_prime(number: int) -> bool: def get_primes(limit: int) -> List[int]: - """Return a list of prime numbers within specified range + """ + Return a list of prime numbers within specified range :param limit: a range limit to look for prime numbers :type limit: int :return: the list of prime numbers within a specified range - :rtype: list[int] + :rtype: list - Usage examples: + Usage: >>> assert get_primes(10) == [2, 3, 5, 7] >>> assert get_primes(20) == [2, 3, 5, 7, 11, 13, 17, 19] @@ -60,13 +62,8 @@ def get_primes(limit: int) -> List[int]: def eratosthenes_sieve(limit: int) -> List[int]: - """Return a list of prime numbers till specified limit - - :param limit: a range limit to look for prime numbers - :type limit: int - - :return: the list of prime numbers within a specified range - :rtype: list[int] + """ + Return a list of prime numbers till specified limit In mathematics, the sieve of Eratosthenes is an ancient algorithm for finding all prime numbers up to any given limit. @@ -86,7 +83,13 @@ def eratosthenes_sieve(limit: int) -> List[int]: .. seealso:: https://en.wikipedia.org/wiki/Sieve_of_Eratosthenes - Usage examples: + :param limit: a range limit to look for prime numbers + :type limit: int + + :return: the list of prime numbers within a specified range + :rtype: list + + Usage: >>> assert eratosthenes_sieve(10) == [2, 3, 5, 7] >>> assert eratosthenes_sieve(20) == [2, 3, 5, 7, 11, 13, 17, 19] diff --git a/src/sequences/func.py b/src/sequences/func.py index e7cc226..62da6d8 100644 --- a/src/sequences/func.py +++ b/src/sequences/func.py @@ -7,13 +7,8 @@ def is_palindrome(origin: str) -> bool: - """Return a palindrome check result - - :param origin: a string to test - :type origin: str - - :return: return a palindrome check result - :rtype: bool + """ + Return a palindrome check result This function implements two pointers method. The left pointer is initialized at the beginning of an origin string, and the right one - @@ -23,7 +18,13 @@ def is_palindrome(origin: str) -> bool: returns True. Punctuation, word boundaries and capitalization are ignored. - Usage examples: + :param origin: a string to test + :type origin: str + + :return: return a palindrome check result + :rtype: bool + + Usage: >>> assert is_palindrome("aba") is True >>> assert is_palindrome("abc") is False @@ -54,7 +55,8 @@ def is_palindrome(origin: str) -> bool: def get_longest_palindrome(origin: str) -> str: - """Return the longest palindrome substring from the given input + """ + Return the longest palindrome substring from the given input :param origin: :type origin: str @@ -62,7 +64,7 @@ def get_longest_palindrome(origin: str) -> str: :return: the longest palindrome :rtype: str - Usage examples: + Usage: >>> assert get_longest_palindrome("0123219") == "12321" >>> assert get_longest_palindrome("1012210") == "012210" @@ -93,7 +95,14 @@ def expand(left: int, right: int) -> int: def are_parentheses_balanced(origin: str) -> bool: - """Return a validation result for a given parentheses sequence + """ + Return a validation result for a given parentheses sequence + + Validation rules: + + - each opening parentheses must be closed by the same type parentheses + - open parentheses must be closed in the correct order + - any non-parentheses characters are to be ignored :param origin: a parentheses sequence to validate :type origin: str @@ -101,13 +110,7 @@ def are_parentheses_balanced(origin: str) -> bool: :return: a validation result :rtype: bool - Validation rules: - - * each opening parentheses must be closed by the same type parentheses - * open parentheses must be closed in the correct order - * any non-parentheses characters are to be ignored - - Usage examples: + Usage: >>> assert are_parentheses_balanced("({[]})") is True >>> assert are_parentheses_balanced(")]}{[(") is False @@ -135,7 +138,8 @@ def are_parentheses_balanced(origin: str) -> bool: def get_longest_uniq_length(origin: str) -> int: - """Return the length of the longest on sequence of unique characters + """ + Return the length of the longest on sequence of unique characters :param origin: original sequences :type origin: str @@ -143,7 +147,7 @@ def get_longest_uniq_length(origin: str) -> int: :return: the length of the longest unique characters sequence :rtype: int - Usage examples: + Usage: >>> assert get_longest_uniq_length("abcdefg") == 7 >>> assert get_longest_uniq_length("racecar") == 4 diff --git a/src/sorting/func.py b/src/sorting/func.py index 2755332..6403b8f 100644 --- a/src/sorting/func.py +++ b/src/sorting/func.py @@ -7,13 +7,8 @@ def bubble_sort(origin: List[int]) -> List[int]: - """Return a sorted collection using the bubble sort algorithm - - :param origin: an original list to sort - :type origin: list[int] - - :return: a sorted list - :rtype: list[int] + """ + Return a sorted collection using the bubble sort algorithm Bubble sort is a sorting algorithm that compares two adjacent elements and swaps them until they are not in the intended order. @@ -24,7 +19,13 @@ def bubble_sort(origin: List[int]) -> List[int]: .. seealso:: https://www.programiz.com/dsa/bubble-sort - Usage examples: + :param origin: an original list to sort + :type origin: list + + :return: a sorted list + :rtype: list + + Usage: >>> assert bubble_sort([5, 4, 3, 2, 1]) == [1, 2, 3, 4, 5] >>> assert bubble_sort([1, 5, 2, 4, 3]) == [1, 2, 3, 4, 5] @@ -43,14 +44,8 @@ def bubble_sort(origin: List[int]) -> List[int]: def selection_sort(origin: List[int]) -> List[int]: - """Return a sorted collection using the selection sort algorithm - - :param origin: an original list to sort - :type origin: list[int] - - :return: a sorted list - :rtype: list[int] - + """ + Return a sorted collection using the selection sort algorithm Selection sort is a sorting algorithm that selects the smallest element from an unsorted list in each iteration and places that @@ -58,7 +53,13 @@ def selection_sort(origin: List[int]) -> List[int]: .. seealso:: https://www.programiz.com/dsa/selection-sort - Usage examples: + :param origin: an original list to sort + :type origin: list + + :return: a sorted list + :rtype: list + + Usage: >>> assert selection_sort([5, 4, 3, 2, 1]) == [1, 2, 3, 4, 5] >>> assert selection_sort([1, 5, 2, 4, 3]) == [1, 2, 3, 4, 5] @@ -81,13 +82,8 @@ def selection_sort(origin: List[int]) -> List[int]: def insertion_sort(origin: List[int]) -> List[int]: - """Return a sorted collection using the insertion sort algorithm - - :param origin: an original list to sort - :type origin: list[int] - - :return: a sorted list - :rtype: list[int] + """ + Return a sorted collection using the insertion sort algorithm Insertion sort is a sorting algorithm that places an unsorted element at its suitable place in each iteration. @@ -102,7 +98,13 @@ def insertion_sort(origin: List[int]) -> List[int]: .. seealso:: https://www.programiz.com/dsa/insertion-sort - Usage examples: + :param origin: an original list to sort + :type origin: list + + :return: a sorted list + :rtype: list + + Usage: >>> assert insertion_sort([5, 4, 3, 2, 1]) == [1, 2, 3, 4, 5] >>> assert insertion_sort([1, 5, 2, 4, 3]) == [1, 2, 3, 4, 5] @@ -126,19 +128,20 @@ def insertion_sort(origin: List[int]) -> List[int]: def merge_lists(list_a: List[int], list_b: List[int]) -> List[int]: - """Return a joined sorted list from two ordered lists + """ + Return a joined sorted list from two ordered lists + + Merge two lists that are already sorted into a new sorted list. :param list_a: first sorted list - :type list_a: list[int] + :type list_a: list :param list_b: second sorted list - :type list_b: list[int] + :type list_b: list :return: merged sorted list - :rtype: list[int] - - Merge two lists that are already sorted into a new sorted list. + :rtype: list - Usage examples: + Usage: >>> assert merge_lists([1, 3, 5], [2, 4]) == [1, 2, 3, 4, 5] @@ -168,14 +171,8 @@ def merge_lists(list_a: List[int], list_b: List[int]) -> List[int]: def merge_sort(origin: List[int]) -> List[int]: - """Return a sorted collection using the merge sort algorithm - - :param origin: an original list to sort - :type origin: list[int] - - :return: a sorted list - :rtype: list[int] - + """ + Return a sorted collection using the merge sort algorithm Merge sort is one of the most popular sorting algorithms that is based on the principle of "Divide and Conquer Algorithm". @@ -186,10 +183,16 @@ def merge_sort(origin: List[int]) -> List[int]: .. seealso:: https://www.programiz.com/dsa/merge-sort - Usage examples: + :param origin: an original list to sort + :type origin: list + + :return: a sorted list + :rtype: list + + Usage: - >>> merge_sort([5, 4, 3, 2, 1]) == [1, 2, 3, 4, 5] - >>> merge_sort([1, 5, 2, 4, 3]) == [1, 2, 3, 4, 5] + >>> assert merge_sort([5, 4, 3, 2, 1]) == [1, 2, 3, 4, 5] + >>> assert merge_sort([1, 5, 2, 4, 3]) == [1, 2, 3, 4, 5] """ @@ -205,13 +208,8 @@ def merge_sort(origin: List[int]) -> List[int]: def quick_sort(origin: List[int]) -> List[int]: - """Return a sorted collection using the quick sort algorithm - - :param origin: an original list to sort - :type origin: list[int] - - :return: a sorted list - :rtype: list[int] + """ + Return a sorted collection using the quick sort algorithm Quicksort is a sorting algorithm based on the **divide and conquer approach** where: @@ -229,10 +227,16 @@ def quick_sort(origin: List[int]) -> List[int]: .. seealso:: https://www.programiz.com/dsa/quick-sort - Usage examples: + :param origin: an original list to sort + :type origin: list + + :return: a sorted list + :rtype: list + + Usage: - >>> quick_sort([5, 4, 3, 2, 1]) == [1, 2, 3, 4, 5] - >>> quick_sort([1, 5, 2, 4, 3]) == [1, 2, 3, 4, 5] + >>> assert quick_sort([5, 4, 3, 2, 1]) == [1, 2, 3, 4, 5] + >>> assert quick_sort([1, 5, 2, 4, 3]) == [1, 2, 3, 4, 5] """ @@ -249,13 +253,8 @@ def quick_sort(origin: List[int]) -> List[int]: def counting_sort(origin: List[int]) -> List[int]: - """Return a sorted collection using the counting sort algorithm - - :param origin: an original list to sort - :type origin: list[int] - - :return: a sorted list - :rtype: list[int] + """ + Return a sorted collection using the counting sort algorithm Counting sort is a sorting algorithm that sorts the elements of a list by counting the number of occurrences of each unique element @@ -264,10 +263,16 @@ def counting_sort(origin: List[int]) -> List[int]: .. seealso:: https://www.programiz.com/dsa/counting-sort - Usage examples: + :param origin: an original list to sort + :type origin: list + + :return: a sorted list + :rtype: list + + Usage: - >>> counting_sort([5, 4, 3, 2, 1]) == [1, 2, 3, 4, 5] - >>> counting_sort([1, 5, 2, 4, 3]) == [1, 2, 3, 4, 5] + >>> assert counting_sort([5, 4, 3, 2, 1]) == [1, 2, 3, 4, 5] + >>> assert counting_sort([1, 5, 2, 4, 3]) == [1, 2, 3, 4, 5] """ @@ -293,64 +298,65 @@ def counting_sort(origin: List[int]) -> List[int]: return result -def radix_counting(origin: List[int], places: int) -> List[int]: - """Return a list sorted by significant place digit - - :param origin: an original unsorted list - :type origin: list[int] - :param places: a significant digits places - :type places: int +def radix_sort(origin: List[int]) -> List[int]: + """ + Return a sorted collection using the radix sort algorithm - :return: a sorted list, by digits at the significant place - :rtype: list[int] + Radix sort is a sorting algorithm that sorts the elements by first + grouping the individual digits of the same **place value**. Then, + sort the elements according to their increasing/decreasing order. - """ + First, we will sort elements based on the value of the unit place. + Then, we will sort elements based on the value of the tenth place. + This process goes on until the last significant place. - size: int = len(origin) - count: List[int] = [0] * 10 - result: List[int] = [0] * size + :param origin: an original list to sort + :type origin: list - for value in origin: - idx = value // places - count[idx % 10] += 1 + :return: a sorted list + :rtype: list - for idx in range(1, 10): - count[idx] += count[idx - 1] + Usage: - idx = size - 1 - while idx >= 0: - count_idx = (origin[idx] // places) % 10 - result_idx = count[count_idx] - 1 - result[result_idx] = origin[idx] - count[count_idx] -= 1 - idx -= 1 + >>> assert radix_sort([5, 4, 3, 2, 1]) == [1, 2, 3, 4, 5] + >>> assert radix_sort([1, 5, 2, 4, 3]) == [1, 2, 3, 4, 5] - return result + """ + def radix_counting(_origin: List[int], _places: int) -> List[int]: + """ + Return a list sorted by significant place digit -def radix_sort(origin: List[int]) -> List[int]: - """Return a sorted collection using the radix sort algorithm + :param _origin: an original unsorted list + :type _origin: list + :param _places: a significant digits places + :type _places: int - :param origin: an original list to sort - :type origin: list[int] + :return: a sorted list, by digits at the significant place + :rtype: list - :return: a sorted list - :rtype: list[int] + """ - Radix sort is a sorting algorithm that sorts the elements by first - grouping the individual digits of the same **place value**. Then, - sort the elements according to their increasing/decreasing order. + size: int = len(_origin) + count: List[int] = [0] * 10 + _radix_counting_result: List[int] = [0] * size - First, we will sort elements based on the value of the unit place. - Then, we will sort elements based on the value of the tenth place. - This process goes on until the last significant place. + for value in _origin: + idx = value // _places + count[idx % 10] += 1 - Usage examples: + for idx in range(1, 10): + count[idx] += count[idx - 1] - >>> assert radix_sort([5, 4, 3, 2, 1]) == [1, 2, 3, 4, 5] - >>> assert radix_sort([1, 5, 2, 4, 3]) == [1, 2, 3, 4, 5] + idx = size - 1 + while idx >= 0: + count_idx = (_origin[idx] // _places) % 10 + result_idx = count[count_idx] - 1 + _radix_counting_result[result_idx] = _origin[idx] + count[count_idx] -= 1 + idx -= 1 - """ + return _radix_counting_result max_value: int = max(origin) result: List[int] = origin.copy() @@ -364,13 +370,8 @@ def radix_sort(origin: List[int]) -> List[int]: def bucket_sort(origin: List[int]) -> List[int]: - """Return a sorted collection using the bucket sort algorithm - - :param origin: an original list to sort - :type origin: list[int] - - :return: a sorted list - :rtype: list[int] + """ + Return a sorted collection using the bucket sort algorithm Bucket sort is a sorting algorithm that divides the unsorted list elements into several groups called buckets. Each bucket is then @@ -382,7 +383,13 @@ def bucket_sort(origin: List[int]) -> List[int]: .. seealso:: https://www.programiz.com/dsa/bucket-sort - Usage examples: + :param origin: an original list to sort + :type origin: list + + :return: a sorted list + :rtype: list + + Usage: >>> assert bucket_sort([5, 4, 3, 2, 1]) == [1, 2, 3, 4, 5] >>> assert bubble_sort([1, 5, 2, 4, 3]) == [1, 2, 3, 4, 5] @@ -412,13 +419,8 @@ def bucket_sort(origin: List[int]) -> List[int]: def heap_sort(origin: List[int]) -> List[int]: - """Return a sorted collection using the heap sort algorithm - - :param origin: an original list to sort - :type origin: list[int] - - :return: a sorted list - :rtype: list[int] + """ + Return a sorted collection using the heap sort algorithm Heap sort is a popular and efficient sorting algorithm in computer programming. Learning how to write the heap sort algorithm requires @@ -429,10 +431,16 @@ def heap_sort(origin: List[int]) -> List[int]: .. seealso:: https://www.programiz.com/dsa/heap-sort - Usage examples: + :param origin: an original list to sort + :type origin: list + + :return: a sorted list + :rtype: list + + Usage: - >>> heap_sort([5, 4, 3, 2, 1]) == [1, 2, 3, 4, 5] - >>> heap_sort([1, 5, 2, 4, 3]) == [1, 2, 3, 4, 5] + >>> assert heap_sort([5, 4, 3, 2, 1]) == [1, 2, 3, 4, 5] + >>> assert heap_sort([1, 5, 2, 4, 3]) == [1, 2, 3, 4, 5] """ @@ -468,13 +476,8 @@ def heapify(_ds: List[int], _size: int, _idx: int) -> List[int]: def shell_sort(origin: List[int]) -> List[int]: - """Return a sorted collection using the shell sort algorithm - - :param origin: an original list to sort - :type origin: list[int] - - :return: a sorted list - :rtype: list[int] + """ + Return a sorted collection using the shell sort algorithm Shell sort is a generalized version of the insertion sort algorithm. It first sorts elements that are far apart from each other and @@ -482,7 +485,13 @@ def shell_sort(origin: List[int]) -> List[int]: .. seealso:: https://www.programiz.com/dsa/shell-sort - Usage examples: + :param origin: an original list to sort + :type origin: list + + :return: a sorted list + :rtype: list + + Usage: >>> assert shell_sort([5, 4, 3, 2, 1]) == [1, 2, 3, 4, 5] >>> assert shell_sort([1, 5, 2, 4, 3]) == [1, 2, 3, 4, 5] diff --git a/src/wtk/enums.py b/src/wtk/enums.py index f5f5b8c..6b4d70b 100644 --- a/src/wtk/enums.py +++ b/src/wtk/enums.py @@ -33,7 +33,8 @@ def __str__(self) -> str: def get_fight_result(attack: FightChoice, defence: FightChoice) -> FightResult: - """Return a fight result based on attack and defence choices + """ + Return a fight result based on attack and defence choices This function performs argument types validation first and raises TypeError in case of failure. After that the attack choice is compared