From da0bb4cfabccd9cadb79360469668bd37707ffaf Mon Sep 17 00:00:00 2001 From: alexpantyukhin Date: Tue, 20 Dec 2022 15:08:43 +0400 Subject: [PATCH 01/15] add word_break dynamic approach up -> down. --- dynamic_programming/word_break.py | 105 ++++++++++++++++++++++++++++++ 1 file changed, 105 insertions(+) create mode 100644 dynamic_programming/word_break.py diff --git a/dynamic_programming/word_break.py b/dynamic_programming/word_break.py new file mode 100644 index 000000000000..a2fda48a3ec9 --- /dev/null +++ b/dynamic_programming/word_break.py @@ -0,0 +1,105 @@ +""" +Author : Alexander Pantyukhin +Date : December 12, 2022 + +Task: +Given a string s and a dictionary of strings wordDict, +return true if s can be segmented into a space-separated +sequence of one or more dictionary words. + +Note that the same word in the dictionary may be reused +multiple times in the segmentation. + +Implementation notes: Trie + Dynamic programming up -> down. +The Trie keeps all wordDict words. It will be useful for scanning +available words for the current position in the string. + +Leetcode: +https://leetcode.com/problems/word-break/description/ + +Runtime: O(n * n) +Space: O(n) +""" + +from functools import lru_cache + +def wordBreak(s: str, word_dict: list[str]) -> bool: + """ + Return True if numbers have opposite signs False otherwise. + + >>> wordBreak("applepenapple", ["apple","pen"]) + True + >>> wordBreak("catsandog", ["cats","dog","sand","and","cat"]) + False + >>> wordBreak("cars", ["car","ca","rs"]) + True + >>> wordBreak("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaab", ["a","aa","aaa","aaaa","aaaaa","aaaaaa","aaaaaaa","aaaaaaaa","aaaaaaaaa","aaaaaaaaaa"]) + False + >>> wordBreak('abc', []) + False + >>> wordBreak(123, ['a']) + Traceback (most recent call last): + ... + ValueError: the s should be not empty string + >>> wordBreak('', ['a']) + Traceback (most recent call last): + ... + ValueError: the s should be not empty string + >>> wordBreak('abc', [123]) + Traceback (most recent call last): + ... + ValueError: the word_dict should a list of non empty string + >>> wordBreak('abc', ['']) + Traceback (most recent call last): + ... + ValueError: the word_dict should a list of non empty string + """ + + # Validation + if not isinstance(s, str) or len(s) == 0: + raise ValueError('the s should be not empty string') + + if not isinstance(word_dict, list) or not all( + [isinstance(item, str) and len(item) > 0 for item in word_dict]): + raise ValueError('the word_dict should a list of non empty string') + + # Build trie + trie = {} + WORD_KEEPER = 'WORD_KEEPER' + for word in word_dict: + trie_node = trie + for c in word: + if c not in trie_node: + trie_node[c] = {} + + trie_node = trie_node[c] + + trie_node[WORD_KEEPER] = True + + len_s = len(s) + + # Dynamic programming method + @lru_cache(maxsize=None) + def is_breakable(index: int) -> bool: + if index == len_s: + return True + + trie_node = trie + for i in range(index, len_s): + trie_node = trie_node.get(s[i], None) + + if trie_node is None: + return False + + if trie_node.get(WORD_KEEPER, False) and is_breakable(i + 1): + return True + + return False + + return is_breakable(0) + + +if __name__ == "__main__": + import doctest + + doctest.testmod() From 319aca4e6014f41db1cea762fc388e11611efd61 Mon Sep 17 00:00:00 2001 From: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> Date: Tue, 20 Dec 2022 11:10:10 +0000 Subject: [PATCH 02/15] updating DIRECTORY.md --- DIRECTORY.md | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/DIRECTORY.md b/DIRECTORY.md index 34ce88a4f2ab..3437df12cbf5 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -14,7 +14,6 @@ ## Audio Filters * [Butterworth Filter](audio_filters/butterworth_filter.py) - * [Equal Loudness Filter](audio_filters/equal_loudness_filter.py) * [Iir Filter](audio_filters/iir_filter.py) * [Show Response](audio_filters/show_response.py) @@ -79,6 +78,7 @@ * [A1Z26](ciphers/a1z26.py) * [Affine Cipher](ciphers/affine_cipher.py) * [Atbash](ciphers/atbash.py) + * [Autokey](ciphers/autokey.py) * [Baconian Cipher](ciphers/baconian_cipher.py) * [Base16](ciphers/base16.py) * [Base32](ciphers/base32.py) @@ -328,6 +328,7 @@ * [Subset Generation](dynamic_programming/subset_generation.py) * [Sum Of Subset](dynamic_programming/sum_of_subset.py) * [Viterbi](dynamic_programming/viterbi.py) + * [Word Break](dynamic_programming/word_break.py) ## Electronics * [Builtin Voltage](electronics/builtin_voltage.py) @@ -475,8 +476,6 @@ * [Decision Tree](machine_learning/decision_tree.py) * Forecasting * [Run](machine_learning/forecasting/run.py) - * [Gaussian Naive Bayes](machine_learning/gaussian_naive_bayes.py) - * [Gradient Boosting Regressor](machine_learning/gradient_boosting_regressor.py) * [Gradient Descent](machine_learning/gradient_descent.py) * [K Means Clust](machine_learning/k_means_clust.py) * [K Nearest Neighbours](machine_learning/k_nearest_neighbours.py) @@ -490,8 +489,6 @@ * [Lstm Prediction](machine_learning/lstm/lstm_prediction.py) * [Multilayer Perceptron Classifier](machine_learning/multilayer_perceptron_classifier.py) * [Polymonial Regression](machine_learning/polymonial_regression.py) - * [Random Forest Classifier](machine_learning/random_forest_classifier.py) - * [Random Forest Regressor](machine_learning/random_forest_regressor.py) * [Scoring Functions](machine_learning/scoring_functions.py) * [Self Organizing Map](machine_learning/self_organizing_map.py) * [Sequential Minimum Optimization](machine_learning/sequential_minimum_optimization.py) From 4986ea36d6d6c5aa72b66f6d4a7df6317ea29acf Mon Sep 17 00:00:00 2001 From: Alexander Pantyukhin Date: Tue, 20 Dec 2022 15:12:32 +0400 Subject: [PATCH 03/15] Update word_break.py fix review notes. --- dynamic_programming/word_break.py | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/dynamic_programming/word_break.py b/dynamic_programming/word_break.py index a2fda48a3ec9..33d8c4b02b3a 100644 --- a/dynamic_programming/word_break.py +++ b/dynamic_programming/word_break.py @@ -23,33 +23,33 @@ from functools import lru_cache -def wordBreak(s: str, word_dict: list[str]) -> bool: +def word_break(s: str, word_dict: list[str]) -> bool: """ Return True if numbers have opposite signs False otherwise. - >>> wordBreak("applepenapple", ["apple","pen"]) + >>> word_break("applepenapple", ["apple","pen"]) True - >>> wordBreak("catsandog", ["cats","dog","sand","and","cat"]) + >>> word_break("catsandog", ["cats","dog","sand","and","cat"]) False - >>> wordBreak("cars", ["car","ca","rs"]) + >>> word_break("cars", ["car","ca","rs"]) True - >>> wordBreak("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaab", ["a","aa","aaa","aaaa","aaaaa","aaaaaa","aaaaaaa","aaaaaaaa","aaaaaaaaa","aaaaaaaaaa"]) + >>> word_break("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaab", ["a","aa","aaa","aaaa","aaaaa","aaaaaa","aaaaaaa","aaaaaaaa","aaaaaaaaa","aaaaaaaaaa"]) False - >>> wordBreak('abc', []) + >>> word_break('abc', []) False - >>> wordBreak(123, ['a']) + >>> word_break(123, ['a']) Traceback (most recent call last): ... ValueError: the s should be not empty string - >>> wordBreak('', ['a']) + >>> word_break('', ['a']) Traceback (most recent call last): ... ValueError: the s should be not empty string - >>> wordBreak('abc', [123]) + >>> word_break('abc', [123]) Traceback (most recent call last): ... ValueError: the word_dict should a list of non empty string - >>> wordBreak('abc', ['']) + >>> word_break('abc', ['']) Traceback (most recent call last): ... ValueError: the word_dict should a list of non empty string From ba0f0d6cf5168787196146d11a597724cedd3976 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 20 Dec 2022 11:13:32 +0000 Subject: [PATCH 04/15] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- dynamic_programming/word_break.py | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/dynamic_programming/word_break.py b/dynamic_programming/word_break.py index 33d8c4b02b3a..2330a2bd8e19 100644 --- a/dynamic_programming/word_break.py +++ b/dynamic_programming/word_break.py @@ -23,6 +23,7 @@ from functools import lru_cache + def word_break(s: str, word_dict: list[str]) -> bool: """ Return True if numbers have opposite signs False otherwise. @@ -57,15 +58,16 @@ def word_break(s: str, word_dict: list[str]) -> bool: # Validation if not isinstance(s, str) or len(s) == 0: - raise ValueError('the s should be not empty string') + raise ValueError("the s should be not empty string") if not isinstance(word_dict, list) or not all( - [isinstance(item, str) and len(item) > 0 for item in word_dict]): - raise ValueError('the word_dict should a list of non empty string') + [isinstance(item, str) and len(item) > 0 for item in word_dict] + ): + raise ValueError("the word_dict should a list of non empty string") # Build trie trie = {} - WORD_KEEPER = 'WORD_KEEPER' + WORD_KEEPER = "WORD_KEEPER" for word in word_dict: trie_node = trie for c in word: @@ -73,7 +75,7 @@ def word_break(s: str, word_dict: list[str]) -> bool: trie_node[c] = {} trie_node = trie_node[c] - + trie_node[WORD_KEEPER] = True len_s = len(s) @@ -90,7 +92,7 @@ def is_breakable(index: int) -> bool: if trie_node is None: return False - + if trie_node.get(WORD_KEEPER, False) and is_breakable(i + 1): return True From 00519c0aefe05916527b7c5c10520d5348f4e99a Mon Sep 17 00:00:00 2001 From: Alexander Pantyukhin Date: Tue, 20 Dec 2022 15:14:48 +0400 Subject: [PATCH 05/15] Update word_break.py fix review notes --- dynamic_programming/word_break.py | 30 ++++++++++++++---------------- 1 file changed, 14 insertions(+), 16 deletions(-) diff --git a/dynamic_programming/word_break.py b/dynamic_programming/word_break.py index 2330a2bd8e19..01ca2c983a7f 100644 --- a/dynamic_programming/word_break.py +++ b/dynamic_programming/word_break.py @@ -23,8 +23,7 @@ from functools import lru_cache - -def word_break(s: str, word_dict: list[str]) -> bool: +def word_break(string: str, word_dict: list[str]) -> bool: """ Return True if numbers have opposite signs False otherwise. @@ -41,11 +40,11 @@ def word_break(s: str, word_dict: list[str]) -> bool: >>> word_break(123, ['a']) Traceback (most recent call last): ... - ValueError: the s should be not empty string + ValueError: the string should be not empty string >>> word_break('', ['a']) Traceback (most recent call last): ... - ValueError: the s should be not empty string + ValueError: the string should be not empty string >>> word_break('abc', [123]) Traceback (most recent call last): ... @@ -57,17 +56,16 @@ def word_break(s: str, word_dict: list[str]) -> bool: """ # Validation - if not isinstance(s, str) or len(s) == 0: - raise ValueError("the s should be not empty string") + if not isinstance(string, str) or len(string) == 0: + raise ValueError('the string should be not empty string') if not isinstance(word_dict, list) or not all( - [isinstance(item, str) and len(item) > 0 for item in word_dict] - ): - raise ValueError("the word_dict should a list of non empty string") + [isinstance(item, str) and len(item) > 0 for item in word_dict]): + raise ValueError('the word_dict should a list of non empty string') # Build trie trie = {} - WORD_KEEPER = "WORD_KEEPER" + WORD_KEEPER = 'WORD_KEEPER' for word in word_dict: trie_node = trie for c in word: @@ -75,24 +73,24 @@ def word_break(s: str, word_dict: list[str]) -> bool: trie_node[c] = {} trie_node = trie_node[c] - + trie_node[WORD_KEEPER] = True - len_s = len(s) + len_string = len(string) # Dynamic programming method @lru_cache(maxsize=None) def is_breakable(index: int) -> bool: - if index == len_s: + if index == len_string: return True trie_node = trie - for i in range(index, len_s): - trie_node = trie_node.get(s[i], None) + for i in range(index, len_string): + trie_node = trie_node.get(string[i], None) if trie_node is None: return False - + if trie_node.get(WORD_KEEPER, False) and is_breakable(i + 1): return True From 53ab4d58959fd5f9222d204a4fddf07a6cc5f99e Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 20 Dec 2022 11:15:46 +0000 Subject: [PATCH 06/15] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- dynamic_programming/word_break.py | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/dynamic_programming/word_break.py b/dynamic_programming/word_break.py index 01ca2c983a7f..01e9e30d7f98 100644 --- a/dynamic_programming/word_break.py +++ b/dynamic_programming/word_break.py @@ -23,6 +23,7 @@ from functools import lru_cache + def word_break(string: str, word_dict: list[str]) -> bool: """ Return True if numbers have opposite signs False otherwise. @@ -57,15 +58,16 @@ def word_break(string: str, word_dict: list[str]) -> bool: # Validation if not isinstance(string, str) or len(string) == 0: - raise ValueError('the string should be not empty string') + raise ValueError("the string should be not empty string") if not isinstance(word_dict, list) or not all( - [isinstance(item, str) and len(item) > 0 for item in word_dict]): - raise ValueError('the word_dict should a list of non empty string') + [isinstance(item, str) and len(item) > 0 for item in word_dict] + ): + raise ValueError("the word_dict should a list of non empty string") # Build trie trie = {} - WORD_KEEPER = 'WORD_KEEPER' + WORD_KEEPER = "WORD_KEEPER" for word in word_dict: trie_node = trie for c in word: @@ -73,7 +75,7 @@ def word_break(string: str, word_dict: list[str]) -> bool: trie_node[c] = {} trie_node = trie_node[c] - + trie_node[WORD_KEEPER] = True len_string = len(string) @@ -90,7 +92,7 @@ def is_breakable(index: int) -> bool: if trie_node is None: return False - + if trie_node.get(WORD_KEEPER, False) and is_breakable(i + 1): return True From df0a9104aa730e7935c7cf8610515b0fb56ba4c9 Mon Sep 17 00:00:00 2001 From: alexpantyukhin Date: Tue, 20 Dec 2022 15:24:09 +0400 Subject: [PATCH 07/15] fix review notes --- dynamic_programming/word_break.py | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/dynamic_programming/word_break.py b/dynamic_programming/word_break.py index 01e9e30d7f98..d0606ef4ecf4 100644 --- a/dynamic_programming/word_break.py +++ b/dynamic_programming/word_break.py @@ -34,8 +34,6 @@ def word_break(string: str, word_dict: list[str]) -> bool: False >>> word_break("cars", ["car","ca","rs"]) True - >>> word_break("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaab", ["a","aa","aaa","aaaa","aaaaa","aaaaaa","aaaaaaa","aaaaaaaa","aaaaaaaaa","aaaaaaaaaa"]) - False >>> word_break('abc', []) False >>> word_break(123, ['a']) @@ -67,7 +65,7 @@ def word_break(string: str, word_dict: list[str]) -> bool: # Build trie trie = {} - WORD_KEEPER = "WORD_KEEPER" + word_keeper_key = "WORD_KEEPER" for word in word_dict: trie_node = trie for c in word: @@ -76,7 +74,7 @@ def word_break(string: str, word_dict: list[str]) -> bool: trie_node = trie_node[c] - trie_node[WORD_KEEPER] = True + trie_node[word_keeper_key] = True len_string = len(string) @@ -93,7 +91,7 @@ def is_breakable(index: int) -> bool: if trie_node is None: return False - if trie_node.get(WORD_KEEPER, False) and is_breakable(i + 1): + if trie_node.get(word_keeper_key, False) and is_breakable(i + 1): return True return False From 1e6a4a827113c47b4fd38586d232489e5f4fd06f Mon Sep 17 00:00:00 2001 From: alexpantyukhin Date: Tue, 20 Dec 2022 15:38:58 +0400 Subject: [PATCH 08/15] add trie type --- dynamic_programming/word_break.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dynamic_programming/word_break.py b/dynamic_programming/word_break.py index d0606ef4ecf4..7e1999b62e3d 100644 --- a/dynamic_programming/word_break.py +++ b/dynamic_programming/word_break.py @@ -64,7 +64,7 @@ def word_break(string: str, word_dict: list[str]) -> bool: raise ValueError("the word_dict should a list of non empty string") # Build trie - trie = {} + trie: Dict[str, Any] = {} word_keeper_key = "WORD_KEEPER" for word in word_dict: trie_node = trie From 37cb00428a39ea8d4ffac51e62f07a6750162dd7 Mon Sep 17 00:00:00 2001 From: Alexander Pantyukhin Date: Tue, 20 Dec 2022 15:49:26 +0400 Subject: [PATCH 09/15] Update word_break.py add typing Any to trie. --- dynamic_programming/word_break.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/dynamic_programming/word_break.py b/dynamic_programming/word_break.py index 7e1999b62e3d..81a623ef2b1b 100644 --- a/dynamic_programming/word_break.py +++ b/dynamic_programming/word_break.py @@ -22,6 +22,7 @@ """ from functools import lru_cache +from typing import Any def word_break(string: str, word_dict: list[str]) -> bool: @@ -64,8 +65,9 @@ def word_break(string: str, word_dict: list[str]) -> bool: raise ValueError("the word_dict should a list of non empty string") # Build trie - trie: Dict[str, Any] = {} + trie: dict[str, Any] = {} word_keeper_key = "WORD_KEEPER" + for word in word_dict: trie_node = trie for c in word: From dcbe9c310af0eb0741fe08abf615fd2532da29d4 Mon Sep 17 00:00:00 2001 From: Alexander Pantyukhin Date: Tue, 20 Dec 2022 23:52:42 +0400 Subject: [PATCH 10/15] Update dynamic_programming/word_break.py Co-authored-by: Caeden Perelli-Harris --- dynamic_programming/word_break.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dynamic_programming/word_break.py b/dynamic_programming/word_break.py index 81a623ef2b1b..98bd29f47d85 100644 --- a/dynamic_programming/word_break.py +++ b/dynamic_programming/word_break.py @@ -60,7 +60,7 @@ def word_break(string: str, word_dict: list[str]) -> bool: raise ValueError("the string should be not empty string") if not isinstance(word_dict, list) or not all( - [isinstance(item, str) and len(item) > 0 for item in word_dict] + isinstance(item, str) and len(item) > 0 for item in word_dict ): raise ValueError("the word_dict should a list of non empty string") From 7bef651d4bff86c4f4f1a6de94a8fec60d220327 Mon Sep 17 00:00:00 2001 From: Alexander Pantyukhin Date: Fri, 30 Dec 2022 08:10:20 +0400 Subject: [PATCH 11/15] Update dynamic_programming/word_break.py Co-authored-by: Christian Clauss --- dynamic_programming/word_break.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/dynamic_programming/word_break.py b/dynamic_programming/word_break.py index 98bd29f47d85..5917a4bd19ac 100644 --- a/dynamic_programming/word_break.py +++ b/dynamic_programming/word_break.py @@ -3,9 +3,8 @@ Date : December 12, 2022 Task: -Given a string s and a dictionary of strings wordDict, -return true if s can be segmented into a space-separated -sequence of one or more dictionary words. +Given a string and a list of words, return true if the string can be +segmented into a space-separated sequence of one or more words. Note that the same word in the dictionary may be reused multiple times in the segmentation. From 51baf03be0396a6750e644b0e12042122a067b90 Mon Sep 17 00:00:00 2001 From: Alexander Pantyukhin Date: Fri, 30 Dec 2022 08:11:15 +0400 Subject: [PATCH 12/15] Update dynamic_programming/word_break.py Co-authored-by: Christian Clauss --- dynamic_programming/word_break.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dynamic_programming/word_break.py b/dynamic_programming/word_break.py index 5917a4bd19ac..900bbb8c32ab 100644 --- a/dynamic_programming/word_break.py +++ b/dynamic_programming/word_break.py @@ -24,7 +24,7 @@ from typing import Any -def word_break(string: str, word_dict: list[str]) -> bool: +def word_break(string: str, words: list[str]) -> bool: """ Return True if numbers have opposite signs False otherwise. From ab642739671f963905c09fdcf92eb043048a7fe9 Mon Sep 17 00:00:00 2001 From: Alexander Pantyukhin Date: Fri, 30 Dec 2022 08:12:05 +0400 Subject: [PATCH 13/15] Update dynamic_programming/word_break.py Co-authored-by: Christian Clauss --- dynamic_programming/word_break.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dynamic_programming/word_break.py b/dynamic_programming/word_break.py index 900bbb8c32ab..2b97799ae975 100644 --- a/dynamic_programming/word_break.py +++ b/dynamic_programming/word_break.py @@ -51,7 +51,7 @@ def word_break(string: str, words: list[str]) -> bool: >>> word_break('abc', ['']) Traceback (most recent call last): ... - ValueError: the word_dict should a list of non empty string + ValueError: the words should be a list of non-empty strings """ # Validation From 3f7292a038354673ddcbd19653d93428e357cfa9 Mon Sep 17 00:00:00 2001 From: Alexander Pantyukhin Date: Fri, 30 Dec 2022 08:12:42 +0400 Subject: [PATCH 14/15] Update dynamic_programming/word_break.py Co-authored-by: Christian Clauss --- dynamic_programming/word_break.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dynamic_programming/word_break.py b/dynamic_programming/word_break.py index 2b97799ae975..1d23da3c3fbb 100644 --- a/dynamic_programming/word_break.py +++ b/dynamic_programming/word_break.py @@ -67,7 +67,7 @@ def word_break(string: str, words: list[str]) -> bool: trie: dict[str, Any] = {} word_keeper_key = "WORD_KEEPER" - for word in word_dict: + for word in words: trie_node = trie for c in word: if c not in trie_node: From 9368d252911ea11bf759845b916ba937bb619e53 Mon Sep 17 00:00:00 2001 From: alexpantyukhin Date: Fri, 30 Dec 2022 09:26:40 +0400 Subject: [PATCH 15/15] fix review notes --- dynamic_programming/word_break.py | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/dynamic_programming/word_break.py b/dynamic_programming/word_break.py index 1d23da3c3fbb..642ea0edf40d 100644 --- a/dynamic_programming/word_break.py +++ b/dynamic_programming/word_break.py @@ -6,11 +6,11 @@ Given a string and a list of words, return true if the string can be segmented into a space-separated sequence of one or more words. -Note that the same word in the dictionary may be reused +Note that the same word may be reused multiple times in the segmentation. Implementation notes: Trie + Dynamic programming up -> down. -The Trie keeps all wordDict words. It will be useful for scanning +The Trie will be used to store the words. It will be useful for scanning available words for the current position in the string. Leetcode: @@ -47,7 +47,7 @@ def word_break(string: str, words: list[str]) -> bool: >>> word_break('abc', [123]) Traceback (most recent call last): ... - ValueError: the word_dict should a list of non empty string + ValueError: the words should be a list of non-empty strings >>> word_break('abc', ['']) Traceback (most recent call last): ... @@ -58,10 +58,10 @@ def word_break(string: str, words: list[str]) -> bool: if not isinstance(string, str) or len(string) == 0: raise ValueError("the string should be not empty string") - if not isinstance(word_dict, list) or not all( - isinstance(item, str) and len(item) > 0 for item in word_dict + if not isinstance(words, list) or not all( + isinstance(item, str) and len(item) > 0 for item in words ): - raise ValueError("the word_dict should a list of non empty string") + raise ValueError("the words should be a list of non-empty strings") # Build trie trie: dict[str, Any] = {} @@ -82,6 +82,11 @@ def word_break(string: str, words: list[str]) -> bool: # Dynamic programming method @lru_cache(maxsize=None) def is_breakable(index: int) -> bool: + """ + >>> string = 'a' + >>> is_breakable(1) + True + """ if index == len_string: return True