From 6f581bcf822537a70965137d2d6b8ad8469fa715 Mon Sep 17 00:00:00 2001 From: Serhii Horodilov Date: Fri, 21 Apr 2023 21:21:34 +0300 Subject: [PATCH 1/7] Updated docstrings - iss. #24 Signed-off-by: Serhii Horodilov # Conflicts: # src/bisearch/prefix.py # src/chess/piece.py # src/conv_store/models.py # src/datasets/func.py # src/dynamic/memoization.py # src/dynamic/tabulation.py # src/primes/func.py # src/sequences/func.py # src/sorting/func.py --- src/bisearch/prefix.py | 8 +- src/chess/piece.py | 4 +- src/conv_store/models.py | 7 +- src/datasets/func.py | 97 ++++++------------- src/dynamic/memoization.py | 39 ++++---- src/dynamic/tabulation.py | 58 ++++++----- src/primes/func.py | 35 ++++--- src/sequences/func.py | 44 +++++---- src/sorting/func.py | 194 +++++++++++++++++++------------------ src/wtk/enums.py | 3 +- 10 files changed, 240 insertions(+), 249 deletions(-) diff --git a/src/bisearch/prefix.py b/src/bisearch/prefix.py index 93d612a..18cfb9e 100644 --- a/src/bisearch/prefix.py +++ b/src/bisearch/prefix.py @@ -20,7 +20,7 @@ def bisect_right(origin: List[str], search: str = "") -> int: """Return the most right one index matching the search value :param origin: a list of strings - :type origin: list[str] + :type origin: list :param search: a prefix to search :type search: str @@ -58,7 +58,7 @@ def bisect_left(origin: List[str], search: str = "") -> int: """Return the most left one index matching the search value :param origin: a list of strings - :type origin: list[str] + :type origin: list :param search: a prefix to search :type search: str @@ -96,12 +96,12 @@ def find_all(origin: List[str], search: str = "") -> List[str]: """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 """ diff --git a/src/chess/piece.py b/src/chess/piece.py index cceec70..98cd8aa 100644 --- a/src/chess/piece.py +++ b/src/chess/piece.py @@ -28,9 +28,9 @@ def __init__(self, """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 """ diff --git a/src/conv_store/models.py b/src/conv_store/models.py index 56d0949..63e5764 100644 --- a/src/conv_store/models.py +++ b/src/conv_store/models.py @@ -158,8 +158,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` @@ -221,11 +221,10 @@ def sub_product(self, 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..05cce6f 100644 --- a/src/datasets/func.py +++ b/src/datasets/func.py @@ -141,15 +141,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 +162,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 +193,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 +220,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 +248,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 +263,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,50 +289,13 @@ 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) return filtered_dataset - - -NestedIntList = Union[int, List["NestedIntList"]] - - -def flatten(origin: List[NestedIntList]) -> List[int]: - """ - Flattens a list of integers and nested lists of integers - - :param origin: an original list - - :return: a single-level list of integers - - Usage: - - >>> assert flatten([1, 2, 3]) == [1, 2, 3] - >>> assert flatten(([[1], [2], [3]])) == [1, 2, 3] - >>> assert flatten([1, [2, 3]]) == [1, 2, 3] - >>> assert flatten([1, [[2], [3]]]) == [1, 2, 3] - - """ - - result: List[int] = [] - - for item in origin: - if isinstance(item, list): - result.extend(flatten(item)) - else: - result.append(item) - - return result diff --git a/src/dynamic/memoization.py b/src/dynamic/memoization.py index a68946e..21f35a7 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,13 +51,8 @@ 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 - - :param height: grid height - :param width: grid width - - :return: the number of available routes - :rtype: int + """ + 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). @@ -64,6 +60,14 @@ def get_grid_travels(height: int, width: int, /) -> int: 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 + """ if height <= 0 or width <= 0: @@ -78,20 +82,21 @@ 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. - """ # check base cases diff --git a/src/dynamic/tabulation.py b/src/dynamic/tabulation.py index 1a31cb5..d4962fd 100644 --- a/src/dynamic/tabulation.py +++ b/src/dynamic/tabulation.py @@ -10,17 +10,18 @@ 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] - - 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. + :rtype: list Usage examples: @@ -47,13 +48,8 @@ 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 - - :param height: grid height - :param width: grid width - - :return: the number of available routes - :rtype: int + """ + 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**. @@ -61,6 +57,14 @@ def get_grid_travels(height: int, width: int, /) -> int: 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 + """ if height <= 0 or width <= 0: @@ -83,18 +87,19 @@ 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. - """ # check base cases @@ -127,15 +132,8 @@ 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 - - :param target: the desired number - :type target: int - :param numbers: the sequence of numbers available for usage - :type numbers: list[int] - - :return: None if impossible, otherwise list of numbers - :rtype: list[int] | None + """ + 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. @@ -144,6 +142,14 @@ def get_target_numbers(target: int, numbers: List[int]) -> Optional[List[int]]: 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 + + :return: None if impossible, otherwise list of numbers + :rtype: list, optional + """ # check base cases 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..7d58518 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[int] + + :return: a sorted list + :rtype: list[int] + + 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[int] + + :return: a sorted list + :rtype: list[int] + + 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[int] + + :return: a sorted list + :rtype: list[int] + + 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,7 +183,13 @@ 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[int] + + :return: a sorted list + :rtype: list[int] + + 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] @@ -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,7 +227,13 @@ 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] @@ -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,7 +263,13 @@ 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] @@ -294,15 +299,16 @@ def counting_sort(origin: List[int]) -> List[int]: def radix_counting(origin: List[int], places: int) -> List[int]: - """Return a list sorted by significant place digit + """ + Return a list sorted by significant place digit :param origin: an original unsorted list - :type origin: list[int] + :type origin: list :param places: a significant digits places :type places: int :return: a sorted list, by digits at the significant place - :rtype: list[int] + :rtype: list """ @@ -329,13 +335,8 @@ def radix_counting(origin: List[int], places: int) -> List[int]: def radix_sort(origin: List[int]) -> List[int]: - """Return a sorted collection using the radix 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 radix sort algorithm Radix sort is a sorting algorithm that sorts the elements by first grouping the individual digits of the same **place value**. Then, @@ -345,7 +346,13 @@ def radix_sort(origin: List[int]) -> List[int]: Then, we will sort elements based on the value of the tenth place. This process goes on until the last significant place. - Usage examples: + :param origin: an original list to sort + :type origin: list + + :return: a sorted list + :rtype: list + + Usage: >>> 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] @@ -364,13 +371,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 +384,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 +420,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,7 +432,13 @@ 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] @@ -468,13 +477,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 +486,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 From 2f3527ee90a6ce46b2adfd6c706d95105af7a54a Mon Sep 17 00:00:00 2001 From: Serhii Horodilov Date: Tue, 11 Apr 2023 23:05:16 +0300 Subject: [PATCH 2/7] fixup! Updated docstrings - iss. #24 Signed-off-by: Serhii Horodilov --- src/bisearch/prefix.py | 25 +++++++++++--------- src/calc/func.py | 48 +++++++++++++++++++++----------------- src/chess/func.py | 6 +++-- src/chess/piece.py | 15 ++++++++---- src/chess/symbols.py | 1 + src/conv_store/models.py | 9 ++++--- src/dynamic/memoization.py | 4 ++++ src/dynamic/tabulation.py | 8 ++++++- 8 files changed, 72 insertions(+), 44 deletions(-) diff --git a/src/bisearch/prefix.py b/src/bisearch/prefix.py index 18cfb9e..6d5bc16 100644 --- a/src/bisearch/prefix.py +++ b/src/bisearch/prefix.py @@ -17,7 +17,12 @@ 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 @@ -29,10 +34,6 @@ def bisect_right(origin: List[str], search: str = "") -> int: :raise: NotFound - 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. - """ low: int = 0 @@ -55,7 +56,12 @@ 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 @@ -67,10 +73,6 @@ def bisect_left(origin: List[str], search: str = "") -> int: :raise: NotFound - 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. - """ low: int = 0 @@ -93,7 +95,8 @@ 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 diff --git a/src/calc/func.py b/src/calc/func.py index 744fd44..d0ea0bd 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,9 +78,6 @@ 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. - """ if idx <= 0: @@ -91,7 +94,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 +108,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..7dd1c9d 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 @@ -29,7 +30,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 98cd8aa..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,7 +26,8 @@ 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, 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 63e5764..fa3598f 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 @@ -216,7 +218,8 @@ 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 diff --git a/src/dynamic/memoization.py b/src/dynamic/memoization.py index 21f35a7..247e277 100644 --- a/src/dynamic/memoization.py +++ b/src/dynamic/memoization.py @@ -68,6 +68,8 @@ def get_grid_travels(height: int, width: int, /) -> int: :return: the number of available routes :rtype: int + # TODO: add usage + """ if height <= 0 or width <= 0: @@ -97,6 +99,8 @@ def can_get_target(target: int, numbers: List[int], :return: the check result :rtype: bool + # TODO: add usage + """ # check base cases diff --git a/src/dynamic/tabulation.py b/src/dynamic/tabulation.py index d4962fd..782bfa5 100644 --- a/src/dynamic/tabulation.py +++ b/src/dynamic/tabulation.py @@ -23,7 +23,7 @@ def get_fibonacci_sequence(size: int, /) -> List[int]: :return: the Fibonacci sequence :rtype: list - Usage examples: + Usage: >>> assert get_fibonacci_sequence(0) == [] >>> assert get_fibonacci_sequence(1) == [0] @@ -65,6 +65,8 @@ def get_grid_travels(height: int, width: int, /) -> int: :return: the number of available routes :rtype: int + # TODO: add usage + """ if height <= 0 or width <= 0: @@ -100,6 +102,8 @@ def can_get_target(target: int, numbers: List[int]) -> bool: :return: the check result :rtype: bool + TODO: add usage + """ # check base cases @@ -150,6 +154,8 @@ def get_target_numbers(target: int, numbers: List[int]) -> Optional[List[int]]: :return: None if impossible, otherwise list of numbers :rtype: list, optional + # TODO: add usage + """ # check base cases From 1b4ee011a2a5720353fd52e2cdce7ff155548b2a Mon Sep 17 00:00:00 2001 From: Serhii Horodilov Date: Fri, 21 Apr 2023 00:50:45 +0300 Subject: [PATCH 3/7] fixup! Updated docstrings - iss. #24 Signed-off-by: Serhii Horodilov --- src/bisearch/prefix.py | 10 +++- src/calc/func.py | 8 +++ src/chess/func.py | 4 ++ src/conv_store/models.py | 2 +- src/dynamic/memoization.py | 4 +- src/sorting/func.py | 103 ++++++++++++++++++------------------- 6 files changed, 74 insertions(+), 57 deletions(-) diff --git a/src/bisearch/prefix.py b/src/bisearch/prefix.py index 6d5bc16..55904c5 100644 --- a/src/bisearch/prefix.py +++ b/src/bisearch/prefix.py @@ -32,7 +32,9 @@ def bisect_right(origin: List[str], search: str = "") -> int: :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 + + # TODO: usage """ @@ -71,7 +73,9 @@ def bisect_left(origin: List[str], search: str = "") -> int: :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 + + # TODO: usage """ @@ -106,6 +110,8 @@ def find_all(origin: List[str], search: str = "") -> List[str]: :return: the list of strings starting with the search prefix :rtype: list + # TODO: usage + """ try: diff --git a/src/calc/func.py b/src/calc/func.py index d0ea0bd..50decaa 100644 --- a/src/calc/func.py +++ b/src/calc/func.py @@ -78,6 +78,14 @@ def get_fibonacci_number_nr(idx: int, /) -> int: :return: a sequence's member :rtype: int + 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 + """ if idx <= 0: diff --git a/src/chess/func.py b/src/chess/func.py index 7dd1c9d..1bb4128 100644 --- a/src/chess/func.py +++ b/src/chess/func.py @@ -21,6 +21,8 @@ def within_board(position: Tuple[int, int]) -> bool: :return: True if position is within a chess board, otherwise False :rtype: bool + # TODO: usage + """ position_x, position_y = position @@ -41,6 +43,8 @@ def filter_can_move(pieces: List[Piece], :return: a list of pieces that can move to specified position :rtype: list + # TODO: usage + """ return [piece for piece in pieces if piece.can_move(position)] diff --git a/src/conv_store/models.py b/src/conv_store/models.py index fa3598f..25982f5 100644 --- a/src/conv_store/models.py +++ b/src/conv_store/models.py @@ -169,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 """ diff --git a/src/dynamic/memoization.py b/src/dynamic/memoization.py index 247e277..f2b623a 100644 --- a/src/dynamic/memoization.py +++ b/src/dynamic/memoization.py @@ -68,7 +68,7 @@ def get_grid_travels(height: int, width: int, /) -> int: :return: the number of available routes :rtype: int - # TODO: add usage + # TODO: usage """ @@ -99,7 +99,7 @@ def can_get_target(target: int, numbers: List[int], :return: the check result :rtype: bool - # TODO: add usage + # TODO: usage """ diff --git a/src/sorting/func.py b/src/sorting/func.py index 7d58518..6403b8f 100644 --- a/src/sorting/func.py +++ b/src/sorting/func.py @@ -20,10 +20,10 @@ def bubble_sort(origin: List[int]) -> List[int]: .. seealso:: https://www.programiz.com/dsa/bubble-sort :param origin: an original list to sort - :type origin: list[int] + :type origin: list :return: a sorted list - :rtype: list[int] + :rtype: list Usage: @@ -54,10 +54,10 @@ def selection_sort(origin: List[int]) -> List[int]: .. seealso:: https://www.programiz.com/dsa/selection-sort :param origin: an original list to sort - :type origin: list[int] + :type origin: list :return: a sorted list - :rtype: list[int] + :rtype: list Usage: @@ -99,10 +99,10 @@ def insertion_sort(origin: List[int]) -> List[int]: .. seealso:: https://www.programiz.com/dsa/insertion-sort :param origin: an original list to sort - :type origin: list[int] + :type origin: list :return: a sorted list - :rtype: list[int] + :rtype: list Usage: @@ -184,15 +184,15 @@ def merge_sort(origin: List[int]) -> List[int]: .. seealso:: https://www.programiz.com/dsa/merge-sort :param origin: an original list to sort - :type origin: list[int] + :type origin: list :return: a sorted list - :rtype: list[int] + :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] """ @@ -235,8 +235,8 @@ def quick_sort(origin: List[int]) -> List[int]: 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] """ @@ -271,8 +271,8 @@ def counting_sort(origin: List[int]) -> List[int]: 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] """ @@ -298,42 +298,6 @@ 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 - :param places: a significant digits places - :type places: int - - :return: a sorted list, by digits at the significant place - :rtype: list - - """ - - size: int = len(origin) - count: List[int] = [0] * 10 - result: List[int] = [0] * size - - for value in origin: - idx = value // places - count[idx % 10] += 1 - - for idx in range(1, 10): - count[idx] += count[idx - 1] - - 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 - - return result - - def radix_sort(origin: List[int]) -> List[int]: """ Return a sorted collection using the radix sort algorithm @@ -359,6 +323,41 @@ def radix_sort(origin: List[int]) -> List[int]: """ + 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 + :param _places: a significant digits places + :type _places: int + + :return: a sorted list, by digits at the significant place + :rtype: list + + """ + + size: int = len(_origin) + count: List[int] = [0] * 10 + _radix_counting_result: List[int] = [0] * size + + for value in _origin: + idx = value // _places + count[idx % 10] += 1 + + for idx in range(1, 10): + count[idx] += count[idx - 1] + + 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() @@ -440,8 +439,8 @@ def heap_sort(origin: List[int]) -> List[int]: 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] """ From 4762be9e1ef3f8d23d288b4bd11d7a95b930eb9e Mon Sep 17 00:00:00 2001 From: Serhii Horodilov Date: Fri, 21 Apr 2023 21:40:49 +0300 Subject: [PATCH 4/7] Updated usage examples Signed-off-by: Serhii Horodilov --- src/chess/func.py | 11 ++++++++--- src/dynamic/memoization.py | 14 ++++++++++++-- src/dynamic/tabulation.py | 21 ++++++++++++++++++--- 3 files changed, 38 insertions(+), 8 deletions(-) diff --git a/src/chess/func.py b/src/chess/func.py index 1bb4128..bdd675b 100644 --- a/src/chess/func.py +++ b/src/chess/func.py @@ -21,7 +21,14 @@ def within_board(position: Tuple[int, int]) -> bool: :return: True if position is within a chess board, otherwise False :rtype: bool - # TODO: usage + 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 """ @@ -43,8 +50,6 @@ def filter_can_move(pieces: List[Piece], :return: a list of pieces that can move to specified position :rtype: list - # TODO: usage - """ return [piece for piece in pieces if piece.can_move(position)] diff --git a/src/dynamic/memoization.py b/src/dynamic/memoization.py index f2b623a..6799b91 100644 --- a/src/dynamic/memoization.py +++ b/src/dynamic/memoization.py @@ -68,7 +68,12 @@ def get_grid_travels(height: int, width: int, /) -> int: :return: the number of available routes :rtype: int - # TODO: usage + 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 """ @@ -99,7 +104,12 @@ def can_get_target(target: int, numbers: List[int], :return: the check result :rtype: bool - # TODO: usage + 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 782bfa5..ec5c006 100644 --- a/src/dynamic/tabulation.py +++ b/src/dynamic/tabulation.py @@ -65,7 +65,12 @@ def get_grid_travels(height: int, width: int, /) -> int: :return: the number of available routes :rtype: int - # TODO: add usage + 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 """ @@ -102,7 +107,12 @@ def can_get_target(target: int, numbers: List[int]) -> bool: :return: the check result :rtype: bool - TODO: add usage + 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 """ @@ -154,7 +164,12 @@ def get_target_numbers(target: int, numbers: List[int]) -> Optional[List[int]]: :return: None if impossible, otherwise list of numbers :rtype: list, optional - # TODO: add usage + Usage: + + >>> 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] """ From 649c49f26aa58abb56673e98159391195a788745 Mon Sep 17 00:00:00 2001 From: Serhii Horodilov Date: Fri, 21 Apr 2023 21:52:40 +0300 Subject: [PATCH 5/7] fixup! Updated usage examples Signed-off-by: Serhii Horodilov --- src/bisearch/prefix.py | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/src/bisearch/prefix.py b/src/bisearch/prefix.py index 55904c5..fa725b2 100644 --- a/src/bisearch/prefix.py +++ b/src/bisearch/prefix.py @@ -34,7 +34,12 @@ def bisect_right(origin: List[str], search: str = "") -> int: :raise NotFound: if the searched value isn't in the list - # TODO: usage + 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 """ @@ -75,7 +80,12 @@ def bisect_left(origin: List[str], search: str = "") -> int: :raise NotFound: if the searched value isn't in the list - # TODO: usage + 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 """ @@ -110,7 +120,12 @@ def find_all(origin: List[str], search: str = "") -> List[str]: :return: the list of strings starting with the search prefix :rtype: list - # TODO: usage + 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"] """ From 227f943ea9438815196041eedcfe2d12ddbeaabf Mon Sep 17 00:00:00 2001 From: Serhii Horodilov Date: Fri, 21 Apr 2023 22:00:23 +0300 Subject: [PATCH 6/7] Reverted flatten function deletion Signed-off-by: Serhii Horodilov --- src/datasets/func.py | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/src/datasets/func.py b/src/datasets/func.py index 05cce6f..501ac0d 100644 --- a/src/datasets/func.py +++ b/src/datasets/func.py @@ -299,3 +299,34 @@ def filter_by_values(origin: List[Dict[str, Hashable]], filtered_dataset.append(entry) return filtered_dataset + + +NestedIntList = Union[int, List["NestedIntList"]] + + +def flatten(origin: List[NestedIntList]) -> List[int]: + """ + Flattens a list of integers and nested lists of integers + + :param origin: an original list + + :return: a single-level list of integers + + Usage: + + >>> assert flatten([1, 2, 3]) == [1, 2, 3] + >>> assert flatten(([[1], [2], [3]])) == [1, 2, 3] + >>> assert flatten([1, [2, 3]]) == [1, 2, 3] + >>> assert flatten([1, [[2], [3]]]) == [1, 2, 3] + + """ + + result: List[int] = [] + + for item in origin: + if isinstance(item, list): + result.extend(flatten(item)) + else: + result.append(item) + + return result From 2b487c72199020e18dfdd6d733877004e90981e1 Mon Sep 17 00:00:00 2001 From: Serhii Horodilov Date: Fri, 21 Apr 2023 22:05:27 +0300 Subject: [PATCH 7/7] Added docstring for "get_both_top_low_students" function Signed-off-by: Serhii Horodilov --- src/datasets/func.py | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/src/datasets/func.py b/src/datasets/func.py index 501ac0d..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": []}