From 7ed104634a93d889374deec6346e67b17e68551d Mon Sep 17 00:00:00 2001 From: dahhou ilyas Date: Sat, 7 Oct 2023 21:02:09 +0100 Subject: [PATCH 01/13] add new programme in dynamique programming wildcard_matching --- dynamic_programming/wildcard_matching.py | 99 ++++++++++++++++++++++++ 1 file changed, 99 insertions(+) create mode 100644 dynamic_programming/wildcard_matching.py diff --git a/dynamic_programming/wildcard_matching.py b/dynamic_programming/wildcard_matching.py new file mode 100644 index 000000000000..86e2425e0ba4 --- /dev/null +++ b/dynamic_programming/wildcard_matching.py @@ -0,0 +1,99 @@ +""" +Author : ilyas dahhou +Date : Oct 7, 2023 + +Task: +Given an input string (s) and a pattern (p), implement wildcard +pattern matching with support for '?' and '*' where: + +'?' matches any single character. +'*' matches any sequence of characters (including the empty sequence). +The matching should cover the entire input string (not partial). + +Implementation notes: +implementation Dynamic Programming up bottom approach. + +Runtime complexity:O(m * n) + +The implementation was tested on the +leetcode: https://leetcode.com/problems/wildcard-matching/ + + +wildcard matching +Dynamic Programming: top -> down. + +""" +import datetime + +import pytz + +tz_maroc = pytz.timezone("Africa/Casablanca") + +now_maroc = datetime.datetime.now(tz=tz_maroc) + + +def is_match(s: str, p: str) -> bool: + """ + >>> isMatch("aa", "a") + False + + >>> isMatch("abc", "abc") + True + + >>> isMatch("abc", "*c") + True + + >>> isMatch("abc", "a*") + True + + >>> isMatch("abc", "*a*") + True + + >>> isMatch("abc", "?b?") + True + + >>> isMatch("abc", "*?") + True + + >>> isMatch("abc", "a*d") + False + + >>> isMatch("abc", "a*c?") + False + + >>> isMatch("", "") + True + + >>> isMatch("a", "") + False + + >>> isMatch("", "*") + True + + >>> isMatch("abc", "*bc") + True + + >>> isMatch("abc", "a*bc") + True + + """ + m, n = len(s), len(p) + dp = [[False] * (n + 1) for _ in range(m + 1)] + + # Base case + dp[0][0] = True + + # Fill in the first row + for j in range(1, n + 1): + if p[j - 1] == "*": + dp[0][j] = dp[0][j - 1] + + # Fill in the rest of the DP table + for i in range(1, m + 1): + for j in range(1, n + 1): + if p[j - 1] == "?" or s[i - 1] == p[j - 1]: + dp[i][j] = dp[i - 1][j - 1] + elif p[j - 1] == "*": + dp[i][j] = dp[i - 1][j] or dp[i][j - 1] + + return dp[m][n] From 16803afd55521a379540c4e88ed198beee5dd9fc Mon Sep 17 00:00:00 2001 From: dahhou ilyas Date: Sat, 7 Oct 2023 21:07:48 +0100 Subject: [PATCH 02/13] add new programme in dynamique programming wildcard_matching --- dynamic_programming/wildcard_matching.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/dynamic_programming/wildcard_matching.py b/dynamic_programming/wildcard_matching.py index 86e2425e0ba4..14180a1108fd 100644 --- a/dynamic_programming/wildcard_matching.py +++ b/dynamic_programming/wildcard_matching.py @@ -32,7 +32,7 @@ now_maroc = datetime.datetime.now(tz=tz_maroc) -def is_match(s: str, p: str) -> bool: +def is_match(string: str, pattern: str) -> bool: """ >>> isMatch("aa", "a") False @@ -77,7 +77,7 @@ def is_match(s: str, p: str) -> bool: True """ - m, n = len(s), len(p) + m, n = len(string), len(pattern) dp = [[False] * (n + 1) for _ in range(m + 1)] # Base case @@ -85,15 +85,15 @@ def is_match(s: str, p: str) -> bool: # Fill in the first row for j in range(1, n + 1): - if p[j - 1] == "*": + if pattern[j - 1] == "*": dp[0][j] = dp[0][j - 1] # Fill in the rest of the DP table for i in range(1, m + 1): for j in range(1, n + 1): - if p[j - 1] == "?" or s[i - 1] == p[j - 1]: + if pattern[j - 1] == "?" or string[i - 1] == pattern[j - 1]: dp[i][j] = dp[i - 1][j - 1] - elif p[j - 1] == "*": + elif pattern[j - 1] == "*": dp[i][j] = dp[i - 1][j] or dp[i][j - 1] return dp[m][n] From 9c0e073963989d91effe491970ec7ce665c3719e Mon Sep 17 00:00:00 2001 From: dahhou ilyas Date: Sat, 7 Oct 2023 21:15:48 +0100 Subject: [PATCH 03/13] fix bug --- dynamic_programming/wildcard_matching.py | 28 ++++++++++++------------ 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/dynamic_programming/wildcard_matching.py b/dynamic_programming/wildcard_matching.py index 14180a1108fd..933ec9a5a5ee 100644 --- a/dynamic_programming/wildcard_matching.py +++ b/dynamic_programming/wildcard_matching.py @@ -34,46 +34,46 @@ def is_match(string: str, pattern: str) -> bool: """ - >>> isMatch("aa", "a") + >>> is_match("aa", "a") False - >>> isMatch("abc", "abc") + >>> is_match("abc", "abc") True - >>> isMatch("abc", "*c") + >>> is_match("abc", "*c") True - >>> isMatch("abc", "a*") + >>> is_match("abc", "a*") True - >>> isMatch("abc", "*a*") + >>> is_match("abc", "*a*") True - >>> isMatch("abc", "?b?") + >>> is_match("abc", "?b?") True - >>> isMatch("abc", "*?") + >>> is_match("abc", "*?") True - >>> isMatch("abc", "a*d") + >>> is_match("abc", "a*d") False - >>> isMatch("abc", "a*c?") + >>> is_match("abc", "a*c?") False - >>> isMatch("", "") + >>> is_match("", "") True - >>> isMatch("a", "") + >>> is_match("a", "") False - >>> isMatch("", "*") + >>> is_match("", "*") True - >>> isMatch("abc", "*bc") + >>> is_match("abc", "*bc") True - >>> isMatch("abc", "a*bc") + >>> is_match("abc", "a*bc") True """ From fe838c6c7ff0e274d95c656d50bfa32212f60965 Mon Sep 17 00:00:00 2001 From: dahhou ilyas Date: Sat, 7 Oct 2023 21:22:18 +0100 Subject: [PATCH 04/13] fix --- requirements.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/requirements.txt b/requirements.txt index 25dba6f5a250..85bec10a9796 100644 --- a/requirements.txt +++ b/requirements.txt @@ -20,5 +20,6 @@ sympy tensorflow ; python_version < '3.12' texttable tweepy +types-pytz xgboost yulewalker From 797e455cbbebd7f2f4cc2995374882fd4b19990b Mon Sep 17 00:00:00 2001 From: dahhou ilyas Date: Sat, 7 Oct 2023 21:28:06 +0100 Subject: [PATCH 05/13] fix --- dynamic_programming/wildcard_matching.py | 1 - 1 file changed, 1 deletion(-) diff --git a/dynamic_programming/wildcard_matching.py b/dynamic_programming/wildcard_matching.py index 933ec9a5a5ee..915711876030 100644 --- a/dynamic_programming/wildcard_matching.py +++ b/dynamic_programming/wildcard_matching.py @@ -75,7 +75,6 @@ def is_match(string: str, pattern: str) -> bool: >>> is_match("abc", "a*bc") True - """ m, n = len(string), len(pattern) dp = [[False] * (n + 1) for _ in range(m + 1)] From d41a90677e421005536c1533ff13594e08269bbd Mon Sep 17 00:00:00 2001 From: dahhou ilyas Date: Sat, 7 Oct 2023 21:31:17 +0100 Subject: [PATCH 06/13] fix --- requirements.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/requirements.txt b/requirements.txt index 85bec10a9796..8dfda6f8807a 100644 --- a/requirements.txt +++ b/requirements.txt @@ -4,6 +4,7 @@ imageio keras lxml matplotlib +mypy numpy opencv-python pandas From cff48ee4742b9547dccdeb212242c01b05009313 Mon Sep 17 00:00:00 2001 From: dahhou ilyas Date: Sat, 7 Oct 2023 21:43:40 +0100 Subject: [PATCH 07/13] fix --- dynamic_programming/wildcard_matching.py | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/dynamic_programming/wildcard_matching.py b/dynamic_programming/wildcard_matching.py index 915711876030..5977afbf3bd2 100644 --- a/dynamic_programming/wildcard_matching.py +++ b/dynamic_programming/wildcard_matching.py @@ -25,9 +25,22 @@ """ import datetime -import pytz -tz_maroc = pytz.timezone("Africa/Casablanca") +class CustomTimeZone(datetime.tzinfo): + def utcoffset(self, dt): + print(dt) + return datetime.timedelta(hours=1) + + def dst(self, dt): + print(dt) + return datetime.timedelta(0) + + def tzname(self, dt): + print(dt) + return "Custom Time Zone" + + +tz_maroc = CustomTimeZone() now_maroc = datetime.datetime.now(tz=tz_maroc) From 0bd8348fd0b9ef47a6f7d02d599183cb1366d16f Mon Sep 17 00:00:00 2001 From: dahhou ilyas Date: Sat, 7 Oct 2023 21:48:04 +0100 Subject: [PATCH 08/13] fix --- dynamic_programming/wildcard_matching.py | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/dynamic_programming/wildcard_matching.py b/dynamic_programming/wildcard_matching.py index 5977afbf3bd2..43bd272cbf60 100644 --- a/dynamic_programming/wildcard_matching.py +++ b/dynamic_programming/wildcard_matching.py @@ -76,18 +76,6 @@ def is_match(string: str, pattern: str) -> bool: >>> is_match("", "") True - - >>> is_match("a", "") - False - - >>> is_match("", "*") - True - - >>> is_match("abc", "*bc") - True - - >>> is_match("abc", "a*bc") - True """ m, n = len(string), len(pattern) dp = [[False] * (n + 1) for _ in range(m + 1)] From 629bac908ab477cf46539b168512d54af0b0e6c0 Mon Sep 17 00:00:00 2001 From: dahhou ilyas Date: Sat, 7 Oct 2023 21:53:40 +0100 Subject: [PATCH 09/13] fix error recrusion --- dynamic_programming/wildcard_matching.py | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/dynamic_programming/wildcard_matching.py b/dynamic_programming/wildcard_matching.py index 43bd272cbf60..be6686a2f664 100644 --- a/dynamic_programming/wildcard_matching.py +++ b/dynamic_programming/wildcard_matching.py @@ -29,7 +29,7 @@ class CustomTimeZone(datetime.tzinfo): def utcoffset(self, dt): print(dt) - return datetime.timedelta(hours=1) + return datetime.timedelta(hours=0) def dst(self, dt): print(dt) @@ -40,6 +40,15 @@ def tzname(self, dt): return "Custom Time Zone" +def get_current_time_in_casablanca(): + tz_maroc = CustomTimeZone() + now_maroc = datetime.datetime.now(tz=tz_maroc) + return now_maroc + + +current_time_in_casablanca = get_current_time_in_casablanca() + + tz_maroc = CustomTimeZone() now_maroc = datetime.datetime.now(tz=tz_maroc) From d90ff92ea396d967cdd314e92dd9f3ae2ace7f03 Mon Sep 17 00:00:00 2001 From: dahhou ilyas Date: Sat, 7 Oct 2023 21:59:00 +0100 Subject: [PATCH 10/13] fix error recrusion --- requirements.txt | 2 -- 1 file changed, 2 deletions(-) diff --git a/requirements.txt b/requirements.txt index 8dfda6f8807a..25dba6f5a250 100644 --- a/requirements.txt +++ b/requirements.txt @@ -4,7 +4,6 @@ imageio keras lxml matplotlib -mypy numpy opencv-python pandas @@ -21,6 +20,5 @@ sympy tensorflow ; python_version < '3.12' texttable tweepy -types-pytz xgboost yulewalker From 3a0ea7d9d41bebb68bf26c18d28a94f7fc6d179b Mon Sep 17 00:00:00 2001 From: dahhou ilyas Date: Sat, 7 Oct 2023 22:16:47 +0100 Subject: [PATCH 11/13] bug fix --- dynamic_programming/wildcard_matching.py | 30 +++--------------------- 1 file changed, 3 insertions(+), 27 deletions(-) diff --git a/dynamic_programming/wildcard_matching.py b/dynamic_programming/wildcard_matching.py index be6686a2f664..c8883110bd1a 100644 --- a/dynamic_programming/wildcard_matching.py +++ b/dynamic_programming/wildcard_matching.py @@ -23,35 +23,11 @@ Dynamic Programming: top -> down. """ -import datetime +from datetime import datetime, timedelta, timezone +country_timezone = timezone(timedelta(hours=1)) -class CustomTimeZone(datetime.tzinfo): - def utcoffset(self, dt): - print(dt) - return datetime.timedelta(hours=0) - - def dst(self, dt): - print(dt) - return datetime.timedelta(0) - - def tzname(self, dt): - print(dt) - return "Custom Time Zone" - - -def get_current_time_in_casablanca(): - tz_maroc = CustomTimeZone() - now_maroc = datetime.datetime.now(tz=tz_maroc) - return now_maroc - - -current_time_in_casablanca = get_current_time_in_casablanca() - - -tz_maroc = CustomTimeZone() - -now_maroc = datetime.datetime.now(tz=tz_maroc) +current_time_in_country = datetime.now(tz=country_timezone) def is_match(string: str, pattern: str) -> bool: From aeccbaf39684a088bda53a71cbef49d8b07f3d1d Mon Sep 17 00:00:00 2001 From: dahhou ilyas Date: Sun, 8 Oct 2023 15:03:56 +0100 Subject: [PATCH 12/13] add doctest --- dynamic_programming/wildcard_matching.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/dynamic_programming/wildcard_matching.py b/dynamic_programming/wildcard_matching.py index c8883110bd1a..204410987386 100644 --- a/dynamic_programming/wildcard_matching.py +++ b/dynamic_programming/wildcard_matching.py @@ -82,3 +82,9 @@ def is_match(string: str, pattern: str) -> bool: dp[i][j] = dp[i - 1][j] or dp[i][j - 1] return dp[m][n] + + +if __name__ == "__main__": + import doctest + + doctest.testmod() From 6fac36f200a69595fde9fb8eac69701c0ac18d5d Mon Sep 17 00:00:00 2001 From: Christian Clauss Date: Sun, 29 Oct 2023 18:07:45 +0100 Subject: [PATCH 13/13] The power of enumerate() --- dynamic_programming/wildcard_matching.py | 33 +++++++----------------- 1 file changed, 9 insertions(+), 24 deletions(-) diff --git a/dynamic_programming/wildcard_matching.py b/dynamic_programming/wildcard_matching.py index 204410987386..ed189c1c8d8a 100644 --- a/dynamic_programming/wildcard_matching.py +++ b/dynamic_programming/wildcard_matching.py @@ -3,31 +3,17 @@ Date : Oct 7, 2023 Task: -Given an input string (s) and a pattern (p), implement wildcard -pattern matching with support for '?' and '*' where: - +Given an input string and a pattern, implement wildcard pattern matching with support +for '?' and '*' where: '?' matches any single character. '*' matches any sequence of characters (including the empty sequence). The matching should cover the entire input string (not partial). -Implementation notes: -implementation Dynamic Programming up bottom approach. - Runtime complexity:O(m * n) The implementation was tested on the leetcode: https://leetcode.com/problems/wildcard-matching/ - - -wildcard matching -Dynamic Programming: top -> down. - """ -from datetime import datetime, timedelta, timezone - -country_timezone = timezone(timedelta(hours=1)) - -current_time_in_country = datetime.now(tz=country_timezone) def is_match(string: str, pattern: str) -> bool: @@ -62,26 +48,25 @@ def is_match(string: str, pattern: str) -> bool: >>> is_match("", "") True """ - m, n = len(string), len(pattern) - dp = [[False] * (n + 1) for _ in range(m + 1)] + dp = [[False] * (len(pattern) + 1) for _ in range(len(string) + 1)] # Base case dp[0][0] = True # Fill in the first row - for j in range(1, n + 1): - if pattern[j - 1] == "*": + for j, char in enumerate(pattern, 1): + if char == "*": dp[0][j] = dp[0][j - 1] # Fill in the rest of the DP table - for i in range(1, m + 1): - for j in range(1, n + 1): - if pattern[j - 1] == "?" or string[i - 1] == pattern[j - 1]: + for i, s_char in enumerate(string, 1): + for j, p_char in enumerate(pattern, 1): + if p_char in (s_char, "?"): dp[i][j] = dp[i - 1][j - 1] elif pattern[j - 1] == "*": dp[i][j] = dp[i - 1][j] or dp[i][j - 1] - return dp[m][n] + return dp[len(string)][len(pattern)] if __name__ == "__main__":