From f7dd18b20a10b3d5e0564191376d6b9ad316abca Mon Sep 17 00:00:00 2001 From: Gautam Manek Date: Sun, 6 Mar 2022 19:58:40 +0100 Subject: [PATCH 1/2] feat: added tests for KMP algorithm --- strings/knuth_morris_pratt.py | 53 ++++++++++++++++++----------------- 1 file changed, 28 insertions(+), 25 deletions(-) diff --git a/strings/knuth_morris_pratt.py b/strings/knuth_morris_pratt.py index a488c171a93b..805b45eaf30a 100644 --- a/strings/knuth_morris_pratt.py +++ b/strings/knuth_morris_pratt.py @@ -1,5 +1,7 @@ from __future__ import annotations +import doctest + def kmp(pattern: str, text: str) -> bool: """ @@ -13,7 +15,25 @@ def kmp(pattern: str, text: str) -> bool: 2) Step through the text one character at a time and compare it to a character in the pattern updating our location within the pattern if necessary - + >>> pattern = "abc1abc12" + >>> text1 = "alskfjaldsabc1abc1abc12k23adsfabcabc" + >>> print(kmp(pattern, text1)) + True + >>> text2 = "alskfjaldsk23adsfabcabc" + >>> print(kmp(pattern, text2)) + False + >>> pattern = "ABABX" + >>> text = "ABABZABABYABABX" + >>> print(kmp(pattern, text)) + True + >>> pattern = "AAAB" + >>> text = "ABAAAAAB" + >>> print(kmp(pattern, text)) + True + >>> pattern = "abcdabcy" + >>> text = "abcxabcdabxabcdabcdabcy" + >>> print(kmp(pattern, text)) + True """ # 1) Construct the failure array @@ -41,6 +61,12 @@ def get_failure_array(pattern: str) -> list[int]: Calculates the new index we should go to if we fail a comparison :param pattern: :return: + >>> pattern = "aabaabaaa" + >>> get_failure_array(pattern) + [0, 1, 0, 1, 2, 3, 4, 5, 2] + >>> pattern = "abcdbeabc" + >>> get_failure_array(pattern) + [0, 0, 0, 0, 0, 0, 1, 2, 3] """ failure = [0] i = 0 @@ -57,27 +83,4 @@ def get_failure_array(pattern: str) -> list[int]: if __name__ == "__main__": - # Test 1) - pattern = "abc1abc12" - text1 = "alskfjaldsabc1abc1abc12k23adsfabcabc" - text2 = "alskfjaldsk23adsfabcabc" - assert kmp(pattern, text1) and not kmp(pattern, text2) - - # Test 2) - pattern = "ABABX" - text = "ABABZABABYABABX" - assert kmp(pattern, text) - - # Test 3) - pattern = "AAAB" - text = "ABAAAAAB" - assert kmp(pattern, text) - - # Test 4) - pattern = "abcdabcy" - text = "abcxabcdabxabcdabcdabcy" - assert kmp(pattern, text) - - # Test 5) - pattern = "aabaabaaa" - assert get_failure_array(pattern) == [0, 1, 0, 1, 2, 3, 4, 5, 2] + doctest.testmod() From 7a568a0c77faa0a4a4a44ec0a7fd498e4f917728 Mon Sep 17 00:00:00 2001 From: Gautam Manek Date: Sun, 6 Mar 2022 20:43:09 +0100 Subject: [PATCH 2/2] feat: add tests for min_cost_string_conversion --- strings/min_cost.txt | 12 +++++ strings/min_cost_string_conversion.py | 64 +++++++++++++++++++++++++-- 2 files changed, 73 insertions(+), 3 deletions(-) create mode 100644 strings/min_cost.txt diff --git a/strings/min_cost.txt b/strings/min_cost.txt new file mode 100644 index 000000000000..73ee5a828555 --- /dev/null +++ b/strings/min_cost.txt @@ -0,0 +1,12 @@ +Insert A APython +Insert l AlPython +Insert g AlgPython +Insert o AlgoPython +Replace P with r Algorython +Replace y with i Algorithon +Copy t Algorithon +Copy h Algorithon +Replace o with m Algorithmn +Replace n with s Algorithms + +Minimum cost: 10 \ No newline at end of file diff --git a/strings/min_cost_string_conversion.py b/strings/min_cost_string_conversion.py index 147bc6fc740a..85583465f34f 100644 --- a/strings/min_cost_string_conversion.py +++ b/strings/min_cost_string_conversion.py @@ -9,6 +9,9 @@ """ +import doctest + + def compute_transform_tables( source_string: str, destination_string: str, @@ -17,6 +20,18 @@ def compute_transform_tables( delete_cost: int, insert_cost: int, ) -> tuple[list[list[int]], list[list[str]]]: + """ + >>> compute_transform_tables("", "test", 1, 1, 1, 1) + ([[0, 1, 2, 3, 4]], [['0', 'It', 'Ie', 'Is', 'It']]) + >>> compute_transform_tables("t", "test", 1, 1, 1, 1) + ([[0, 1, 2, 3, 4], [1, 1, 2, 3, 4]], [['0', 'It', 'Ie', 'Is', 'It'], ['Dt', 'Ct', 'Rte', 'Rts', 'Ct']]) + >>> compute_transform_tables("te", "test", 1, 1, 1, 1) + ([[0, 1, 2, 3, 4], [1, 1, 2, 3, 4], [2, 2, 2, 3, 4]], [['0', 'It', 'Ie', 'Is', 'It'], ['Dt', 'Ct', 'Rte', 'Rts', 'Ct'], ['De', 'Ret', 'Ce', 'Res', 'Ret']]) + >>> compute_transform_tables("pl", "tst", 1, 1, 1, 1) + ([[0, 1, 2, 3], [1, 1, 2, 3], [2, 2, 2, 3]], [['0', 'It', 'Is', 'It'], ['Dp', 'Rpt', 'Rps', 'Rpt'], ['Dl', 'Rlt', 'Rls', 'Rlt']]) + >>> compute_transform_tables("test", "", 1, 1, 1, 1) + ([[0], [1], [2], [3], [4]], [['0'], ['Dt'], ['De'], ['Ds'], ['Dt']]) + """ source_seq = list(source_string) destination_seq = list(destination_string) len_source_seq = len(source_seq) @@ -58,6 +73,17 @@ def compute_transform_tables( def assemble_transformation(ops: list[list[str]], i: int, j: int) -> list[str]: + """ + >>> costs, ops = compute_transform_tables("te", "test", 1, 1, 1, 1) + >>> assemble_transformation(ops, 0, 0) + [] + >>> assemble_transformation(ops, 1, 1) + ['Ct'] + >>> assemble_transformation(ops, 2, 1) + ['Dt', 'Ret'] + >>> assemble_transformation(ops, 1, 2) + ['It', 'Rte'] + """ if i == 0 and j == 0: return [] else: @@ -75,8 +101,37 @@ def assemble_transformation(ops: list[list[str]], i: int, j: int) -> list[str]: return seq -if __name__ == "__main__": - _, operations = compute_transform_tables("Python", "Algorithms", -1, 1, 2, 2) +def print_operations( + source_string: str, + destination_string: str, + copy_cost: int, + replace_cost: int, + delete_cost: int, + insert_cost: int, +): + """ + >>> print_operations("Python", "Algorithms", 1, 1, 1, 1) + Python + APython + AlPython + AlgPython + AlgoPython + Algorython + Algorithon + Algorithon + Algorithon + Algorithmn + Algorithms + Cost: 10 + """ + _, operations = compute_transform_tables( + source_string, + destination_string, + copy_cost, + replace_cost, + delete_cost, + insert_cost, + ) m = len(operations) n = len(operations[0]) @@ -85,7 +140,6 @@ def assemble_transformation(ops: list[list[str]], i: int, j: int) -> list[str]: string = list("Python") i = 0 cost = 0 - with open("min_cost.txt", "w") as file: for op in sequence: print("".join(string)) @@ -127,3 +181,7 @@ def assemble_transformation(ops: list[list[str]], i: int, j: int) -> list[str]: print("Cost: ", cost) file.write("\r\nMinimum cost: " + str(cost)) + + +if __name__ == "__main__": + doctest.testmod()