From cf915e704285b1b40b6d0f180d60791204486fd3 Mon Sep 17 00:00:00 2001 From: Alexander Pantyukhin Date: Sun, 30 Oct 2022 17:00:16 +0400 Subject: [PATCH] add Levinstein distance with Dynamic Programming: up -> down approach (#7171) * add Levinstein distance with Dynamic Programming: up -> down approach * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * add type hint * fix flake8 * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update dynamic_programming/min_distance_up_bottom.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update min_distance_up_bottom.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Christian Clauss --- dynamic_programming/min_distance_up_bottom.py | 55 +++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 dynamic_programming/min_distance_up_bottom.py diff --git a/dynamic_programming/min_distance_up_bottom.py b/dynamic_programming/min_distance_up_bottom.py new file mode 100644 index 000000000..49c361f24 --- /dev/null +++ b/dynamic_programming/min_distance_up_bottom.py @@ -0,0 +1,55 @@ +""" +Author : Alexander Pantyukhin +Date : October 14, 2022 +This is implementation Dynamic Programming up bottom approach +to find edit distance. +The aim is to demonstate up bottom approach for solving the task. +The implementation was tested on the +leetcode: https://leetcode.com/problems/edit-distance/ +""" + +""" +Levinstein distance +Dynamic Programming: up -> down. +""" + + +def min_distance_up_bottom(word1: str, word2: str) -> int: + """ + >>> min_distance_up_bottom("intention", "execution") + 5 + >>> min_distance_up_bottom("intention", "") + 9 + >>> min_distance_up_bottom("", "") + 0 + >>> min_distance_up_bottom("zooicoarchaeologist", "zoologist") + 10 + """ + + from functools import lru_cache + + len_word1 = len(word1) + len_word2 = len(word2) + + @lru_cache(maxsize=None) + def min_distance(index1: int, index2: int) -> int: + # if first word index is overflow - delete all from the second word + if index1 >= len_word1: + return len_word2 - index2 + # if second word index is overflow - delete all from the first word + if index2 >= len_word2: + return len_word1 - index1 + diff = int(word1[index1] != word2[index2]) # current letters not identical + return min( + 1 + min_distance(index1 + 1, index2), + 1 + min_distance(index1, index2 + 1), + diff + min_distance(index1 + 1, index2 + 1), + ) + + return min_distance(0, 0) + + +if __name__ == "__main__": + import doctest + + doctest.testmod()