From b42f504849655307e403088b6479c6547a7cdffb Mon Sep 17 00:00:00 2001 From: CaedenPH Date: Fri, 19 May 2023 16:19:44 +0100 Subject: [PATCH 1/6] refactor: Merge and add benchmarks to palindrome --- strings/is_palindrome.py | 41 ---------------------------------------- strings/palindrome.py | 35 ++++++++++++++++++++++++++++++++++ 2 files changed, 35 insertions(+), 41 deletions(-) delete mode 100644 strings/is_palindrome.py diff --git a/strings/is_palindrome.py b/strings/is_palindrome.py deleted file mode 100644 index 406aa2e8d3c3..000000000000 --- a/strings/is_palindrome.py +++ /dev/null @@ -1,41 +0,0 @@ -def is_palindrome(s: str) -> bool: - """ - Determine if the string s is a palindrome. - - >>> is_palindrome("A man, A plan, A canal -- Panama!") - True - >>> is_palindrome("Hello") - False - >>> is_palindrome("Able was I ere I saw Elba") - True - >>> is_palindrome("racecar") - True - >>> is_palindrome("Mr. Owl ate my metal worm?") - True - """ - # Since punctuation, capitalization, and spaces are often ignored while checking - # palindromes, we first remove them from our string. - s = "".join(character for character in s.lower() if character.isalnum()) - # return s == s[::-1] the slicing method - # uses extra spaces we can - # better with iteration method. - - end = len(s) // 2 - n = len(s) - - # We need to traverse till half of the length of string - # as we can get access of the i'th last element from - # i'th index. - # eg: [0,1,2,3,4,5] => 4th index can be accessed - # with the help of 1st index (i==n-i-1) - # where n is length of string - - return all(s[i] == s[n - i - 1] for i in range(end)) - - -if __name__ == "__main__": - s = input("Please enter a string to see if it is a palindrome: ") - if is_palindrome(s): - print(f"'{s}' is a palindrome.") - else: - print(f"'{s}' is not a palindrome.") diff --git a/strings/palindrome.py b/strings/palindrome.py index dd1fe316f479..d289d5468129 100644 --- a/strings/palindrome.py +++ b/strings/palindrome.py @@ -1,5 +1,8 @@ # Algorithms to determine if a string is palindrome +from timeit import timeit + + test_data = { "MALAYALAM": True, "String": False, @@ -33,6 +36,25 @@ def is_palindrome(s: str) -> bool: return True +def is_palindrome_traversal(s: str) -> bool: + """ + Return True if s is a palindrome otherwise return False. + + >>> all(is_palindrome_traversal(key) is value for key, value in test_data.items()) + True + """ + end = len(s) // 2 + n = len(s) + + # We need to traverse till half of the length of string + # as we can get access of the i'th last element from + # i'th index. + # eg: [0,1,2,3,4,5] => 4th index can be accessed + # with the help of 1st index (i==n-i-1) + # where n is length of string + return all(s[i] == s[n - i - 1] for i in range(end)) + + def is_palindrome_recursive(s: str) -> bool: """ Return True if s is a palindrome otherwise return False. @@ -58,9 +80,22 @@ def is_palindrome_slice(s: str) -> bool: return s == s[::-1] +def benchmark_function(name: str) -> None: + setup = f"from __main__ import test_data, {name}" + number = 100000 + res = timeit(f"all({name}(key) is value for key, value in test_data.items())", setup=setup, number=number) + print(f"{name:<35} finished {number} runs in {res:.5f} seconds") + + if __name__ == "__main__": for key, value in test_data.items(): assert is_palindrome(key) is is_palindrome_recursive(key) assert is_palindrome(key) is is_palindrome_slice(key) print(f"{key:21} {value}") print("a man a plan a canal panama") + + benchmark_function("is_palindrome") # finished 100000 runs in 0.33785 seconds + benchmark_function("is_palindrome_traversal") # finished 100000 runs in 0.70002 seconds + benchmark_function("is_palindrome_recursive") # finished 100000 runs in 0.48514 seconds + benchmark_function("is_palindrome_slice") # finished 100000 runs in 0.18703 seconds + From b1f49ca525a2bfe832f24a6fd161c4864c92d3c7 Mon Sep 17 00:00:00 2001 From: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> Date: Fri, 19 May 2023 15:20:35 +0000 Subject: [PATCH 2/6] updating DIRECTORY.md --- DIRECTORY.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DIRECTORY.md b/DIRECTORY.md index 82791cde183d..4c39ab67b613 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -577,6 +577,7 @@ * [Hexagonal Number](maths/hexagonal_number.py) * [Integration By Simpson Approx](maths/integration_by_simpson_approx.py) * [Is Ip V4 Address Valid](maths/is_ip_v4_address_valid.py) + * [Is Palindrome](maths/is_palindrome.py) * [Is Square Free](maths/is_square_free.py) * [Jaccard Similarity](maths/jaccard_similarity.py) * [Juggler Sequence](maths/juggler_sequence.py) @@ -1154,7 +1155,6 @@ * [Indian Phone Validator](strings/indian_phone_validator.py) * [Is Contains Unique Chars](strings/is_contains_unique_chars.py) * [Is Isogram](strings/is_isogram.py) - * [Is Palindrome](strings/is_palindrome.py) * [Is Pangram](strings/is_pangram.py) * [Is Spain National Id](strings/is_spain_national_id.py) * [Is Srilankan Phone Number](strings/is_srilankan_phone_number.py) From 316fd04769dd21d090fea1fca96ea84cca105bd5 Mon Sep 17 00:00:00 2001 From: CaedenPH Date: Fri, 19 May 2023 16:22:16 +0100 Subject: [PATCH 3/6] chore: Fix failing tests --- strings/palindrome.py | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/strings/palindrome.py b/strings/palindrome.py index d289d5468129..71c976ae81e0 100644 --- a/strings/palindrome.py +++ b/strings/palindrome.py @@ -2,7 +2,6 @@ from timeit import timeit - test_data = { "MALAYALAM": True, "String": False, @@ -83,7 +82,11 @@ def is_palindrome_slice(s: str) -> bool: def benchmark_function(name: str) -> None: setup = f"from __main__ import test_data, {name}" number = 100000 - res = timeit(f"all({name}(key) is value for key, value in test_data.items())", setup=setup, number=number) + res = timeit( + f"all({name}(key) is value for key, value in test_data.items())", + setup=setup, + number=number, + ) print(f"{name:<35} finished {number} runs in {res:.5f} seconds") @@ -95,7 +98,10 @@ def benchmark_function(name: str) -> None: print("a man a plan a canal panama") benchmark_function("is_palindrome") # finished 100000 runs in 0.33785 seconds - benchmark_function("is_palindrome_traversal") # finished 100000 runs in 0.70002 seconds - benchmark_function("is_palindrome_recursive") # finished 100000 runs in 0.48514 seconds + benchmark_function( + "is_palindrome_traversal" + ) # finished 100000 runs in 0.70002 seconds + benchmark_function( + "is_palindrome_recursive" + ) # finished 100000 runs in 0.48514 seconds benchmark_function("is_palindrome_slice") # finished 100000 runs in 0.18703 seconds - From da3003ab043dee7dccd3a7a554ff22492cd2ac6a Mon Sep 17 00:00:00 2001 From: Caeden Perelli-Harris Date: Thu, 25 May 2023 11:35:16 +0100 Subject: [PATCH 4/6] Update strings/palindrome.py Co-authored-by: Christian Clauss --- strings/palindrome.py | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/strings/palindrome.py b/strings/palindrome.py index 71c976ae81e0..8fba9d9ecee8 100644 --- a/strings/palindrome.py +++ b/strings/palindrome.py @@ -80,13 +80,9 @@ def is_palindrome_slice(s: str) -> bool: def benchmark_function(name: str) -> None: + stmt = f"all({name}(key) is value for key, value in test_data.items())" setup = f"from __main__ import test_data, {name}" - number = 100000 - res = timeit( - f"all({name}(key) is value for key, value in test_data.items())", - setup=setup, - number=number, - ) + res = timeit(stmt=stmt, setup=setup, number=100000) print(f"{name:<35} finished {number} runs in {res:.5f} seconds") From 35ea03e508189211b5cce897143fc97d66d8ea90 Mon Sep 17 00:00:00 2001 From: Christian Clauss Date: Thu, 25 May 2023 12:54:21 +0200 Subject: [PATCH 5/6] Update palindrome.py --- strings/palindrome.py | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/strings/palindrome.py b/strings/palindrome.py index 8fba9d9ecee8..2b94f0b795a6 100644 --- a/strings/palindrome.py +++ b/strings/palindrome.py @@ -61,7 +61,7 @@ def is_palindrome_recursive(s: str) -> bool: >>> all(is_palindrome_recursive(key) is value for key, value in test_data.items()) True """ - if len(s) <= 1: + if len(s) <= 2: return True if s[0] == s[len(s) - 1]: return is_palindrome_recursive(s[1:-1]) @@ -82,8 +82,9 @@ def is_palindrome_slice(s: str) -> bool: def benchmark_function(name: str) -> None: stmt = f"all({name}(key) is value for key, value in test_data.items())" setup = f"from __main__ import test_data, {name}" - res = timeit(stmt=stmt, setup=setup, number=100000) - print(f"{name:<35} finished {number} runs in {res:.5f} seconds") + number = 500000 + result = timeit(stmt=stmt, setup=setup, number=number) + print(f"{name:<35} finished {number:,} runs in {result:.5f} seconds") if __name__ == "__main__": @@ -93,11 +94,11 @@ def benchmark_function(name: str) -> None: print(f"{key:21} {value}") print("a man a plan a canal panama") - benchmark_function("is_palindrome") # finished 100000 runs in 0.33785 seconds - benchmark_function( - "is_palindrome_traversal" - ) # finished 100000 runs in 0.70002 seconds - benchmark_function( - "is_palindrome_recursive" - ) # finished 100000 runs in 0.48514 seconds - benchmark_function("is_palindrome_slice") # finished 100000 runs in 0.18703 seconds + # finished 500,000 runs in 0.46793 seconds + benchmark_function("is_palindrome_slice") + # finished 500,000 runs in 0.85234 seconds + benchmark_function("is_palindrome") + # finished 500,000 runs in 1.32028 seconds + benchmark_function("is_palindrome_recursive") + #finished 500,000 runs in 2.08679 seconds + benchmark_function("is_palindrome_traversal") From c28fe2e546e4f9d7f6fb5dac3642b514bb803867 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Thu, 25 May 2023 10:55:48 +0000 Subject: [PATCH 6/6] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- strings/palindrome.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/strings/palindrome.py b/strings/palindrome.py index 2b94f0b795a6..bfdb3ddcf396 100644 --- a/strings/palindrome.py +++ b/strings/palindrome.py @@ -100,5 +100,5 @@ def benchmark_function(name: str) -> None: benchmark_function("is_palindrome") # finished 500,000 runs in 1.32028 seconds benchmark_function("is_palindrome_recursive") - #finished 500,000 runs in 2.08679 seconds + # finished 500,000 runs in 2.08679 seconds benchmark_function("is_palindrome_traversal")