Skip to content
Open
Changes from 1 commit
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
66eea04
Algorithm solving problem "136. Single Number" from Leetcode (https:/…
eukub Nov 11, 2023
e662451
Algorithm solving problem "136. Single Number" from Leetcode (https:/…
eukub Nov 11, 2023
352d0fb
Algorithm solving problem "136. Single Number" from Leetcode (https:/…
eukub Nov 14, 2023
492890f
Merge branch 'TheAlgorithms:master' into Single-number-I
eukub Nov 14, 2023
ea22368
Algorithm solving problem "136. Single Number" from Leetcode (https:/…
eukub Nov 14, 2023
67859cc
Merge branch 'Single-number-I' of github.com:eukub/Python into Single…
eukub Nov 14, 2023
2fec97b
Algorithm solving problem "136. Single Number" from Leetcode (https:/…
eukub Nov 11, 2023
09a990b
Algorithm solving problem "136. Single Number" from Leetcode (https:/…
eukub Nov 11, 2023
66af9cb
Algorithm solving problem "136. Single Number" from Leetcode (https:/…
eukub Nov 14, 2023
56017b7
Algorithm solving problem "136. Single Number" from Leetcode (https:/…
eukub Nov 14, 2023
b91dbfc
Fix ignore venv in build_directory_md.py (#11156)
FishyGitHubUser Nov 16, 2023
f693cd9
adding a geometry module (#11138)
meg-1 Nov 24, 2023
9a3ddf1
Fix typo in knight_tour.py (#11173)
FishyGitHubUser Nov 25, 2023
826f64d
Typo deicmal -> decimal (#11169)
rahidzeynal Nov 25, 2023
8ecbc70
add graphs/ant_colony_optimization_algorithms.py (#11163)
Clarkzzzzz Nov 25, 2023
3c2925d
Bug fix combinations (#11158)
moaldeen Nov 25, 2023
f474f45
[pre-commit.ci] pre-commit autoupdate (#11154)
pre-commit-ci[bot] Nov 25, 2023
7922760
Create Spearman's rank correlation coefficient (#11155)
cyrixninja Nov 25, 2023
414f854
Added doctest to binary_search_tree.py (#11145)
Suyashd999 Nov 25, 2023
c36b5a7
Update levenshtein_distance.py (#11171)
pedram-mohajer Nov 26, 2023
9b8e185
Add doctest to is_safe function (#11183)
pedram-mohajer Nov 27, 2023
262c01f
[pre-commit.ci] pre-commit autoupdate (#11184)
pre-commit-ci[bot] Nov 27, 2023
0a89331
Create smallestRange.py (#11179)
pedram-mohajer Dec 1, 2023
daa4b92
Merge branch 'Single-number-I' of github.com:eukub/Python into Single…
eukub Dec 2, 2023
File filter

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Update levenshtein_distance.py (#11171)
* Update levenshtein_distance.py * Update levenshtein_distance.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update levenshtein_distance.py * Update levenshtein_distance.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update levenshtein_distance.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update levenshtein_distance.py * Update levenshtein_distance.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 <cclauss@me.com>
  • Loading branch information
3 people authored and eukub committed Dec 2, 2023
commit c36b5a7e8fa228728251bad3fa3859f90a952176
93 changes: 74 additions & 19 deletions strings/levenshtein_distance.py
Original file line number Diff line number Diff line change
@@ -1,20 +1,9 @@
"""
This is a Python implementation of the levenshtein distance.
Levenshtein distance is a string metric for measuring the
difference between two sequences.

For doctests run following command:
python -m doctest -v levenshtein-distance.py
or
python3 -m doctest -v levenshtein-distance.py

For manual testing run:
python levenshtein-distance.py
"""
from collections.abc import Callable


def levenshtein_distance(first_word: str, second_word: str) -> int:
"""Implementation of the levenshtein distance in Python.
"""
Implementation of the Levenshtein distance in Python.
:param first_word: the first word to measure the difference.
:param second_word: the second word to measure the difference.
:return: the levenshtein distance between the two words.
Expand Down Expand Up @@ -47,7 +36,7 @@ def levenshtein_distance(first_word: str, second_word: str) -> int:
current_row = [i + 1]

for j, c2 in enumerate(second_word):
# Calculate insertions, deletions and substitutions
# Calculate insertions, deletions, and substitutions
insertions = previous_row[j + 1] + 1
deletions = current_row[j] + 1
substitutions = previous_row[j] + (c1 != c2)
Expand All @@ -62,9 +51,75 @@ def levenshtein_distance(first_word: str, second_word: str) -> int:
return previous_row[-1]


def levenshtein_distance_optimized(first_word: str, second_word: str) -> int:
"""
Compute the Levenshtein distance between two words (strings).
The function is optimized for efficiency by modifying rows in place.
:param first_word: the first word to measure the difference.
:param second_word: the second word to measure the difference.
:return: the Levenshtein distance between the two words.
Examples:
>>> levenshtein_distance_optimized("planet", "planetary")
3
>>> levenshtein_distance_optimized("", "test")
4
>>> levenshtein_distance_optimized("book", "back")
2
>>> levenshtein_distance_optimized("book", "book")
0
>>> levenshtein_distance_optimized("test", "")
4
>>> levenshtein_distance_optimized("", "")
0
>>> levenshtein_distance_optimized("orchestration", "container")
10
"""
if len(first_word) < len(second_word):
return levenshtein_distance_optimized(second_word, first_word)

if len(second_word) == 0:
return len(first_word)

previous_row = list(range(len(second_word) + 1))

for i, c1 in enumerate(first_word):
current_row = [i + 1] + [0] * len(second_word)

for j, c2 in enumerate(second_word):
insertions = previous_row[j + 1] + 1
deletions = current_row[j] + 1
substitutions = previous_row[j] + (c1 != c2)
current_row[j + 1] = min(insertions, deletions, substitutions)

previous_row = current_row

return previous_row[-1]


def benchmark_levenshtein_distance(func: Callable) -> None:
"""
Benchmark the Levenshtein distance function.
:param str: The name of the function being benchmarked.
:param func: The function to be benchmarked.
"""
from timeit import timeit

stmt = f"{func.__name__}('sitting', 'kitten')"
setup = f"from __main__ import {func.__name__}"
number = 25_000
result = timeit(stmt=stmt, setup=setup, number=number)
print(f"{func.__name__:<30} finished {number:,} runs in {result:.5f} seconds")


if __name__ == "__main__":
first_word = input("Enter the first word:\n").strip()
second_word = input("Enter the second word:\n").strip()
# Get user input for words
first_word = input("Enter the first word for Levenshtein distance:\n").strip()
second_word = input("Enter the second word for Levenshtein distance:\n").strip()

# Calculate and print Levenshtein distances
print(f"{levenshtein_distance(first_word, second_word) = }")
print(f"{levenshtein_distance_optimized(first_word, second_word) = }")

result = levenshtein_distance(first_word, second_word)
print(f"Levenshtein distance between {first_word} and {second_word} is {result}")
# Benchmark the Levenshtein distance functions
benchmark_levenshtein_distance(levenshtein_distance)
benchmark_levenshtein_distance(levenshtein_distance_optimized)