mirror of
https://github.com/TheAlgorithms/Python.git
synced 2025-01-18 16:27:02 +00:00
Fix sphinx/build_docs warnings for dynamic_programming (#12484)
* Fix sphinx/build_docs warnings for dynamic_programming * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Fix * Fix * Fix * Fix * Fix * Fix --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
This commit is contained in:
parent
493a7c153c
commit
7fa9b4bf1b
|
@ -9,8 +9,9 @@ from __future__ import annotations
|
||||||
def all_construct(target: str, word_bank: list[str] | None = None) -> list[list[str]]:
|
def all_construct(target: str, word_bank: list[str] | None = None) -> list[list[str]]:
|
||||||
"""
|
"""
|
||||||
returns the list containing all the possible
|
returns the list containing all the possible
|
||||||
combinations a string(target) can be constructed from
|
combinations a string(`target`) can be constructed from
|
||||||
the given list of substrings(word_bank)
|
the given list of substrings(`word_bank`)
|
||||||
|
|
||||||
>>> all_construct("hello", ["he", "l", "o"])
|
>>> all_construct("hello", ["he", "l", "o"])
|
||||||
[['he', 'l', 'l', 'o']]
|
[['he', 'l', 'l', 'o']]
|
||||||
>>> all_construct("purple",["purp","p","ur","le","purpl"])
|
>>> all_construct("purple",["purp","p","ur","le","purpl"])
|
||||||
|
|
|
@ -7,16 +7,17 @@ the sum of chosen elements is equal to the target number tar.
|
||||||
Example
|
Example
|
||||||
|
|
||||||
Input:
|
Input:
|
||||||
N = 3
|
* N = 3
|
||||||
target = 5
|
* target = 5
|
||||||
array = [1, 2, 5]
|
* array = [1, 2, 5]
|
||||||
|
|
||||||
Output:
|
Output:
|
||||||
9
|
9
|
||||||
|
|
||||||
Approach:
|
Approach:
|
||||||
The basic idea is to go over recursively to find the way such that the sum
|
The basic idea is to go over recursively to find the way such that the sum
|
||||||
of chosen elements is “tar”. For every element, we have two choices
|
of chosen elements is `target`. For every element, we have two choices
|
||||||
|
|
||||||
1. Include the element in our set of chosen elements.
|
1. Include the element in our set of chosen elements.
|
||||||
2. Don't include the element in our set of chosen elements.
|
2. Don't include the element in our set of chosen elements.
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -3,11 +3,12 @@
|
||||||
|
|
||||||
def fizz_buzz(number: int, iterations: int) -> str:
|
def fizz_buzz(number: int, iterations: int) -> str:
|
||||||
"""
|
"""
|
||||||
Plays FizzBuzz.
|
| Plays FizzBuzz.
|
||||||
Prints Fizz if number is a multiple of 3.
|
| Prints Fizz if number is a multiple of ``3``.
|
||||||
Prints Buzz if its a multiple of 5.
|
| Prints Buzz if its a multiple of ``5``.
|
||||||
Prints FizzBuzz if its a multiple of both 3 and 5 or 15.
|
| Prints FizzBuzz if its a multiple of both ``3`` and ``5`` or ``15``.
|
||||||
Else Prints The Number Itself.
|
| Else Prints The Number Itself.
|
||||||
|
|
||||||
>>> fizz_buzz(1,7)
|
>>> fizz_buzz(1,7)
|
||||||
'1 2 Fizz 4 Buzz Fizz 7 '
|
'1 2 Fizz 4 Buzz Fizz 7 '
|
||||||
>>> fizz_buzz(1,0)
|
>>> fizz_buzz(1,0)
|
||||||
|
|
|
@ -11,7 +11,7 @@ def mf_knapsack(i, wt, val, j):
|
||||||
"""
|
"""
|
||||||
This code involves the concept of memory functions. Here we solve the subproblems
|
This code involves the concept of memory functions. Here we solve the subproblems
|
||||||
which are needed unlike the below example
|
which are needed unlike the below example
|
||||||
F is a 2D array with -1s filled up
|
F is a 2D array with ``-1`` s filled up
|
||||||
"""
|
"""
|
||||||
global f # a global dp table for knapsack
|
global f # a global dp table for knapsack
|
||||||
if f[i][j] < 0:
|
if f[i][j] < 0:
|
||||||
|
@ -45,22 +45,24 @@ def knapsack_with_example_solution(w: int, wt: list, val: list):
|
||||||
the several possible optimal subsets.
|
the several possible optimal subsets.
|
||||||
|
|
||||||
Parameters
|
Parameters
|
||||||
---------
|
----------
|
||||||
|
|
||||||
W: int, the total maximum weight for the given knapsack problem.
|
* `w`: int, the total maximum weight for the given knapsack problem.
|
||||||
wt: list, the vector of weights for all items where wt[i] is the weight
|
* `wt`: list, the vector of weights for all items where ``wt[i]`` is the weight
|
||||||
of the i-th item.
|
of the ``i``-th item.
|
||||||
val: list, the vector of values for all items where val[i] is the value
|
* `val`: list, the vector of values for all items where ``val[i]`` is the value
|
||||||
of the i-th item
|
of the ``i``-th item
|
||||||
|
|
||||||
Returns
|
Returns
|
||||||
-------
|
-------
|
||||||
optimal_val: float, the optimal value for the given knapsack problem
|
|
||||||
example_optional_set: set, the indices of one of the optimal subsets
|
* `optimal_val`: float, the optimal value for the given knapsack problem
|
||||||
|
* `example_optional_set`: set, the indices of one of the optimal subsets
|
||||||
which gave rise to the optimal value.
|
which gave rise to the optimal value.
|
||||||
|
|
||||||
Examples
|
Examples
|
||||||
-------
|
--------
|
||||||
|
|
||||||
>>> knapsack_with_example_solution(10, [1, 3, 5, 2], [10, 20, 100, 22])
|
>>> knapsack_with_example_solution(10, [1, 3, 5, 2], [10, 20, 100, 22])
|
||||||
(142, {2, 3, 4})
|
(142, {2, 3, 4})
|
||||||
>>> knapsack_with_example_solution(6, [4, 3, 2, 3], [3, 2, 4, 4])
|
>>> knapsack_with_example_solution(6, [4, 3, 2, 3], [3, 2, 4, 4])
|
||||||
|
@ -104,19 +106,19 @@ def _construct_solution(dp: list, wt: list, i: int, j: int, optimal_set: set):
|
||||||
a filled DP table and the vector of weights
|
a filled DP table and the vector of weights
|
||||||
|
|
||||||
Parameters
|
Parameters
|
||||||
---------
|
----------
|
||||||
|
|
||||||
dp: list of list, the table of a solved integer weight dynamic programming problem
|
* `dp`: list of list, the table of a solved integer weight dynamic programming
|
||||||
|
problem
|
||||||
wt: list or tuple, the vector of weights of the items
|
* `wt`: list or tuple, the vector of weights of the items
|
||||||
i: int, the index of the item under consideration
|
* `i`: int, the index of the item under consideration
|
||||||
j: int, the current possible maximum weight
|
* `j`: int, the current possible maximum weight
|
||||||
optimal_set: set, the optimal subset so far. This gets modified by the function.
|
* `optimal_set`: set, the optimal subset so far. This gets modified by the function.
|
||||||
|
|
||||||
Returns
|
Returns
|
||||||
-------
|
-------
|
||||||
None
|
|
||||||
|
|
||||||
|
``None``
|
||||||
"""
|
"""
|
||||||
# for the current item i at a maximum weight j to be part of an optimal subset,
|
# for the current item i at a maximum weight j to be part of an optimal subset,
|
||||||
# the optimal value at (i, j) must be greater than the optimal value at (i-1, j).
|
# the optimal value at (i, j) must be greater than the optimal value at (i-1, j).
|
||||||
|
|
|
@ -1,8 +1,11 @@
|
||||||
"""
|
"""
|
||||||
Longest Common Substring Problem Statement: Given two sequences, find the
|
Longest Common Substring Problem Statement:
|
||||||
|
Given two sequences, find the
|
||||||
longest common substring present in both of them. A substring is
|
longest common substring present in both of them. A substring is
|
||||||
necessarily continuous.
|
necessarily continuous.
|
||||||
Example: "abcdef" and "xabded" have two longest common substrings, "ab" or "de".
|
|
||||||
|
Example:
|
||||||
|
``abcdef`` and ``xabded`` have two longest common substrings, ``ab`` or ``de``.
|
||||||
Therefore, algorithm should return any one of them.
|
Therefore, algorithm should return any one of them.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
@ -10,6 +13,7 @@ Therefore, algorithm should return any one of them.
|
||||||
def longest_common_substring(text1: str, text2: str) -> str:
|
def longest_common_substring(text1: str, text2: str) -> str:
|
||||||
"""
|
"""
|
||||||
Finds the longest common substring between two strings.
|
Finds the longest common substring between two strings.
|
||||||
|
|
||||||
>>> longest_common_substring("", "")
|
>>> longest_common_substring("", "")
|
||||||
''
|
''
|
||||||
>>> longest_common_substring("a","")
|
>>> longest_common_substring("a","")
|
||||||
|
|
|
@ -7,8 +7,10 @@ increasing subsequence of a given sequence.
|
||||||
The problem is:
|
The problem is:
|
||||||
Given an array, to find the longest and increasing sub-array in that given array and
|
Given an array, to find the longest and increasing sub-array in that given array and
|
||||||
return it.
|
return it.
|
||||||
Example: [10, 22, 9, 33, 21, 50, 41, 60, 80] as input will return
|
|
||||||
[10, 22, 33, 41, 60, 80] as output
|
Example:
|
||||||
|
``[10, 22, 9, 33, 21, 50, 41, 60, 80]`` as input will return
|
||||||
|
``[10, 22, 33, 41, 60, 80]`` as output
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
@ -17,6 +19,7 @@ from __future__ import annotations
|
||||||
def longest_subsequence(array: list[int]) -> list[int]: # This function is recursive
|
def longest_subsequence(array: list[int]) -> list[int]: # This function is recursive
|
||||||
"""
|
"""
|
||||||
Some examples
|
Some examples
|
||||||
|
|
||||||
>>> longest_subsequence([10, 22, 9, 33, 21, 50, 41, 60, 80])
|
>>> longest_subsequence([10, 22, 9, 33, 21, 50, 41, 60, 80])
|
||||||
[10, 22, 33, 41, 60, 80]
|
[10, 22, 33, 41, 60, 80]
|
||||||
>>> longest_subsequence([4, 8, 7, 5, 1, 12, 2, 3, 9])
|
>>> longest_subsequence([4, 8, 7, 5, 1, 12, 2, 3, 9])
|
||||||
|
|
|
@ -1,8 +1,10 @@
|
||||||
"""
|
"""
|
||||||
Find the minimum number of multiplications needed to multiply chain of matrices.
|
| Find the minimum number of multiplications needed to multiply chain of matrices.
|
||||||
Reference: https://www.geeksforgeeks.org/matrix-chain-multiplication-dp-8/
|
| Reference: https://www.geeksforgeeks.org/matrix-chain-multiplication-dp-8/
|
||||||
|
|
||||||
The algorithm has interesting real-world applications. Example:
|
The algorithm has interesting real-world applications.
|
||||||
|
|
||||||
|
Example:
|
||||||
1. Image transformations in Computer Graphics as images are composed of matrix.
|
1. Image transformations in Computer Graphics as images are composed of matrix.
|
||||||
2. Solve complex polynomial equations in the field of algebra using least processing
|
2. Solve complex polynomial equations in the field of algebra using least processing
|
||||||
power.
|
power.
|
||||||
|
@ -11,32 +13,36 @@ The algorithm has interesting real-world applications. Example:
|
||||||
4. Self-driving car navigation can be made more accurate as matrix multiplication can
|
4. Self-driving car navigation can be made more accurate as matrix multiplication can
|
||||||
accurately determine position and orientation of obstacles in short time.
|
accurately determine position and orientation of obstacles in short time.
|
||||||
|
|
||||||
Python doctests can be run with the following command:
|
Python doctests can be run with the following command::
|
||||||
|
|
||||||
python -m doctest -v matrix_chain_multiply.py
|
python -m doctest -v matrix_chain_multiply.py
|
||||||
|
|
||||||
Given a sequence arr[] that represents chain of 2D matrices such that the dimension of
|
Given a sequence ``arr[]`` that represents chain of 2D matrices such that the dimension
|
||||||
the ith matrix is arr[i-1]*arr[i].
|
of the ``i`` th matrix is ``arr[i-1]*arr[i]``.
|
||||||
So suppose arr = [40, 20, 30, 10, 30] means we have 4 matrices of dimensions
|
So suppose ``arr = [40, 20, 30, 10, 30]`` means we have ``4`` matrices of dimensions
|
||||||
40*20, 20*30, 30*10 and 10*30.
|
``40*20``, ``20*30``, ``30*10`` and ``10*30``.
|
||||||
|
|
||||||
matrix_chain_multiply() returns an integer denoting minimum number of multiplications to
|
``matrix_chain_multiply()`` returns an integer denoting minimum number of
|
||||||
multiply the chain.
|
multiplications to multiply the chain.
|
||||||
|
|
||||||
We do not need to perform actual multiplication here.
|
We do not need to perform actual multiplication here.
|
||||||
We only need to decide the order in which to perform the multiplication.
|
We only need to decide the order in which to perform the multiplication.
|
||||||
|
|
||||||
Hints:
|
Hints:
|
||||||
1. Number of multiplications (ie cost) to multiply 2 matrices
|
1. Number of multiplications (ie cost) to multiply ``2`` matrices
|
||||||
of size m*p and p*n is m*p*n.
|
of size ``m*p`` and ``p*n`` is ``m*p*n``.
|
||||||
2. Cost of matrix multiplication is associative ie (M1*M2)*M3 != M1*(M2*M3)
|
2. Cost of matrix multiplication is not associative ie ``(M1*M2)*M3 != M1*(M2*M3)``
|
||||||
3. Matrix multiplication is not commutative. So, M1*M2 does not mean M2*M1 can be done.
|
3. Matrix multiplication is not commutative. So, ``M1*M2`` does not mean ``M2*M1``
|
||||||
|
can be done.
|
||||||
4. To determine the required order, we can try different combinations.
|
4. To determine the required order, we can try different combinations.
|
||||||
|
|
||||||
So, this problem has overlapping sub-problems and can be solved using recursion.
|
So, this problem has overlapping sub-problems and can be solved using recursion.
|
||||||
We use Dynamic Programming for optimal time complexity.
|
We use Dynamic Programming for optimal time complexity.
|
||||||
|
|
||||||
Example input:
|
Example input:
|
||||||
arr = [40, 20, 30, 10, 30]
|
``arr = [40, 20, 30, 10, 30]``
|
||||||
output: 26000
|
output:
|
||||||
|
``26000``
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from collections.abc import Iterator
|
from collections.abc import Iterator
|
||||||
|
@ -50,12 +56,13 @@ def matrix_chain_multiply(arr: list[int]) -> int:
|
||||||
Find the minimum number of multiplcations required to multiply the chain of matrices
|
Find the minimum number of multiplcations required to multiply the chain of matrices
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
arr: The input array of integers.
|
`arr`: The input array of integers.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
Minimum number of multiplications needed to multiply the chain
|
Minimum number of multiplications needed to multiply the chain
|
||||||
|
|
||||||
Examples:
|
Examples:
|
||||||
|
|
||||||
>>> matrix_chain_multiply([1, 2, 3, 4, 3])
|
>>> matrix_chain_multiply([1, 2, 3, 4, 3])
|
||||||
30
|
30
|
||||||
>>> matrix_chain_multiply([10])
|
>>> matrix_chain_multiply([10])
|
||||||
|
@ -66,8 +73,7 @@ def matrix_chain_multiply(arr: list[int]) -> int:
|
||||||
722
|
722
|
||||||
>>> matrix_chain_multiply(list(range(1, 100)))
|
>>> matrix_chain_multiply(list(range(1, 100)))
|
||||||
323398
|
323398
|
||||||
|
>>> # matrix_chain_multiply(list(range(1, 251)))
|
||||||
# >>> matrix_chain_multiply(list(range(1, 251)))
|
|
||||||
# 2626798
|
# 2626798
|
||||||
"""
|
"""
|
||||||
if len(arr) < 2:
|
if len(arr) < 2:
|
||||||
|
@ -93,8 +99,10 @@ def matrix_chain_multiply(arr: list[int]) -> int:
|
||||||
def matrix_chain_order(dims: list[int]) -> int:
|
def matrix_chain_order(dims: list[int]) -> int:
|
||||||
"""
|
"""
|
||||||
Source: https://en.wikipedia.org/wiki/Matrix_chain_multiplication
|
Source: https://en.wikipedia.org/wiki/Matrix_chain_multiplication
|
||||||
|
|
||||||
The dynamic programming solution is faster than cached the recursive solution and
|
The dynamic programming solution is faster than cached the recursive solution and
|
||||||
can handle larger inputs.
|
can handle larger inputs.
|
||||||
|
|
||||||
>>> matrix_chain_order([1, 2, 3, 4, 3])
|
>>> matrix_chain_order([1, 2, 3, 4, 3])
|
||||||
30
|
30
|
||||||
>>> matrix_chain_order([10])
|
>>> matrix_chain_order([10])
|
||||||
|
@ -105,8 +113,7 @@ def matrix_chain_order(dims: list[int]) -> int:
|
||||||
722
|
722
|
||||||
>>> matrix_chain_order(list(range(1, 100)))
|
>>> matrix_chain_order(list(range(1, 100)))
|
||||||
323398
|
323398
|
||||||
|
>>> # matrix_chain_order(list(range(1, 251))) # Max before RecursionError is raised
|
||||||
# >>> matrix_chain_order(list(range(1, 251))) # Max before RecursionError is raised
|
|
||||||
# 2626798
|
# 2626798
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
def max_product_subarray(numbers: list[int]) -> int:
|
def max_product_subarray(numbers: list[int]) -> int:
|
||||||
"""
|
"""
|
||||||
Returns the maximum product that can be obtained by multiplying a
|
Returns the maximum product that can be obtained by multiplying a
|
||||||
contiguous subarray of the given integer list `nums`.
|
contiguous subarray of the given integer list `numbers`.
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
>>> max_product_subarray([2, 3, -2, 4])
|
>>> max_product_subarray([2, 3, -2, 4])
|
||||||
6
|
6
|
||||||
>>> max_product_subarray((-2, 0, -1))
|
>>> max_product_subarray((-2, 0, -1))
|
||||||
|
|
|
@ -5,6 +5,7 @@ import sys
|
||||||
def minimum_squares_to_represent_a_number(number: int) -> int:
|
def minimum_squares_to_represent_a_number(number: int) -> int:
|
||||||
"""
|
"""
|
||||||
Count the number of minimum squares to represent a number
|
Count the number of minimum squares to represent a number
|
||||||
|
|
||||||
>>> minimum_squares_to_represent_a_number(25)
|
>>> minimum_squares_to_represent_a_number(25)
|
||||||
1
|
1
|
||||||
>>> minimum_squares_to_represent_a_number(37)
|
>>> minimum_squares_to_represent_a_number(37)
|
||||||
|
|
|
@ -1,23 +1,25 @@
|
||||||
"""
|
"""
|
||||||
Regex matching check if a text matches pattern or not.
|
Regex matching check if a text matches pattern or not.
|
||||||
Pattern:
|
Pattern:
|
||||||
'.' Matches any single character.
|
|
||||||
'*' Matches zero or more of the preceding element.
|
1. ``.`` Matches any single character.
|
||||||
|
2. ``*`` Matches zero or more of the preceding element.
|
||||||
|
|
||||||
More info:
|
More info:
|
||||||
https://medium.com/trick-the-interviwer/regular-expression-matching-9972eb74c03
|
https://medium.com/trick-the-interviwer/regular-expression-matching-9972eb74c03
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
def recursive_match(text: str, pattern: str) -> bool:
|
def recursive_match(text: str, pattern: str) -> bool:
|
||||||
"""
|
r"""
|
||||||
Recursive matching algorithm.
|
Recursive matching algorithm.
|
||||||
|
|
||||||
Time complexity: O(2 ^ (|text| + |pattern|))
|
| Time complexity: O(2^(\|text\| + \|pattern\|))
|
||||||
Space complexity: Recursion depth is O(|text| + |pattern|).
|
| Space complexity: Recursion depth is O(\|text\| + \|pattern\|).
|
||||||
|
|
||||||
:param text: Text to match.
|
:param text: Text to match.
|
||||||
:param pattern: Pattern to match.
|
:param pattern: Pattern to match.
|
||||||
:return: True if text matches pattern, False otherwise.
|
:return: ``True`` if `text` matches `pattern`, ``False`` otherwise.
|
||||||
|
|
||||||
>>> recursive_match('abc', 'a.c')
|
>>> recursive_match('abc', 'a.c')
|
||||||
True
|
True
|
||||||
|
@ -48,15 +50,15 @@ def recursive_match(text: str, pattern: str) -> bool:
|
||||||
|
|
||||||
|
|
||||||
def dp_match(text: str, pattern: str) -> bool:
|
def dp_match(text: str, pattern: str) -> bool:
|
||||||
"""
|
r"""
|
||||||
Dynamic programming matching algorithm.
|
Dynamic programming matching algorithm.
|
||||||
|
|
||||||
Time complexity: O(|text| * |pattern|)
|
| Time complexity: O(\|text\| * \|pattern\|)
|
||||||
Space complexity: O(|text| * |pattern|)
|
| Space complexity: O(\|text\| * \|pattern\|)
|
||||||
|
|
||||||
:param text: Text to match.
|
:param text: Text to match.
|
||||||
:param pattern: Pattern to match.
|
:param pattern: Pattern to match.
|
||||||
:return: True if text matches pattern, False otherwise.
|
:return: ``True`` if `text` matches `pattern`, ``False`` otherwise.
|
||||||
|
|
||||||
>>> dp_match('abc', 'a.c')
|
>>> dp_match('abc', 'a.c')
|
||||||
True
|
True
|
||||||
|
|
|
@ -20,18 +20,21 @@ def naive_cut_rod_recursive(n: int, prices: list):
|
||||||
Runtime: O(2^n)
|
Runtime: O(2^n)
|
||||||
|
|
||||||
Arguments
|
Arguments
|
||||||
-------
|
---------
|
||||||
n: int, the length of the rod
|
|
||||||
prices: list, the prices for each piece of rod. ``p[i-i]`` is the
|
* `n`: int, the length of the rod
|
||||||
|
* `prices`: list, the prices for each piece of rod. ``p[i-i]`` is the
|
||||||
price for a rod of length ``i``
|
price for a rod of length ``i``
|
||||||
|
|
||||||
Returns
|
Returns
|
||||||
-------
|
-------
|
||||||
The maximum revenue obtainable for a rod of length n given the list of prices
|
|
||||||
|
The maximum revenue obtainable for a rod of length `n` given the list of prices
|
||||||
for each piece.
|
for each piece.
|
||||||
|
|
||||||
Examples
|
Examples
|
||||||
--------
|
--------
|
||||||
|
|
||||||
>>> naive_cut_rod_recursive(4, [1, 5, 8, 9])
|
>>> naive_cut_rod_recursive(4, [1, 5, 8, 9])
|
||||||
10
|
10
|
||||||
>>> naive_cut_rod_recursive(10, [1, 5, 8, 9, 10, 17, 17, 20, 24, 30])
|
>>> naive_cut_rod_recursive(10, [1, 5, 8, 9, 10, 17, 17, 20, 24, 30])
|
||||||
|
@ -54,28 +57,30 @@ def top_down_cut_rod(n: int, prices: list):
|
||||||
"""
|
"""
|
||||||
Constructs a top-down dynamic programming solution for the rod-cutting
|
Constructs a top-down dynamic programming solution for the rod-cutting
|
||||||
problem via memoization. This function serves as a wrapper for
|
problem via memoization. This function serves as a wrapper for
|
||||||
_top_down_cut_rod_recursive
|
``_top_down_cut_rod_recursive``
|
||||||
|
|
||||||
Runtime: O(n^2)
|
Runtime: O(n^2)
|
||||||
|
|
||||||
Arguments
|
Arguments
|
||||||
--------
|
---------
|
||||||
n: int, the length of the rod
|
|
||||||
prices: list, the prices for each piece of rod. ``p[i-i]`` is the
|
* `n`: int, the length of the rod
|
||||||
|
* `prices`: list, the prices for each piece of rod. ``p[i-i]`` is the
|
||||||
price for a rod of length ``i``
|
price for a rod of length ``i``
|
||||||
|
|
||||||
Note
|
.. note::
|
||||||
----
|
For convenience and because Python's lists using ``0``-indexing, ``length(max_rev)
|
||||||
For convenience and because Python's lists using 0-indexing, length(max_rev) =
|
= n + 1``, to accommodate for the revenue obtainable from a rod of length ``0``.
|
||||||
n + 1, to accommodate for the revenue obtainable from a rod of length 0.
|
|
||||||
|
|
||||||
Returns
|
Returns
|
||||||
-------
|
-------
|
||||||
The maximum revenue obtainable for a rod of length n given the list of prices
|
|
||||||
|
The maximum revenue obtainable for a rod of length `n` given the list of prices
|
||||||
for each piece.
|
for each piece.
|
||||||
|
|
||||||
Examples
|
Examples
|
||||||
-------
|
--------
|
||||||
|
|
||||||
>>> top_down_cut_rod(4, [1, 5, 8, 9])
|
>>> top_down_cut_rod(4, [1, 5, 8, 9])
|
||||||
10
|
10
|
||||||
>>> top_down_cut_rod(10, [1, 5, 8, 9, 10, 17, 17, 20, 24, 30])
|
>>> top_down_cut_rod(10, [1, 5, 8, 9, 10, 17, 17, 20, 24, 30])
|
||||||
|
@ -94,16 +99,18 @@ def _top_down_cut_rod_recursive(n: int, prices: list, max_rev: list):
|
||||||
Runtime: O(n^2)
|
Runtime: O(n^2)
|
||||||
|
|
||||||
Arguments
|
Arguments
|
||||||
--------
|
---------
|
||||||
n: int, the length of the rod
|
|
||||||
prices: list, the prices for each piece of rod. ``p[i-i]`` is the
|
* `n`: int, the length of the rod
|
||||||
|
* `prices`: list, the prices for each piece of rod. ``p[i-i]`` is the
|
||||||
price for a rod of length ``i``
|
price for a rod of length ``i``
|
||||||
max_rev: list, the computed maximum revenue for a piece of rod.
|
* `max_rev`: list, the computed maximum revenue for a piece of rod.
|
||||||
``max_rev[i]`` is the maximum revenue obtainable for a rod of length ``i``
|
``max_rev[i]`` is the maximum revenue obtainable for a rod of length ``i``
|
||||||
|
|
||||||
Returns
|
Returns
|
||||||
-------
|
-------
|
||||||
The maximum revenue obtainable for a rod of length n given the list of prices
|
|
||||||
|
The maximum revenue obtainable for a rod of length `n` given the list of prices
|
||||||
for each piece.
|
for each piece.
|
||||||
"""
|
"""
|
||||||
if max_rev[n] >= 0:
|
if max_rev[n] >= 0:
|
||||||
|
@ -130,18 +137,21 @@ def bottom_up_cut_rod(n: int, prices: list):
|
||||||
Runtime: O(n^2)
|
Runtime: O(n^2)
|
||||||
|
|
||||||
Arguments
|
Arguments
|
||||||
----------
|
---------
|
||||||
n: int, the maximum length of the rod.
|
|
||||||
prices: list, the prices for each piece of rod. ``p[i-i]`` is the
|
* `n`: int, the maximum length of the rod.
|
||||||
|
* `prices`: list, the prices for each piece of rod. ``p[i-i]`` is the
|
||||||
price for a rod of length ``i``
|
price for a rod of length ``i``
|
||||||
|
|
||||||
Returns
|
Returns
|
||||||
-------
|
-------
|
||||||
The maximum revenue obtainable from cutting a rod of length n given
|
|
||||||
|
The maximum revenue obtainable from cutting a rod of length `n` given
|
||||||
the prices for each piece of rod p.
|
the prices for each piece of rod p.
|
||||||
|
|
||||||
Examples
|
Examples
|
||||||
-------
|
--------
|
||||||
|
|
||||||
>>> bottom_up_cut_rod(4, [1, 5, 8, 9])
|
>>> bottom_up_cut_rod(4, [1, 5, 8, 9])
|
||||||
10
|
10
|
||||||
>>> bottom_up_cut_rod(10, [1, 5, 8, 9, 10, 17, 17, 20, 24, 30])
|
>>> bottom_up_cut_rod(10, [1, 5, 8, 9, 10, 17, 17, 20, 24, 30])
|
||||||
|
@ -168,12 +178,11 @@ def _enforce_args(n: int, prices: list):
|
||||||
"""
|
"""
|
||||||
Basic checks on the arguments to the rod-cutting algorithms
|
Basic checks on the arguments to the rod-cutting algorithms
|
||||||
|
|
||||||
n: int, the length of the rod
|
* `n`: int, the length of the rod
|
||||||
prices: list, the price list for each piece of rod.
|
* `prices`: list, the price list for each piece of rod.
|
||||||
|
|
||||||
Throws ValueError:
|
Throws ``ValueError``:
|
||||||
|
if `n` is negative or there are fewer items in the price list than the length of
|
||||||
if n is negative or there are fewer items in the price list than the length of
|
|
||||||
the rod
|
the rod
|
||||||
"""
|
"""
|
||||||
if n < 0:
|
if n < 0:
|
||||||
|
|
|
@ -1,11 +1,14 @@
|
||||||
def subset_combinations(elements: list[int], n: int) -> list:
|
def subset_combinations(elements: list[int], n: int) -> list:
|
||||||
"""
|
"""
|
||||||
Compute n-element combinations from a given list using dynamic programming.
|
Compute n-element combinations from a given list using dynamic programming.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
elements: The list of elements from which combinations will be generated.
|
* `elements`: The list of elements from which combinations will be generated.
|
||||||
n: The number of elements in each combination.
|
* `n`: The number of elements in each combination.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
A list of tuples, each representing a combination of n elements.
|
A list of tuples, each representing a combination of `n` elements.
|
||||||
|
|
||||||
>>> subset_combinations(elements=[10, 20, 30, 40], n=2)
|
>>> subset_combinations(elements=[10, 20, 30, 40], n=2)
|
||||||
[(10, 20), (10, 30), (10, 40), (20, 30), (20, 40), (30, 40)]
|
[(10, 20), (10, 30), (10, 40), (20, 30), (20, 40), (30, 40)]
|
||||||
>>> subset_combinations(elements=[1, 2, 3], n=1)
|
>>> subset_combinations(elements=[1, 2, 3], n=1)
|
||||||
|
|
|
@ -11,9 +11,11 @@ def viterbi(
|
||||||
"""
|
"""
|
||||||
Viterbi Algorithm, to find the most likely path of
|
Viterbi Algorithm, to find the most likely path of
|
||||||
states from the start and the expected output.
|
states from the start and the expected output.
|
||||||
|
|
||||||
https://en.wikipedia.org/wiki/Viterbi_algorithm
|
https://en.wikipedia.org/wiki/Viterbi_algorithm
|
||||||
sdafads
|
|
||||||
Wikipedia example
|
Wikipedia example
|
||||||
|
|
||||||
>>> observations = ["normal", "cold", "dizzy"]
|
>>> observations = ["normal", "cold", "dizzy"]
|
||||||
>>> states = ["Healthy", "Fever"]
|
>>> states = ["Healthy", "Fever"]
|
||||||
>>> start_p = {"Healthy": 0.6, "Fever": 0.4}
|
>>> start_p = {"Healthy": 0.6, "Fever": 0.4}
|
||||||
|
@ -27,97 +29,78 @@ def viterbi(
|
||||||
... }
|
... }
|
||||||
>>> viterbi(observations, states, start_p, trans_p, emit_p)
|
>>> viterbi(observations, states, start_p, trans_p, emit_p)
|
||||||
['Healthy', 'Healthy', 'Fever']
|
['Healthy', 'Healthy', 'Fever']
|
||||||
|
|
||||||
>>> viterbi((), states, start_p, trans_p, emit_p)
|
>>> viterbi((), states, start_p, trans_p, emit_p)
|
||||||
Traceback (most recent call last):
|
Traceback (most recent call last):
|
||||||
...
|
...
|
||||||
ValueError: There's an empty parameter
|
ValueError: There's an empty parameter
|
||||||
|
|
||||||
>>> viterbi(observations, (), start_p, trans_p, emit_p)
|
>>> viterbi(observations, (), start_p, trans_p, emit_p)
|
||||||
Traceback (most recent call last):
|
Traceback (most recent call last):
|
||||||
...
|
...
|
||||||
ValueError: There's an empty parameter
|
ValueError: There's an empty parameter
|
||||||
|
|
||||||
>>> viterbi(observations, states, {}, trans_p, emit_p)
|
>>> viterbi(observations, states, {}, trans_p, emit_p)
|
||||||
Traceback (most recent call last):
|
Traceback (most recent call last):
|
||||||
...
|
...
|
||||||
ValueError: There's an empty parameter
|
ValueError: There's an empty parameter
|
||||||
|
|
||||||
>>> viterbi(observations, states, start_p, {}, emit_p)
|
>>> viterbi(observations, states, start_p, {}, emit_p)
|
||||||
Traceback (most recent call last):
|
Traceback (most recent call last):
|
||||||
...
|
...
|
||||||
ValueError: There's an empty parameter
|
ValueError: There's an empty parameter
|
||||||
|
|
||||||
>>> viterbi(observations, states, start_p, trans_p, {})
|
>>> viterbi(observations, states, start_p, trans_p, {})
|
||||||
Traceback (most recent call last):
|
Traceback (most recent call last):
|
||||||
...
|
...
|
||||||
ValueError: There's an empty parameter
|
ValueError: There's an empty parameter
|
||||||
|
|
||||||
>>> viterbi("invalid", states, start_p, trans_p, emit_p)
|
>>> viterbi("invalid", states, start_p, trans_p, emit_p)
|
||||||
Traceback (most recent call last):
|
Traceback (most recent call last):
|
||||||
...
|
...
|
||||||
ValueError: observations_space must be a list
|
ValueError: observations_space must be a list
|
||||||
|
|
||||||
>>> viterbi(["valid", 123], states, start_p, trans_p, emit_p)
|
>>> viterbi(["valid", 123], states, start_p, trans_p, emit_p)
|
||||||
Traceback (most recent call last):
|
Traceback (most recent call last):
|
||||||
...
|
...
|
||||||
ValueError: observations_space must be a list of strings
|
ValueError: observations_space must be a list of strings
|
||||||
|
|
||||||
>>> viterbi(observations, "invalid", start_p, trans_p, emit_p)
|
>>> viterbi(observations, "invalid", start_p, trans_p, emit_p)
|
||||||
Traceback (most recent call last):
|
Traceback (most recent call last):
|
||||||
...
|
...
|
||||||
ValueError: states_space must be a list
|
ValueError: states_space must be a list
|
||||||
|
|
||||||
>>> viterbi(observations, ["valid", 123], start_p, trans_p, emit_p)
|
>>> viterbi(observations, ["valid", 123], start_p, trans_p, emit_p)
|
||||||
Traceback (most recent call last):
|
Traceback (most recent call last):
|
||||||
...
|
...
|
||||||
ValueError: states_space must be a list of strings
|
ValueError: states_space must be a list of strings
|
||||||
|
|
||||||
>>> viterbi(observations, states, "invalid", trans_p, emit_p)
|
>>> viterbi(observations, states, "invalid", trans_p, emit_p)
|
||||||
Traceback (most recent call last):
|
Traceback (most recent call last):
|
||||||
...
|
...
|
||||||
ValueError: initial_probabilities must be a dict
|
ValueError: initial_probabilities must be a dict
|
||||||
|
|
||||||
>>> viterbi(observations, states, {2:2}, trans_p, emit_p)
|
>>> viterbi(observations, states, {2:2}, trans_p, emit_p)
|
||||||
Traceback (most recent call last):
|
Traceback (most recent call last):
|
||||||
...
|
...
|
||||||
ValueError: initial_probabilities all keys must be strings
|
ValueError: initial_probabilities all keys must be strings
|
||||||
|
|
||||||
>>> viterbi(observations, states, {"a":2}, trans_p, emit_p)
|
>>> viterbi(observations, states, {"a":2}, trans_p, emit_p)
|
||||||
Traceback (most recent call last):
|
Traceback (most recent call last):
|
||||||
...
|
...
|
||||||
ValueError: initial_probabilities all values must be float
|
ValueError: initial_probabilities all values must be float
|
||||||
|
|
||||||
>>> viterbi(observations, states, start_p, "invalid", emit_p)
|
>>> viterbi(observations, states, start_p, "invalid", emit_p)
|
||||||
Traceback (most recent call last):
|
Traceback (most recent call last):
|
||||||
...
|
...
|
||||||
ValueError: transition_probabilities must be a dict
|
ValueError: transition_probabilities must be a dict
|
||||||
|
|
||||||
>>> viterbi(observations, states, start_p, {"a":2}, emit_p)
|
>>> viterbi(observations, states, start_p, {"a":2}, emit_p)
|
||||||
Traceback (most recent call last):
|
Traceback (most recent call last):
|
||||||
...
|
...
|
||||||
ValueError: transition_probabilities all values must be dict
|
ValueError: transition_probabilities all values must be dict
|
||||||
|
|
||||||
>>> viterbi(observations, states, start_p, {2:{2:2}}, emit_p)
|
>>> viterbi(observations, states, start_p, {2:{2:2}}, emit_p)
|
||||||
Traceback (most recent call last):
|
Traceback (most recent call last):
|
||||||
...
|
...
|
||||||
ValueError: transition_probabilities all keys must be strings
|
ValueError: transition_probabilities all keys must be strings
|
||||||
|
|
||||||
>>> viterbi(observations, states, start_p, {"a":{2:2}}, emit_p)
|
>>> viterbi(observations, states, start_p, {"a":{2:2}}, emit_p)
|
||||||
Traceback (most recent call last):
|
Traceback (most recent call last):
|
||||||
...
|
...
|
||||||
ValueError: transition_probabilities all keys must be strings
|
ValueError: transition_probabilities all keys must be strings
|
||||||
|
|
||||||
>>> viterbi(observations, states, start_p, {"a":{"b":2}}, emit_p)
|
>>> viterbi(observations, states, start_p, {"a":{"b":2}}, emit_p)
|
||||||
Traceback (most recent call last):
|
Traceback (most recent call last):
|
||||||
...
|
...
|
||||||
ValueError: transition_probabilities nested dictionary all values must be float
|
ValueError: transition_probabilities nested dictionary all values must be float
|
||||||
|
|
||||||
>>> viterbi(observations, states, start_p, trans_p, "invalid")
|
>>> viterbi(observations, states, start_p, trans_p, "invalid")
|
||||||
Traceback (most recent call last):
|
Traceback (most recent call last):
|
||||||
...
|
...
|
||||||
ValueError: emission_probabilities must be a dict
|
ValueError: emission_probabilities must be a dict
|
||||||
|
|
||||||
>>> viterbi(observations, states, start_p, trans_p, None)
|
>>> viterbi(observations, states, start_p, trans_p, None)
|
||||||
Traceback (most recent call last):
|
Traceback (most recent call last):
|
||||||
...
|
...
|
||||||
|
@ -213,7 +196,6 @@ def _validation(
|
||||||
... "Fever": {"normal": 0.1, "cold": 0.3, "dizzy": 0.6},
|
... "Fever": {"normal": 0.1, "cold": 0.3, "dizzy": 0.6},
|
||||||
... }
|
... }
|
||||||
>>> _validation(observations, states, start_p, trans_p, emit_p)
|
>>> _validation(observations, states, start_p, trans_p, emit_p)
|
||||||
|
|
||||||
>>> _validation([], states, start_p, trans_p, emit_p)
|
>>> _validation([], states, start_p, trans_p, emit_p)
|
||||||
Traceback (most recent call last):
|
Traceback (most recent call last):
|
||||||
...
|
...
|
||||||
|
@ -242,7 +224,6 @@ def _validate_not_empty(
|
||||||
"""
|
"""
|
||||||
>>> _validate_not_empty(["a"], ["b"], {"c":0.5},
|
>>> _validate_not_empty(["a"], ["b"], {"c":0.5},
|
||||||
... {"d": {"e": 0.6}}, {"f": {"g": 0.7}})
|
... {"d": {"e": 0.6}}, {"f": {"g": 0.7}})
|
||||||
|
|
||||||
>>> _validate_not_empty(["a"], ["b"], {"c":0.5}, {}, {"f": {"g": 0.7}})
|
>>> _validate_not_empty(["a"], ["b"], {"c":0.5}, {}, {"f": {"g": 0.7}})
|
||||||
Traceback (most recent call last):
|
Traceback (most recent call last):
|
||||||
...
|
...
|
||||||
|
@ -267,12 +248,10 @@ def _validate_not_empty(
|
||||||
def _validate_lists(observations_space: Any, states_space: Any) -> None:
|
def _validate_lists(observations_space: Any, states_space: Any) -> None:
|
||||||
"""
|
"""
|
||||||
>>> _validate_lists(["a"], ["b"])
|
>>> _validate_lists(["a"], ["b"])
|
||||||
|
|
||||||
>>> _validate_lists(1234, ["b"])
|
>>> _validate_lists(1234, ["b"])
|
||||||
Traceback (most recent call last):
|
Traceback (most recent call last):
|
||||||
...
|
...
|
||||||
ValueError: observations_space must be a list
|
ValueError: observations_space must be a list
|
||||||
|
|
||||||
>>> _validate_lists(["a"], [3])
|
>>> _validate_lists(["a"], [3])
|
||||||
Traceback (most recent call last):
|
Traceback (most recent call last):
|
||||||
...
|
...
|
||||||
|
@ -285,7 +264,6 @@ def _validate_lists(observations_space: Any, states_space: Any) -> None:
|
||||||
def _validate_list(_object: Any, var_name: str) -> None:
|
def _validate_list(_object: Any, var_name: str) -> None:
|
||||||
"""
|
"""
|
||||||
>>> _validate_list(["a"], "mock_name")
|
>>> _validate_list(["a"], "mock_name")
|
||||||
|
|
||||||
>>> _validate_list("a", "mock_name")
|
>>> _validate_list("a", "mock_name")
|
||||||
Traceback (most recent call last):
|
Traceback (most recent call last):
|
||||||
...
|
...
|
||||||
|
@ -294,7 +272,6 @@ def _validate_list(_object: Any, var_name: str) -> None:
|
||||||
Traceback (most recent call last):
|
Traceback (most recent call last):
|
||||||
...
|
...
|
||||||
ValueError: mock_name must be a list of strings
|
ValueError: mock_name must be a list of strings
|
||||||
|
|
||||||
"""
|
"""
|
||||||
if not isinstance(_object, list):
|
if not isinstance(_object, list):
|
||||||
msg = f"{var_name} must be a list"
|
msg = f"{var_name} must be a list"
|
||||||
|
@ -313,7 +290,6 @@ def _validate_dicts(
|
||||||
) -> None:
|
) -> None:
|
||||||
"""
|
"""
|
||||||
>>> _validate_dicts({"c":0.5}, {"d": {"e": 0.6}}, {"f": {"g": 0.7}})
|
>>> _validate_dicts({"c":0.5}, {"d": {"e": 0.6}}, {"f": {"g": 0.7}})
|
||||||
|
|
||||||
>>> _validate_dicts("invalid", {"d": {"e": 0.6}}, {"f": {"g": 0.7}})
|
>>> _validate_dicts("invalid", {"d": {"e": 0.6}}, {"f": {"g": 0.7}})
|
||||||
Traceback (most recent call last):
|
Traceback (most recent call last):
|
||||||
...
|
...
|
||||||
|
@ -339,7 +315,6 @@ def _validate_dicts(
|
||||||
def _validate_nested_dict(_object: Any, var_name: str) -> None:
|
def _validate_nested_dict(_object: Any, var_name: str) -> None:
|
||||||
"""
|
"""
|
||||||
>>> _validate_nested_dict({"a":{"b": 0.5}}, "mock_name")
|
>>> _validate_nested_dict({"a":{"b": 0.5}}, "mock_name")
|
||||||
|
|
||||||
>>> _validate_nested_dict("invalid", "mock_name")
|
>>> _validate_nested_dict("invalid", "mock_name")
|
||||||
Traceback (most recent call last):
|
Traceback (most recent call last):
|
||||||
...
|
...
|
||||||
|
@ -367,7 +342,6 @@ def _validate_dict(
|
||||||
) -> None:
|
) -> None:
|
||||||
"""
|
"""
|
||||||
>>> _validate_dict({"b": 0.5}, "mock_name", float)
|
>>> _validate_dict({"b": 0.5}, "mock_name", float)
|
||||||
|
|
||||||
>>> _validate_dict("invalid", "mock_name", float)
|
>>> _validate_dict("invalid", "mock_name", float)
|
||||||
Traceback (most recent call last):
|
Traceback (most recent call last):
|
||||||
...
|
...
|
||||||
|
|
Loading…
Reference in New Issue
Block a user