Levenshtein distance: Difference between revisions

Add bruijn
(Added Algol 68.)
(Add bruijn)
 
(92 intermediate revisions by 45 users not shown)
Line 17:
 
 
;Task;:
Implements a Levenshtein distance function, or uses a library function, to show the Levenshtein distance between   "kitten"   and   "sitting".
 
Line 23:
;Related task:
*   [[Longest common subsequence]]
 
 
{{Template:Strings}}
<br><br>
 
=={{header|11l}}==
{{trans|Python}}
 
<syntaxhighlight lang="11l">F minimumEditDistance(=s1, =s2)
I s1.len > s2.len
(s1, s2) = (s2, s1)
 
V distances = Array(0 .. s1.len)
 
L(char2) s2
V newDistances = [L.index + 1]
L(char1) s1
I char1 == char2
newDistances.append(distances[L.index])
E
newDistances.append(1 + min((distances[L.index], distances[L.index + 1], newDistances.last)))
distances = newDistances
R distances.last
 
print(minimumEditDistance(‘kitten’, ‘sitting’))
print(minimumEditDistance(‘rosettacode’, ‘raisethysword’))</syntaxhighlight>
 
{{out}}
<pre>
3
8
</pre>
 
=={{header|360 Assembly}}==
<langsyntaxhighlight lang="360asm">* Levenshtein distance - 22/04/2020
LEVENS CSECT
USING LEVENS,R13 base register
Line 198 ⟶ 229:
XDEC DS CL12 temp fo xdeco
REGEQU
END LEVENS</langsyntaxhighlight>
{{out}}
<pre>
Line 209 ⟶ 240:
 
=={{header|Action!}}==
{{Improve||The output shown does not appear to match the PrintF calls in the code}}
<lang action>
<syntaxhighlight lang="action">
DEFINE STRING="CHAR ARRAY" ; sys.act
DEFINE width="15" ; max characters 14
Line 232 ⟶ 264:
 
FOR I=0 TO MatrixSize-1 DO matrix(I)=0 OD
FOR I=0 TO M DO Set2Dm(matrix, I,10, I) OD
FOR J=0 TO N DO Set2Dm(matrix, 10,J, J) OD
FOR J=1 TO N DO
Line 288 ⟶ 320:
;PrintF("Damerau Levenshtein Distance=%U%E%E",result)
RETURN
</syntaxhighlight>
</lang>
{{out}}
<pre>kitten, sitting: 3
Line 295 ⟶ 327:
 
=={{header|Ada}}==
<langsyntaxhighlight Adalang="ada">with Ada.Text_IO;
 
procedure Main is
Line 328 ⟶ 360:
("rosettacode -> raisethysword:" &
Integer'Image (Levenshtein_Distance ("rosettacode", "raisethysword")));
end Main;</langsyntaxhighlight>
{{out}}
<pre>kitten -> sitting: 3
Line 335 ⟶ 367:
=={{header|Aime}}==
{{trans|C}}
<langsyntaxhighlight lang="aime">integer
dist(data s, t, integer i, j, list d)
{
Line 379 ⟶ 411:
 
0;
}</langsyntaxhighlight>
{{Out}}
<pre>`rosettacode' to `raisethysword' is 8
Line 386 ⟶ 418:
=={{header|ALGOL 68}}==
{{Trans|Action!}}
...largely to highlight the syntactic similarities.
<lang algol68># Calculate Levenshtein distance between strings - translated from the Action! sample #
<br>
Non-recursive algorithm - although Algol 68 supports recursion, Action! doesn't.
<syntaxhighlight lang="algol68"># Calculate Levenshtein distance between strings - translated from the Action! sample #
BEGIN
 
PROC damerau PROC levenshtein distance = (STRING str1, str2)INT:
BEGIN
 
INT m=UPB str1;
INT n=UPB str2;
 
(0:m,0:n)INT matrix;
FOR i FROM 0 TO m DO FOR j FROM 0 TO n DO matrix(i,j):=0 OD OD;
FOR i TO m DO matrix(i,1):=i OD;
FOR j TO n DO matrix(1,j):=j OD;
FOR j FROM 1 TO n DO
FOR i FROM 1 TO m DO
IF str1(i) = str2(j) THEN
matrix(i,j):=matrix(i-1, j-1) # no operation required #
ELSE
INT min := matrix(i-1,j)+1 ; # REMdeletion delete #
INT k = matrix(i,j-1)+1 ; # REMinsertion insert #
INT l = matrix(i-1, j-1)+1 ; # REM substitution #
IF k < min THEN min:=k FI;
IF l < min THEN min:=l FI;
matrix(i,j):=min
COMMENT
;
# transposition for Damerau Levenshtein Distance #
IF i>1 AND j>1 THEN
IF str1(i) = str2(j-1) AND str1(i-1) = str2(j) THEN
INT min:=matrix(i,j);
INT tmp=matrix(i-2,j-2)+1;
IF min>tmp THEN min=tmp FI;
matrix(i,j):=min # REM transposition #
FI
FI
OD
COMMENT
FIOD;
ODmatrix(m,n)
ODEND;
matrix(m,n)
END;
 
STRING word 1, word 2;
word 1 :="kitten"; word 2 := "sitting";
print((word 1," -> ",word 2,newline": "));
print(("Levenshtein Distance=: ",whole(damerau levenshtein distance(word 1,word 2),0),newline));
word 1 := "rosettacode"; word 2 := "raisethysword";
print((word 1," -> ",word 2,newline": "));
print(("Levenshtein Distance=: ",whole(damerau levenshtein distance(word 1,word 2),0),newline));
word 1 := "qwerty"; word 2 := "qweryt";
print((word 1," -> ",word 2,newline": "));
print(("Levenshtein Distance=: ",whole(damerau levenshtein distance(word 1,word 2),0),newline));
 
END</lang>
word 1 := "Action!"; word 2 := "Algol 68";
print((word 1," -> ",word 2,": "));
print(("Levenshtein Distance: ",whole(levenshtein distance(word 1,word 2),0),newline))
END</syntaxhighlight>
{{out}}
<pre>
kitten -> sitting: Levenshtein Distance: 3
rosettacode -> raisethysword: Levenshtein Distance=3: 8
qwerty -> qweryt: Levenshtein Distance: 2
rosettacode - raisethysword
Action! -> Algol 68: Levenshtein Distance=8: 7
qwerty - qweryt
Levenshtein Distance=2
</pre>
 
Line 457 ⟶ 482:
===Iteration===
Translation of the "fast" C-version
<langsyntaxhighlight AppleScriptlang="applescript">set dist to findLevenshteinDistance for "sunday" against "saturday"
to findLevenshteinDistance for s1 against s2
script o
Line 511 ⟶ 536:
end if
end if
end min3</langsyntaxhighlight>
 
===Composition of generic functions===
{{Trans|JavaScript}}
(ES6 version)
 
<lang AppleScript>-- levenshtein :: String -> String -> Int
In the ancient tradition of "''Use library functions whenever feasible.''" (for better productivity), and also in the even older functional tradition of composing values (for better reliability) rather than sequencing actions:
<syntaxhighlight lang="applescript">-- levenshtein :: String -> String -> Int
on levenshtein(sa, sb)
set {s1, s2} to {characters of sa, characters of sb}
Line 534 ⟶ 561:
end script
itemlast -1item of foldl(result, enumFromTo(0, length of s1), s2)
end levenshtein
 
--------------------------- TEST- ---------------------------
on run
script test
on |λ|(xstuple)
levenshtein(itemset 1 of xs{sa, item 2sb} ofto xs)tuple
levenshtein(sa, sb)
end |λ|
end script
Line 552 ⟶ 581:
 
 
--------------------- GENERIC FUNCTIONS ---------------------
 
-- enumFromTo :: Int -> Int -> [Int]
Line 566 ⟶ 595:
end if
end enumFromTo
 
 
-- fromEnum :: Enum a => a -> Int
Line 586 ⟶ 616:
end if
end fromEnum
 
 
-- foldl :: (a -> b -> a) -> a -> [b] -> a
Line 598 ⟶ 629:
end tell
end foldl
 
 
-- map :: (a -> b) -> [a] -> [b]
Line 612 ⟶ 644:
end tell
end map
 
 
-- minimum :: Ord a => [a] -> a
Line 624 ⟶ 657:
return m
end minimum
 
 
-- mReturn :: First-class m => (a -> b) -> m (a -> b)
Line 636 ⟶ 670:
end if
end mReturn
 
 
-- scanl :: (b -> a -> b) -> b -> [a] -> [b]
Line 650 ⟶ 685:
end tell
end scanl
 
 
-- zip3 :: [a] -> [b] -> [c] -> [(a, b, c)]
Line 660 ⟶ 696:
map(result, items 1 thru ¬
minimum({length of xs, length of ys, length of zs}) of xs)
end zip3</langsyntaxhighlight>
{{Out}}
<langsyntaxhighlight AppleScriptlang="applescript">{3, 3, 8, 8}</langsyntaxhighlight>
 
=={{header|Arc}}==
Line 668 ⟶ 704:
O(n * m) time, linear space, using lists instead of vectors
 
<langsyntaxhighlight lang="lisp">(def levenshtein (str1 str2)
(withs l1 len.str1
l2 len.str2
Line 683 ⟶ 719:
next))
(= row nrev.next)))
row.l1))</langsyntaxhighlight>
 
=={{header|Arturo}}==
 
<syntaxhighlight lang="rebol">print levenshtein "kitten" "sitting"</syntaxhighlight>
 
{{out}}
 
<pre>3</pre>
 
=={{header|AutoHotkey}}==
{{trans|Go}}
<langsyntaxhighlight AutoHotkeylang="autohotkey">levenshtein(s, t){
If s =
return StrLen(t)
Line 705 ⟶ 749:
s1 := "kitten"
s2 := "sitting"
MsgBox % "distance between " s1 " and " s2 ": " levenshtein(s1, s2)</langsyntaxhighlight>It correctly outputs '3'
 
 
=={{header|AWK}}==
Line 712 ⟶ 755:
Slavishly copied from the very clear AutoHotKey example.
 
<langsyntaxhighlight lang="awk">#!/usr/bin/awk -f
 
BEGIN {
Line 757 ⟶ 800:
}
 
</syntaxhighlight>
</lang>
 
Example output:
Line 767 ⟶ 810:
Alternative, much faster but also less readable lazy-evaluation version from http://awk.freeshell.org/LevenshteinEditDistance
(where the above takes e.g. 0m44.904s in gawk 4.1.3 for 5 edits (length 10 and 14 strings), this takes user 0m0.004s):
<langsyntaxhighlight lang="awk">#!/usr/bin/awk -f
 
function levdist(str1, str2, l1, l2, tog, arr, i, j, a, b, c) {
Line 795 ⟶ 838:
return arr[tog, j-1]
}
</syntaxhighlight>
</lang>
 
=={{header|BBC BASIC}}==
<langsyntaxhighlight lang="bbcbasic"> PRINT "'kitten' -> 'sitting' has distance " ;
PRINT ; FNlevenshtein("kitten", "sitting")
PRINT "'rosettacode' -> 'raisethysword' has distance " ;
Line 825 ⟶ 868:
NEXT
NEXT j%
= d%(i%-1,j%-1)</langsyntaxhighlight>
'''Output:'''
<pre>
Line 831 ⟶ 874:
'rosettacode' -> 'raisethysword' has distance 8
</pre>
 
=={{header|BQN}}==
Recursive slow version:
<syntaxhighlight lang="bqn">Levenshtein ← {
𝕨 𝕊"": ≠𝕨;
""𝕊 𝕩: ≠𝕩;
𝕨 𝕊 𝕩:
Tail←1⊸↓
𝕨 =○⊑◶⟨1+·⌊´ 𝕊○Tail ∾ Tail⊸𝕊 ∾ 𝕊⟜Tail, 𝕊○Tail⟩ 𝕩
}</syntaxhighlight>
Fast version:
<syntaxhighlight lang="bqn">Levenshtein ← @⊸∾⊸{¯1⊑(↕≠𝕨)𝕨{(1⊸+⊸⌊`1⊸+⌊⊑⊸»+𝕨≠𝕗˙)𝕩}´⌽𝕩}</syntaxhighlight>
{{out|Example use}}
<syntaxhighlight lang="text"> "kitten" Levenshtein "sitting"
3
"Saturday" Levenshtein "Sunday"
3
"rosettacode" Levenshtein "raisethysword"
8</syntaxhighlight>
 
=={{header|Bracmat}}==
{{trans|C}}
Recursive method, but with memoization.
<langsyntaxhighlight lang="bracmat">(levenshtein=
lev cache
. ( lev
Line 859 ⟶ 921:
)
& new$hash:?cache
& lev$!arg);</langsyntaxhighlight>
{{out|Demonstrating}}
<pre> levenshtein$(kitten,sitting)
Line 865 ⟶ 927:
levenshtein$(rosettacode,raisethysword)
8</pre>
 
=={{header|Bruijn}}==
{{trans|Haskell}}
Recursive and non-memoized method:
 
<syntaxhighlight lang="bruijn>
:import std/Combinator .
:import std/Char C
:import std/List .
:import std/Math .
 
levenshtein y [[[∅?1 ∀0 (∅?0 ∀1 (0 (1 [[[[go]]]])))]]]
go (C.eq? 3 1) (6 2 0) ++(lmin ((6 2 0) : ((6 5 0) : {}(6 2 4))))
 
:test ((levenshtein "rosettacode" "raisethysword") =? (+8)) ([[1]])
:test ((levenshtein "kitten" "sitting") =? (+3)) ([[1]])
</syntaxhighlight>
 
=={{header|C}}==
Recursive method. Deliberately left in an inefficient state to show the recursive nature of the algorithm; notice how it would have become the Wikipedia algorithm if we memoized the function against parameters <code>ls</code> and <code>lt</code>.
<langsyntaxhighlight Clang="c">#include <stdio.h>
#include <string.h>
 
Line 912 ⟶ 991:
 
return 0;
}</langsyntaxhighlight>
Take the above and add caching, we get (in [[C99]]):
<langsyntaxhighlight lang="c">#include <stdio.h>
#include <string.h>
 
Line 957 ⟶ 1,036:
return 0;
}</langsyntaxhighlight>
 
=={{header|C sharp|C#}}==
This is a straightforward translation of the Wikipedia pseudocode.
<langsyntaxhighlight lang="csharp">using System;
 
namespace LevenshteinDistance
Line 1,010 ⟶ 1,089:
}
}
}</langsyntaxhighlight>
{{out|Example output}}
<pre>
Line 1,021 ⟶ 1,100:
 
=={{header|C++}}==
<langsyntaxhighlight lang="c">#include <string>
#include <iostream>
using namespace std;
Line 1,028 ⟶ 1,107:
// Martin Ettl, 2012-10-05
 
size_t uiLevenshteinDistance(const std::string &s1, const std::string &s2)
{
const size_t m(s1.size());
const size_t nm(s2s1.size());,
n(s2.size());
 
if( m==0 ) return n;
if( n==0 ) return m;
 
// allocation below is not ISO-compliant,
size_t *costs = new size_t[n + 1];
// it won't work with -pedantic-errors.
size_t costs[n + 1];
 
for( size_t k=0; k<=n; k++ ) costs[k] = k;
 
size_t i ={ 0 };
for (char const &c1 : s1)
for ( std::string::const_iterator it1 = s1.begin(); it1 != s1.end(); ++it1, ++i )
{
costs[0] = i+1;
size_t corner ={ i; },
j { 0 };
 
size_tfor j(char =const 0;&c2 : s2)
for ( std::string::const_iterator it2 = s2.begin(); it2 != s2.end(); ++it2, ++j )
{
size_t upper ={ costs[j+1] };
if( *it1c1 == *it2c2 ) costs[j+1] = corner;
else {
size_t t(upper<corner? upper: corner);
costs[j+1] = corner;
}
else
{
size_t t(upper<corner?upper:corner);
costs[j+1] = (costs[j]<t?costs[j]:t)+1;
}
 
corner = upper;
j++;
}
i++;
}
 
size_t result =return costs[n];
delete [] costs;
 
return result;
}
 
int main()
{
string s0 ={ "rosettacode"; },
string s1 ={ "raisethysword" };
cout << "distance between " << s0 << " and " << s1 << " : "
<< uiLevenshteinDistance(s0,s1) << std::endl;
 
return 0;
}</syntaxhighlight>
}
</lang>
{{out|Example output}}
<pre>
$ ./a.out rosettacode raisethysword
distance between rosettacode and raisethysword : 8
</pre>
 
===Generic ISO C++ version===
<syntaxhighlight lang="cpp">#include <algorithm>
#include <iostream>
#include <numeric>
#include <string>
#include <vector>
template <typename StringType>
size_t levenshtein_distance(const StringType& s1, const StringType& s2) {
const size_t m = s1.size();
const size_t n = s2.size();
if (m == 0)
return n;
if (n == 0)
return m;
std::vector<size_t> costs(n + 1);
std::iota(costs.begin(), costs.end(), 0);
size_t i = 0;
for (auto c1 : s1) {
costs[0] = i + 1;
size_t corner = i;
size_t j = 0;
for (auto c2 : s2) {
size_t upper = costs[j + 1];
costs[j + 1] = (c1 == c2) ? corner
: 1 + std::min(std::min(upper, corner), costs[j]);
corner = upper;
++j;
}
++i;
}
return costs[n];
}
int main() {
std::wstring s0 = L"rosettacode";
std::wstring s1 = L"raisethysword";
std::wcout << L"distance between " << s0 << L" and " << s1 << L": "
<< levenshtein_distance(s0, s1) << std::endl;
return 0;
}</syntaxhighlight>
 
{{out}}
<pre>
distance between rosettacode and raisethysword: 8
</pre>
 
Line 1,089 ⟶ 1,211:
 
===Recursive Version===
<langsyntaxhighlight lang="lisp">(defn levenshtein [str1 str2]
(let [len1 (count str1)
len2 (count str2)]
Line 1,101 ⟶ 1,223:
(levenshtein (rest str1) (rest str2))))))))
 
(println (levenshtein "rosettacode" "raisethysword"))</langsyntaxhighlight>
{{out}}
<pre>8</pre>
 
===Iterative version===
<langsyntaxhighlight lang="lisp">(defn levenshtein [w1 w2]
(letfn [(cell-value [same-char? prev-row cur-row col-idx]
(min (inc (nth prev-row col-idx))
Line 1,126 ⟶ 1,248:
i))))
[row-idx] (range 1 (count prev-row)))]
(recur (inc row-idx) max-rows next-prev-row))))))</langsyntaxhighlight>
 
=={{header|CLU}}==
<syntaxhighlight lang="clu">min = proc [T: type] (a, b: T) returns (T)
where T has lt: proctype (T,T) returns (bool)
if a<b
then return(a)
else return(b)
end
end min
 
levenshtein = proc (s, t: string) returns (int)
ai = array[int]
aai = array[array[int]]
m: int := string$size(s)
n: int := string$size(t)
d: aai := aai$fill_copy(0, m+1, ai$fill(0, n+1, 0))
for i: int in int$from_to(1, m) do d[i][0] := i end
for j: int in int$from_to(1, n) do d[0][j] := j end
for j: int in int$from_to(1, n) do
for i: int in int$from_to(1, m) do
cost: int
if s[i] = t[j]
then cost := 0
else cost := 1
end
d[i][j] := min[int]( d[i-1][j]+1,
min[int]( d[i][j-1]+1,
d[i-1][j-1]+cost ))
end
end
return (d[m][n])
end levenshtein
 
show = proc (s, t: string)
po: stream := stream$primary_output()
stream$putl(po, s || " => " || t || ": " || int$unparse(levenshtein(s,t)))
end show
 
start_up = proc ()
show("kitten", "sitting")
show("rosettacode", "raisethysword")
end start_up</syntaxhighlight>
{{out}}
<pre>kitten => sitting: 3
rosettacode => raisethysword: 8</pre>
 
=={{header|COBOL}}==
GnuCobol 2.2
<langsyntaxhighlight lang="cobol">
identification division.
program-id. Levenshtein.
Line 1,193 ⟶ 1,364:
display trim(string-a) " -> " trim(string-b) " = " trim(distance)
.
</syntaxhighlight>
</lang>
{{out|Output}}
<pre>
Line 1,202 ⟶ 1,373:
 
=={{header|CoffeeScript}}==
<langsyntaxhighlight lang="coffeescript">levenshtein = (str1, str2) ->
# more of less ported simple algorithm from JS
m = str1.length
Line 1,231 ⟶ 1,402:
console.log levenshtein("stop", "tops")
console.log levenshtein("yo", "")
console.log levenshtein("", "yo")</langsyntaxhighlight>
 
=={{header|Common Lisp}}==
<langsyntaxhighlight lang="lisp">(defun levenshtein (a b)
(let* ((la (length a))
(lb (length b))
(rec (make-array (list (1+ la) (1+ lb)) :initial-element nil)))
(labels ((leven (x y)
 
(defun leven (x y) (cond
(cond(zerop x) y)
((zerop xy) yx)
((aref rec x y) (aref rec x y))
((zerop y) x)
((aref rec x y) (t (setf (aref rec x y))
(tmin (setf+ (arefleven rec(1- x) y) 1)
(+ (if (char= (char a (- la x)) (char+ b(leven x (1- lb y))) 0 1)
(+ (leven (1- x) (1- y)) (if (char= (char a (- la x)) (char b (- lb y))) 0 1))))))))
(min (leven (1- x) y)
(leven x (1-leven la ylb))))
(leven (1- x) (1- y))))))))
(leven la lb)))
 
(print (levenshtein "rosettacode" "raisethysword"))</langsyntaxhighlight>
{{out}}
<pre>8</pre>
Line 1,257 ⟶ 1,426:
=={{header|Crystal}}==
The standard library includes [https://crystal-lang.org/api/0.19.2/Levenshtein.html levenshtein] module
<langsyntaxhighlight lang="ruby">require "levenshtein"
puts Levenshtein.distance("kitten", "sitting")
puts Levenshtein.distance("rosettacode", "raisethysword")
</syntaxhighlight>
</lang>
{{out}}
<pre>3
Line 1,266 ⟶ 1,435:
 
{{trans|Ruby 1st version}}
<langsyntaxhighlight lang="ruby">module Levenshtein
def self.distance(a, b)
Line 1,289 ⟶ 1,458:
Levenshtein.test
</syntaxhighlight>
</lang>
{{out}}
<pre>
Line 1,298 ⟶ 1,467:
 
{{trans|Ruby 2nd version}}
<langsyntaxhighlight lang="ruby">def levenshtein_distance(str1, str2)
n, m = str1.size, str2.size
max = n / 2
Line 1,329 ⟶ 1,498:
puts "distance(#{a}, #{b}) = #{levenshtein_distance(a, b)}"
end
</syntaxhighlight>
</lang>
{{out}}
<pre>
Line 1,340 ⟶ 1,509:
===Standard Version===
The standard library [http://www.digitalmars.com/d/2.0/phobos/std_algorithm.html#levenshteinDistance std.algorithm] module includes a Levenshtein distance function:
<langsyntaxhighlight lang="d">void main() {
import std.stdio, std.algorithm;
 
levenshteinDistance("kitten", "sitting").writeln;
}</langsyntaxhighlight>
{{out}}
<pre>3</pre>
Line 1,350 ⟶ 1,519:
===Iterative Version===
{{trans|Java}}
<langsyntaxhighlight lang="d">import std.stdio, std.algorithm;
 
int distance(in string s1, in string s2) pure nothrow {
Line 1,381 ⟶ 1,550:
foreach (p; [["kitten", "sitting"], ["rosettacode", "raisethysword"]])
writefln("distance(%s, %s): %d", p[0], p[1], distance(p[0], p[1]));
}</langsyntaxhighlight>
 
===Memoized Recursive Version===
{{trans|Python}}
<langsyntaxhighlight lang="d">import std.stdio, std.array, std.algorithm, std.functional;
 
uint lDist(T)(in const(T)[] s, in const(T)[] t) nothrow {
Line 1,399 ⟶ 1,568:
lDist("kitten", "sitting").writeln;
lDist("rosettacode", "raisethysword").writeln;
}</langsyntaxhighlight>
 
=={{header|Delphi}}==
{{Trans|C#}}
<syntaxhighlight lang="delphi">
program Levenshtein_distanceTest;
 
{$APPTYPE CONSOLE}
 
{$R *.res}
 
uses
System.SysUtils,
Math;
 
function Levenshtein_distance(s, t: string): integer;
var
d: array of array of integer;
i, j, cost: integer;
begin
SetLength(d, Length(s) + 1);
for i := Low(d) to High(d) do
begin
SetLength(d[i], Length(t) + 1);
end;
 
for i := Low(d) to High(d) do
begin
d[i, 0] := i;
for j := Low(d[i]) to High(d[i]) do
begin
d[0, j] := j;
end;
end;
 
for i := Low(d) + 1 to High(d) do
begin
for j := Low(d[i]) + 1 to High(d[i]) do
begin
if s[i] = t[j] then
begin
cost := 0;
end
else
begin
cost := 1;
end;
 
d[i, j] := Min(Min(d[i - 1, j] + 1, //deletion
d[i, j - 1] + 1), //insertion
d[i - 1, j - 1] + cost //substitution
);
end;
end;
Result := d[Length(s), Length(t)];
end;
 
procedure Println(s, t: string);
begin
Writeln('> LevenshteinDistance "', s, '" "', t, '"');
Writeln(s, ' -> ', t, ' = ', Levenshtein_distance(s, t), #10);
end;
 
begin
Println('kitten', 'sitting');
Println('rosettacode', 'raisethysword');
readln;
end.
</syntaxhighlight>
 
 
 
=={{header|DWScript}}==
Based on Wikipedia version
<langsyntaxhighlight lang="delphi">function LevenshteinDistance(s, t : String) : Integer;
var
i, j : Integer;
Line 1,425 ⟶ 1,664:
end;
 
PrintLn(LevenshteinDistance('kitten', 'sitting'));</langsyntaxhighlight>
 
=={{header|Dyalect}}==
 
<langsyntaxhighlight lang="dyalect">func minlevenshtein(xs, yt) {
ifvar xn <= y {s.Length()
var m = xt.Length()
var d = Array.Empty(n + 1, () => Array.Empty(m + 1))
} else {
y
}
}
 
func levenshtein(s, t) {
var n = s.len()
var m = t.len()
var d = Array.empty(n + 1, () => Array.empty(m + 1))
 
if n == 0 {
return m
Line 1,453 ⟶ 1,684:
d[i][0] = i
}
 
for j in 0..m {
d[0][j] = j
Line 1,472 ⟶ 1,703:
}
}
 
d[n][m]
}
 
func run(x, y) {
print("\(x) -> \(y) = \(levenshtein(x, y))")
}
 
run("rosettacode", "raisethysword")</langsyntaxhighlight>
 
{{out}}
 
<pre>rosettacode -> raisethysword = 8</pre>
 
=={{header|EasyLang}}==
{{trans|AWK}}
 
<syntaxhighlight lang=easylang>
func dist s1$ s2$ .
if len s1$ = 0
return len s2$
.
if len s2$ = 0
return len s1$
.
c1$ = substr s1$ 1 1
c2$ = substr s2$ 1 1
s1rest$ = substr s1$ 2 len s1$
s2rest$ = substr s2$ 2 len s2$
#
if c1$ = c2$
return dist s1rest$ s2rest$
.
min = lower dist s1rest$ s2rest$ dist s1$ s2rest$
min = lower min dist s1rest$ s2rest$
return min + 1
.
print dist "kitten" "sitting"
print dist "rosettacode" "raisethysword"
</syntaxhighlight>
 
=={{header|EchoLisp}}==
<langsyntaxhighlight lang="lisp">
;; Recursive version adapted from Clojure
;; Added necessary memoization
Line 1,516 ⟶ 1,774:
 
(levenshtein "rosettacode" "raisethysword") → 8
</syntaxhighlight>
</lang>
 
=={{header|Ela}}==
This code is translated from Haskell version.
 
<langsyntaxhighlight lang="ela">open list
 
levenshtein s1 s2 = last <| foldl transform [0 .. length s1] s2
where transform (n::ns')@ns c = scanl calc (n+1) <| zip3 s1 ns ns'
where calc z (c', x, y) = minimum [y+1, z+1, x + toInt (c' <> c)]</langsyntaxhighlight>
 
Executing:
 
<langsyntaxhighlight lang="ela">(levenshtein "kitten" "sitting", levenshtein "rosettacode" "raisethysword")</langsyntaxhighlight>
{{out}}
<pre>(3, 8)</pre>
Line 1,535 ⟶ 1,793:
=={{header|Elixir}}==
{{trans|Ruby}}
<langsyntaxhighlight lang="elixir">defmodule Levenshtein do
def distance(a, b) do
ta = String.downcase(a) |> to_char_listto_charlist |> List.to_tuple
tb = String.downcase(b) |> to_char_listto_charlist |> List.to_tuple
m = tuple_size(ta)
n = tuple_size(tb)
Line 1,562 ⟶ 1,820:
Enum.each(Enum.chunk(words, 2), fn [a,b] ->
IO.puts "distance(#{a}, #{b}) = #{Levenshtein.distance(a,b)}"
end)</langsyntaxhighlight>
 
{{out}}
Line 1,573 ⟶ 1,831:
=={{header|Erlang}}==
Here are two implementations. The first is the naive version, the second is a memoized version using Erlang's dictionary datatype.
<langsyntaxhighlight lang="erlang">
-module(levenshtein).
-compile(export_all).
Line 1,609 ⟶ 1,867:
{L,dict:store({S,T},L,C3)}
end.
</syntaxhighlight>
</lang>
Below is a comparison of the runtimes, measured in microseconds, between the two implementations.
<langsyntaxhighlight lang="erlang">
68> timer:tc(levenshtein,distance,["rosettacode","raisethysword"]).
{774799,8} % {Time, Result}
Line 1,620 ⟶ 1,878:
71> timer:tc(levenshtein,distance_cached,["kitten","sitting"]).
{213,3}
</syntaxhighlight>
</lang>
 
=={{header|ERRE}}==
<syntaxhighlight lang="erre">
<lang ERRE>
PROGRAM LEVENSHTEIN
 
Line 1,667 ⟶ 1,925:
!$ERASE D%
END PROGRAM
</syntaxhighlight>
</lang>
{{out}}<pre>
'kitten' -> 'sitting' has distance 3
Line 1,675 ⟶ 1,933:
=={{header|Euphoria}}==
Code by Jeremy Cowgar from the [http://www.rapideuphoria.com/cgi-bin/asearch.exu?gen=on&keywords=Levenshtein Euphoria File Archive].
<langsyntaxhighlight lang="euphoria">function min(sequence s)
atom m
m = s[1]
Line 1,721 ⟶ 1,979:
 
? levenshtein("kitten", "sitting")
? levenshtein("rosettacode", "raisethysword")</langsyntaxhighlight>
{{out}}
<pre>3
Line 1,727 ⟶ 1,985:
</pre>
 
=={{header|F SharpF_Sharp|F#}}==
=== Standard version ===
<lang FSharp>
<syntaxhighlight lang="fsharp">
open System
 
Line 1,761 ⟶ 2,020:
 
Console.ReadKey () |> ignore
</syntaxhighlight>
</lang>
 
=== Recursive Version ===
<syntaxhighlight lang="fsharp">
open System
 
let levenshtein (s1:string) (s2:string) : int =
 
let s1' = s1.ToCharArray()
let s2' = s2.ToCharArray()
 
let rec dist l1 l2 =
match (l1,l2) with
| (l1, 0) -> l1
| (0, l2) -> l2
| (l1, l2) ->
if s1'.[l1-1] = s2'.[l2-1] then dist (l1-1) (l2-1)
else
let d1 = dist (l1 - 1) l2
let d2 = dist l1 (l2 - 1)
let d3 = dist (l1 - 1) (l2 - 1)
1 + Math.Min(d1,(Math.Min(d2,d3)))
 
dist s1.Length s2.Length
printfn "dist(kitten, sitting) = %i" (levenshtein "kitten" "sitting")
</syntaxhighlight>
 
=={{header|Factor}}==
<langsyntaxhighlight lang="factor">USING: lcs prettyprint ;
"kitten" "sitting" levenshtein .</langsyntaxhighlight>
{{out}}
<pre>
Line 1,773 ⟶ 2,058:
=={{header|Forth}}==
{{trans|C}}
<langsyntaxhighlight lang="forth">: levenshtein ( a1 n1 a2 n2 -- n3)
dup \ if either string is empty, difference
if \ is inserting all chars from the other
Line 1,795 ⟶ 2,080:
 
s" kitten" s" sitting" levenshtein . cr
s" rosettacode" s" raisethysword" levenshtein . cr</langsyntaxhighlight>
 
=={{header|Fortran}}==
<syntaxhighlight lang="fortran">
program demo_edit_distance
character(len=:),allocatable :: sources(:),targets(:)
integer,allocatable :: answers(:),expected(:)
 
sources=[character(len=20) :: "kitten", "rosettacode", "Saturday", "sleep", "qwerty", "Fortran" ]
targets=[character(len=20) :: "sitting", "raisethysword", "Sunday", "fleeting", "qweryt", "Fortran" ]
expected=[ 3, 8, 3, 5, 2, 0 ]
! calculate answers
answers=edit_distance(sources,targets)
! print inputs, answers, and confirmation
do i=1, size(sources)
write(*,'(*(g0,1x))') sources(i), targets(i), answers(i), answers(i) == expected(i)
enddo
! a longer test
write(*,*)edit_distance("here's a bunch of words", "to wring out this code")==18
 
contains
 
pure elemental integer function edit_distance (source,target)
!! The Levenshtein distance function returns how many edits (deletions,
!! insertions, transposition) are required to turn one string into another.
character(len=*), intent(in) :: source, target
integer :: len_source, len_target, i, j, cost
integer :: matrix(0:len_trim(source), 0:len_trim(target))
len_source = len_trim(source)
len_target = len_trim(target)
matrix(:,0) = [(i,i=0,len_source)]
matrix(0,:) = [(j,j=0,len_target)]
do i = 1, len_source
do j = 1, len_target
cost=merge(0,1,source(i:i)==target(j:j))
matrix(i,j) = min(matrix(i-1,j)+1, matrix(i,j-1)+1, matrix(i-1,j-1)+cost)
enddo
enddo
edit_distance = matrix(len_source,len_target)
end function edit_distance
 
end program demo_edit_distance
</syntaxhighlight>
{{out}}
<pre>
kitten sitting 3 T
rosettacode raisethysword 8 T
Saturday Sunday 3 T
sleep fleeting 5 T
qwerty qweryt 2 T
Fortran Fortran 0 T
T
</pre>
 
=={{header|FreeBASIC}}==
<langsyntaxhighlight lang="freebasic">' FB 1.05.0 Win64
 
' Uses the "iterative with two matrix rows" algorithm
Line 1,846 ⟶ 2,183:
Print
Print "Press any key to quit"
Sleep</langsyntaxhighlight>
 
{{out}}
Line 1,857 ⟶ 2,194:
=={{header|Frink}}==
Frink has a built-in function to calculate the Levenshtein edit distance between two strings:
<langsyntaxhighlight lang="frink">println[editDistance["kitten","sitting"]]</langsyntaxhighlight>
It also has a function to calculate the Levenshtein-Damerau edit distance, <CODE>editDistanceDamerau[<I>str1</I>,<I>str2</I>]</CODE>. This is similar to the <CODE>editDistance</CODE> function but also allows ''swaps'' between two adjoining characters, which count as an edit distance of 1. This may make distances between some strings shorter, by say, treating transposition errors in a word as a less expensive operation than in the pure Levenshtein algorithm, and is generally more useful in more circumstances.
 
=={{header|FutureBasic}}==
Recursive version.
Based on Wikipedia algorithm. Suitable for Pascal strings.
<langsyntaxhighlight lang="futurebasic">
local fn LevenshteinDistance( s1 as CFStringRef, s2 as CFStringRef ) as NSInteger
include "ConsoleWindow"
NSInteger result
// If strings are equal, Levenshtein distance is 0
if ( fn StringIsEqual( s1, s2 ) ) then result = 0 : exit fn
// If either string is empty, then distance is the length of the other string.
if ( len(s1) == 0) then result = len(s2) : exit fn
if ( len(s2) == 0) then result = len(s1) : exit fn
// The remaining recursive process uses first characters and remainder of each string.
CFStringRef s1First = fn StringSubstringToIndex( s1, 1 )
CFStringRef s2First = fn StringSubstringToIndex( s2, 1 )
CFStringRef s1Rest = mid( s1, 1, len(s1) -1 )
CFStringRef s2Rest = mid( s2, 1, len(s2) -1 )
// If leading characters are the same, then distance is that between the rest of the strings.
if fn StringIsEqual( s1First, s2First ) then result = fn LevenshteinDistance( s1Rest, s2Rest ) : exit fn
// Find the distances between sub strings.
NSInteger distA = fn LevenshteinDistance( s1Rest, s2 )
NSInteger distB = fn LevenshteinDistance( s1, s2Rest )
NSInteger distC = fn LevenshteinDistance( s1Rest, s2Rest )
// Return the minimum distance between substrings.
NSInteger minDist = distA
if ( distB < minDist ) then minDist = distB
if ( distC < minDist ) then minDist = distC
result = minDist + 1 // Include change for the first character.
end fn = result
 
local fn LevenshteinDistance( aStr as Str255, bStr as Str255 ) as long
dim as long m, n, i, j, min, k, l
dim as long distance( 255, 255 )
 
NSInteger i
m = len(aStr)
CFStringRef testStr( 6, 2 )
n = len(bStr)
for i = 0 to m
distance( i, 0 ) = i
next
 
testStr( 0, 0 ) = @"kitten" : testStr( 0, 1 ) = @"sitting"
for j = 0 to n
testStr( 1, 0 ) = @"rosettacode" : testStr( 1, 1 ) = @"raisethysword"
distance( 0, j ) = j
testStr( 2, 0 ) = @"Saturday" : testStr( 2, 1 ) = @"Sunday"
next
testStr( 3, 0 ) = @"FutureBasic" : testStr( 3, 1 ) = @"FutureBasic"
testStr( 4, 0 ) = @"rave" : testStr( 4, 1 ) = @"ravel"
for j = 1 to n
testStr( 5, 0 ) = @"black" : testStr( 5, 1 ) = @"slack"
for i = 1 to m
testStr( 6, 0 ) = @"rave" if mid$( aStr, i, 1 ) == mid$: testStr( bStr, j6, 1 ) = @"grave"
distance( i, j ) = distance( i-1, j-1 )
else
min = distance( i-1, j ) + 1
k = distance( i, j - 1 ) + 1
l = distance( i-1, j-1 ) + 1
if k < min then min = k
if l < min then min = l
distance( i, j ) = min
end if
next
next
end fn = distance( m, n )
 
dim as long i
dim as Str255 testStr( 5, 2 )
 
testStr( 0, 0 ) = "kitten" : testStr( 0, 1 ) = "sitting"
testStr( 1, 0 ) = "rosettacode" : testStr( 1, 1 ) = "raisethysword"
testStr( 2, 0 ) = "Saturday" : testStr( 2, 1 ) = "Sunday"
testStr( 3, 0 ) = "FutureBasic" : testStr( 3, 1 ) = "FutureBasic"
testStr( 4, 0 ) = "here's a bunch of words"
testStr( 4, 1 ) = "to wring out this code"
 
for i = 0 to 46
print @"1st string = "; testStr( i, 0 )
print @"2nd string = "; testStr( i, 1 )
print @"Levenshtein distance = "; fn LevenshteinDistance( testStr( i, 0 ), testStr( i, 1 ) )
print
next
</lang>
 
HandleEvents
Output:
</syntaxhighlight>
 
{{output}}
<pre>
1st string = kitten
Line 1,931 ⟶ 2,271:
Levenshtein distance = 0
 
1st string = here's a bunch of wordsrave
2nd string = to wring out this coderavel
Levenshtein distance = 181
 
1st string = black
2nd string = slack
Levenshtein distance = 1
 
1st string = rave
2nd string = grave
Levenshtein distance = 1
</pre>
 
=={{header|Go}}==
WP algorithm:
<langsyntaxhighlight lang="go">package main
 
import "fmt"
Line 1,975 ⟶ 2,323:
}
return d[len(s)][len(t)]
}</langsyntaxhighlight>
{{out}}
<pre>
Line 1,981 ⟶ 2,329:
</pre>
{{trans|C}}
<langsyntaxhighlight lang="go">package main
 
import "fmt"
Line 2,004 ⟶ 2,352:
fmt.Printf("distance between %s and %s: %d\n", s1, s2,
levenshtein(s1, s2))
}</langsyntaxhighlight>
{{out}}
<pre>
Line 2,011 ⟶ 2,359:
 
=={{header|Groovy}}==
<langsyntaxhighlight lang="groovy">def distance(String str1, String str2) {
def dist = new int[str1.size() + 1][str2.size() + 1]
(0..str1.size()).each { dist[it][0] = it }
Line 2,029 ⟶ 2,377:
println "Checking distance(${key[0]}, ${key[1]}) == $dist"
assert distance(key[0], key[1]) == dist
}</langsyntaxhighlight>
{{out}}
<pre>
Line 2,038 ⟶ 2,386:
 
=={{header|Haskell}}==
 
<lang haskell>levenshtein :: Eq a => [a] -> [a] -> Int
===Implementation 1===
<syntaxhighlight lang="haskell">levenshtein :: Eq a => [a] -> [a] -> Int
levenshtein s1 s2 = last $ foldl transform [0 .. length s1] s2
where
Line 2,046 ⟶ 2,396:
 
main :: IO ()
main = print (levenshtein "kitten" "sitting")</langsyntaxhighlight>
{{Out}}
<pre>3</pre>
 
===Implementation 2===
<syntaxhighlight lang="haskell">levenshtein :: Eq a => [a] -> [a] -> Int
levenshtein s1 [] = length s1
levenshtein [] s2 = length s2
levenshtein s1@(s1Head:s1Tail) s2@(s2Head:s2Tail)
| s1Head == s2Head = levenshtein s1Tail s2Tail
| otherwise = 1 + minimum [score1, score2, score3]
where score1 = levenshtein s1Tail s2Tail
score2 = levenshtein s1 s2Tail
score3 = levenshtein s1Tail s2
 
main :: IO ()
main = print (levenshtein "kitten" "sitting")</syntaxhighlight>
{{Out}}
<pre>3</pre>
 
=={{header|Icon}} and {{header|Unicon}}==
<langsyntaxhighlight lang="unicon">procedure main()
every process(!&input)
end
Line 2,071 ⟶ 2,437:
 
return d[n,m]-1
end</langsyntaxhighlight>
{{out|Example}}
<pre>
Line 2,082 ⟶ 2,448:
=={{header|Io}}==
A <code>levenshtein</code> method is available on strings when the standard <code>Range</code> addon is loaded.
<syntaxhighlight lang="text">Io 20110905
Io> Range ; "kitten" levenshtein("sitting")
==> 3
Io> "rosettacode" levenshtein("raisethysword")
==> 8
Io> </langsyntaxhighlight>
 
=={{header|IS-BASIC}}==
<syntaxhighlight lang="is-basic">100 PROGRAM "Levensht.bas"
110 LET S1$="kitten":LET S2$="sitting"
120 PRINT "The Levenshtein distance between """;S1$;""" and """;S2$;""" is:";LEVDIST(S1$,S2$)
130 DEF LEVDIST(S$,T$)
140 LET N=LEN(T$):LET M=LEN(S$)
150 NUMERIC D(0 TO M,0 TO N)
160 FOR I=0 TO M
170 LET D(I,0)=I
180 NEXT
190 FOR J=0 TO N
200 LET D(0,J)=J
210 NEXT
220 FOR J=1 TO N
230 FOR I=1 TO M
240 IF S$(I)=T$(J) THEN
250 LET D(I,J)=D(I-1,J-1)
260 ELSE
270 LET D(I,J)=MIN(D(I-1,J)+1,MIN(D(I,J-1)+1,D(I-1,J-1)+1))
280 END IF
290 NEXT
300 NEXT
310 LET LEVDIST=D(M,N)
320 END DEF</syntaxhighlight>
 
=={{header|J}}==
One approach would be a literal transcription of the [[wp:Levenshtein_distance#Computing_Levenshtein_distance|wikipedia implementation]]:
<langsyntaxhighlight lang="j">levenshtein=:4 :0
D=. x +/&i.&>:&# y
for_i.1+i.#x do.
Line 2,104 ⟶ 2,495:
end.
{:{:D
)</langsyntaxhighlight>
 
However, this is a rather slow and bulky approach. Another alternative would be:
<lang j>levD=: i.@-@>:@#@] ,~ >:@i.@-@#@[ ,.~ ~:/
lev=: [: {. {."1@((1&{ ,~ (1 1 , {.) <./@:+ }.)@,/\.)@,./@levD</lang>
First, we setup up an matrix of costs, with 0 or 1 for unexplored cells (1 being where the character pair corresponding to that cell position has two different characters). Note that the "cost to reach the empty string" cells go on the bottom and the right, instead of the top and the left, because this works better with J's "[http://www.jsoftware.com/help/dictionary/d420.htm insert]" operation (which we will call "reduce" in the next paragraph here. It could also be thought of as a right fold which has been constrained such the initial value is the identity value for the operation. Or, just think of it as inserting its operation between each item of its argument...).
 
Then we reduce the rows of that matrix using an operation that treats those two rows as columns and reduces the rows of this derived matrix with an operation that gives the (unexplored cell + the minumum of the other cells) followed by (the cell adjacent to the previously unexplored cell.
 
However, this is a rather slow and bulky approach.
 
We can also do the usual optimization where we only represent one row of the distance matrix at a time:
 
<syntaxhighlight lang="j">levdist =:4 :0
'a b'=. (x;y) /: (#x),(#y)
D=. >: iz =. i.#b
for_j. a do.
D=. <./\&.(-&iz) (>: D) <. (j ~: b) + |.!.j_index D
end.
{:D
)</syntaxhighlight>
{{out|Example use}}
<langsyntaxhighlight lang="j"> 'kitten' levenshtein 'sitting'
3
'kitten' levlevdist 'sitting'
3</langsyntaxhighlight>
Time and space use:
<syntaxhighlight lang="j">
<lang j> ts=: 6!:2,7!:2
tstimespacex '''kitten'' levenshtein ''sitting'''
0.000113 6016
0.00153132 12800
tstimespacex '''kitten'' levlevdist ''sitting'''
1.5e_5 4416</syntaxhighlight>
0.000132101 5376</lang>
(TheSo Jthe flavoredlevdist variantimplementation winds up beingis about 107 times faster, in J, for this testexample (which approximately corresponds to the case,length thanof the explicitshortest version.string)
 
See the [[j:Essays/Levenshtein Distance|Levenshtein distance essay]] on the Jwiki for additional solutions.
 
=={{header|Java}}==
Based on the definition for Levenshtein distance given in the Wikipedia article:
<langsyntaxhighlight lang="java">public class Levenshtein {
 
public static int distance(String a, String b) {
Line 2,155 ⟶ 2,556:
System.out.println("distance(" + data[i] + ", " + data[i+1] + ") = " + distance(data[i], data[i+1]));
}
}</langsyntaxhighlight>
{{out}}
<pre>distance(kitten, sitting) = 3
Line 2,162 ⟶ 2,563:
</pre>
{{trans|C}}
<langsyntaxhighlight lang="java">public class Levenshtein{
public static int levenshtein(String s, String t){
/* if either string is empty, difference is inserting all chars
Line 2,207 ⟶ 2,608:
+ levenshtein(sb1.reverse().toString(), sb2.reverse().toString()));
}
}</langsyntaxhighlight>
{{out}}
<pre>distance between 'kitten' and 'sitting': 3
Line 2,215 ⟶ 2,616:
===Iterative space optimized (even bounded) ===
{{trans|Python}}
<langsyntaxhighlight lang="java">
import static java.lang.Math.abs;
import static java.lang.Math.max;
Line 2,241 ⟶ 2,642:
int[] cost = new int[lb+1];
for (int i=0; i<=lb; i+=1) {
cost[i] = i;
}
 
for (int i=1; i<=la; i+=1) {
cost[0] = i;
Line 2,285 ⟶ 2,690:
}
}
</syntaxhighlight>
</lang>
{{out}}
<pre>
Line 2,295 ⟶ 2,700:
===ES5===
Iterative:
<langsyntaxhighlight lang="javascript">function levenshtein(a, b) {
var t = [], u, i, j, m = a.length, n = b.length;
if (!m) { return n; }
Line 2,325 ⟶ 2,730:
console.log('levenstein("' + a + '","' + b + '") was ' + d + ' should be ' + t);
}
});</langsyntaxhighlight>
 
===ES6===
Line 2,331 ⟶ 2,736:
 
By composition of generic functions:
<langsyntaxhighlight JavaScriptlang="javascript">(() => {
'use strict';
 
// levenshtein :: String -> String -> Int
const levenshtein = (sa, => sb) => {
const [s1, s2]cs = [chars(sa.split(''), sb.split('')];
const go = (ns, c) => {
 
return last(s2.reduce((ns, c) const calc = z => tpl => {
const [nc1, x, ns1y] = unconsArray.from(nstpl);
return minimum([
 
return scanl succ(y),
(z, [c1, x, y] succ(z) =>,
minimum x + (c !== c1 ? 1 : 0)
[y + 1, z + 1, x + fromEnum(c1 != c)]);
),};
const [n, ns1] = n +[ns[0], ns.slice(1,)];
return zip3scanl(s1, ns, ns1calc)(succ(n))(
zip3(cs)(ns)(ns1)
);
}, range(0, s1.length)));
return last(
chars(sb).reduce(
go,
enumFromTo(0)(cs.length)
)
);
};
 
// ----------------------- TEST ------------------------
const main = () => [
["kitten", "sitting"],
["sitting", "kitten"],
["rosettacode", "raisethysword"],
["raisethysword", "rosettacode"]
].map(uncurry(levenshtein));
 
/*********************************************************************/
// GENERIC FUNCTIONS
 
// ----------------- GENERIC FUNCTIONS -----------------
// minimum :: [a] -> a
const minimum = xs =>
xs.reduce((a, x) => (x < a || a === undefined ? x : a), undefined);
 
// fromEnumTuple (,) :: Enum a =-> ab -> Int(a, b)
const fromEnumTuple = xa => {
const typeb => typeof x;({
return type === 'boolean' ?type: ('Tuple',
x ? 1 '0': 0a,
) : (type === 'string1' ? x.charCodeAt(0) : undefined);b,
length: 2
};
});
 
// uncons :: [a] -> Maybe (a, [a])
const uncons = xs => xs.length ? [xs[0], xs.slice(1)] : undefined;
 
// scanlTupleN :: (b -> a -> b) ->... b -> [(a], ->b [b]... )
const scanl =function TupleN(f, a, xs) => {
const
for (var lst = [a], lng = xs.length, i = 0; i < lng; i++) {
aargs = fArray.from(a, xs[i], i, xsarguments), lst.push(a);
} n = args.length;
return lst;2 < n ? Object.assign(
args.reduce((a, x, i) => Object.assign(a, {
[i]: x
}), {
type: 'Tuple' + n.toString(),
length: n
})
) : args.reduce((f, x) => f(x), Tuple);
};
 
// zip3 :: [a] -> [b] -> [c] -> [(a,b,c)]
const zip3 = (xs, ys, zs) =>
xs.slice(0, Math.min(xs.length, ys.length, zs.length))
.map((x, i) => [x, ys[i], zs[i]]);
 
// lastchars :: [a]String -> a[Char]
const lastchars = xss => xs.length ? xs.slice(-1) : undefined;
s.split('');
 
 
// rangeenumFromTo :: Int -> Int -> [Int]
const rangeenumFromTo = (m, n) =>
n => Array.from({
length: Math.floor(1 + n - m) + 1
}, (_, i) => m + i);
 
/*********************************************************************/
// TEST
return [
["kitten", "sitting"],
["sitting", "kitten"],
["rosettacode", "raisethysword"],
["raisethysword", "rosettacode"]
].map(pair => levenshtein.apply(null, pair));
 
// ->last :: [3,a] 3,-> 8, 8]a
const last = xs => (
})();</lang>
// The last item of a list.
ys => 0 < ys.length ? (
ys.slice(-1)[0]
) : undefined
)(xs);
 
 
// minimum :: Ord a => [a] -> a
const minimum = xs => (
// The least value of xs.
ys => 0 < ys.length ? (
ys.slice(1)
.reduce((a, y) => y < a ? y : a, ys[0])
) : undefined
)(xs);
 
 
// length :: [a] -> Int
const length = xs =>
// Returns Infinity over objects without finite
// length. This enables zip and zipWith to choose
// the shorter argument when one is non-finite,
// like cycle, repeat etc
'GeneratorFunction' !== xs.constructor.constructor.name ? (
xs.length
) : Infinity;
 
 
// scanl :: (b -> a -> b) -> b -> [a] -> [b]
const scanl = f => startValue => xs =>
xs.reduce((a, x) => {
const v = f(a[0])(x);
return Tuple(v)(a[1].concat(v));
}, Tuple(startValue)([startValue]))[1];
 
 
// succ :: Enum a => a -> a
const succ = x =>
1 + x;
 
 
// uncurry :: (a -> b -> c) -> ((a, b) -> c)
const uncurry = f =>
// A function over a pair, derived
// from a curried function.
function () {
const
args = arguments,
xy = Boolean(args.length % 2) ? (
args[0]
) : args;
return f(xy[0])(xy[1]);
};
 
 
// zip3 :: [a] -> [b] -> [c] -> [(a, b, c)]
const zip3 = xs =>
ys => zs => xs
.slice(0, Math.min(...[xs, ys, zs].map(length)))
.map((x, i) => TupleN(x, ys[i], zs[i]));
 
// MAIN ---
return JSON.stringify(main())
})();</syntaxhighlight>
{{Out}}
<lang JavaScriptpre>[3, 3, 8, 8]</langpre>
 
=={{header|jq}}==
{{works with|jq}}
'''Works with gojq, the Go implementation of jq'''
 
The main point of interest about the following implementation is that it shows how the naive recursive algorithm can be tweaked within a completely functional framework to yield an efficient implementation.
 
Line 2,418 ⟶ 2,895:
67ms for rosettacode/raisethysword
71ms for edocattesor/drowsyhtesiar
<syntaxhighlight lang="jq">
<lang jq>
# lookup the distance between s and t in the nested cache,
# which uses basic properties of the Levenshtein distance to save space:
Line 2,469 ⟶ 2,946:
 
def levenshteinDistance(s;t):
s as $s | t as $t | {} | ld($s;$t) | .[0];</langsyntaxhighlight>
'''Task'''
<langsyntaxhighlight lang="jq">def demo:
"levenshteinDistance between \(.[0]) and \(.[1]) is \( levenshteinDistance(.[0]; .[1]) )";
Line 2,478 ⟶ 2,955:
(["edocattesor", "drowsyhtesiar"] | demo),
(["this_algorithm_is_similar_to",
"Damerau-Levenshtein_distance"] | demo)</langsyntaxhighlight>
{{Out}}
levenshteinDistance between kitten and sitting is 3
levenshteinDistance between rosettacode and raisethysword is 8
levenshteinDistance between edocattesor and drowsyhtesiar is 8
levenshteinDistance between this_algorithm_is_similar_to and Damerau-Levenshtein_distance is 24
 
=={{header|Jsish}}==
From Javascript, ES5 entry.
<langsyntaxhighlight lang="javascript">/* Levenshtein Distance, in Jsish */
 
function levenshtein(a, b) {
Line 2,530 ⟶ 3,008:
levenshtein('mississippi', 'swiss miss') ==> 8
=!EXPECTEND!=
*/</langsyntaxhighlight>
{{out}}
<pre>prompt$ jsish -u levenshtein.jsi
Line 2,539 ⟶ 3,017:
'''Recursive''':
{{works with|Julia|1.0}}
<langsyntaxhighlight lang="julia">function levendist(s::AbstractString, t::AbstractString)
ls, lt = length.((s, t))
ls == 0 && return lt
Line 2,550 ⟶ 3,028:
 
@show levendist("kitten", "sitting") # 3
@show levendist("rosettacode", "raisethysword") # 8</langsyntaxhighlight>
 
'''Iterative''':
{{works with|Julia|0.6}}
<langsyntaxhighlight lang="julia">function levendist1(s::AbstractString, t::AbstractString)
ls, lt = length(s), length(t)
if ls > lt
Line 2,574 ⟶ 3,052:
end
return dist[end]
end</langsyntaxhighlight>
 
Let's see some benchmark:
<langsyntaxhighlight lang="julia">using BenchmarkTools
println("\n# levendist(kitten, sitting)")
s, t = "kitten", "sitting"
Line 2,589 ⟶ 3,067:
@btime levendist(s, t)
println(" - Iterative:")
@btime levendist1(s, t)</langsyntaxhighlight>
 
{{out}}
Line 2,607 ⟶ 3,085:
=={{header|Kotlin}}==
===Standard Version===
<langsyntaxhighlight lang="scala">// version 1.0.6
 
// Uses the "iterative with two matrix rows" algorithm referred to in the Wikipedia article.
Line 2,639 ⟶ 3,117:
println("'rosettacode' to 'raisethysword' => ${levenshtein("rosettacode", "raisethysword")}")
println("'sleep' to 'fleeting' => ${levenshtein("sleep", "fleeting")}")
}</langsyntaxhighlight>
 
{{out}}
Line 2,649 ⟶ 3,127:
 
===Functional/Folding Version===
<langsyntaxhighlight lang="scala">
fun levenshtein(s: String, t: String,
charScore : (Char, Char) -> Int = { c1, c2 -> if (c1 == c2) 0 else 1}) : Int {
Line 2,669 ⟶ 3,147:
 
}
</syntaxhighlight>
</lang>
{{out}}
<pre>
Line 2,683 ⟶ 3,161:
Suitable for short strings:
 
<langsyntaxhighlight lang="lisp">
(defun levenshtein-simple
(('() str)
Line 2,697 ⟶ 3,175:
(levenshtein-simple str1-tail str2)
(levenshtein-simple str1-tail str2-tail))))))
</syntaxhighlight>
</lang>
 
You can copy and paste that function into an LFE REPL and run it like so:
 
<langsyntaxhighlight lang="lisp">
> (levenshtein-simple "a" "a")
0
Line 2,710 ⟶ 3,188:
> (levenshtein-simple "kitten" "sitting")
3
</syntaxhighlight>
</lang>
 
It is not recommended to test strings longer than the last example using this implementation, as performance quickly degrades.
Line 2,716 ⟶ 3,194:
=== Cached Implementation ===
 
<langsyntaxhighlight lang="lisp">
(defun levenshtein-distance (str1 str2)
(let (((tuple distance _) (levenshtein-distance
Line 2,743 ⟶ 3,221:
(len (+ 1 (lists:min (list l1 l2 l3)))))
(tuple len (dict:store (tuple str1 str2) len c3)))))))
</syntaxhighlight>
</lang>
 
As before, here's some usage in the REPL. Note that longer strings are now possible to compare without incurring long execution times:
 
<langsyntaxhighlight lang="lisp">
> (levenshtein-distance "a" "a")
0
Line 2,758 ⟶ 3,236:
> (levenshtein-distance "rosettacode" "raisethysword")
8
</syntaxhighlight>
</lang>
 
=={{header|Liberty BASIC}}==
<langsyntaxhighlight lang="lb">'Levenshtein Distance translated by Brandon Parker
'08/19/10
'from http://www.merriampark.com/ld.htm#VB
Line 2,806 ⟶ 3,284:
Next i
LevenshteinDistance = d(n, m)
End Function </langsyntaxhighlight>
 
=={{header|Limbo}}==
{{trans|Go}}
<langsyntaxhighlight lang="limbo">implement Levenshtein;
 
include "sys.m"; sys: Sys;
Line 2,857 ⟶ 3,335:
return a + 1;
}
</syntaxhighlight>
</lang>
 
{{outputout}}
<codepre>
% levenshtein kitten sitting rosettacode raisethysword
kitten <-> sitting => 3
rosettacode <-> raisethysword => 8
</codepre>
 
=={{header|LiveCode}}==
{{trans|Go}}
<syntaxhighlight lang="livecode">
<lang LiveCode>
//Code By Neurox66
function Levenshtein pString1 pString2
Line 2,892 ⟶ 3,370:
put Levenshtein("kitten","sitting")
put Levenshtein("rosettacode","raisethysword")
</syntaxhighlight>
</lang>
{{out}}
<pre>3
Line 2,899 ⟶ 3,377:
=={{header|Lobster}}==
{{trans|C}}
<langsyntaxhighlight Lobsterlang="lobster">def levenshtein(s: string, t: string) -> int:
 
def makeNxM(n: int, m: int, v: int) -> [[int]]:
Line 2,934 ⟶ 3,412:
 
assert 3 == levenshtein("kitten", "sitting")
assert 8 == levenshtein("rosettacode", "raisethysword")</langsyntaxhighlight>
 
=={{header|Lua}}==
<langsyntaxhighlight lang="lua">function leven(s,t)
if s == '' then return t:len() end
if t == '' then return s:len() end
Line 2,956 ⟶ 3,434:
 
print(leven("kitten", "sitting"))
print(leven("rosettacode", "raisethysword"))</langsyntaxhighlight>
{{out}}
<pre>3
Line 2,962 ⟶ 3,440:
 
=={{header|M2000 Interpreter}}==
<syntaxhighlight lang="m2000 interpreter">
<lang M2000 Interpreter>
Module Checkit {
\\ Iterative with two matrix rows
Line 3,029 ⟶ 3,507:
}
Checkit2
</syntaxhighlight>
</lang>
 
=={{header|Maple}}==
<syntaxhighlight lang="maple">
<lang Maple>
> with(StringTools):
> Levenshtein("kitten","sitting");
Line 3,039 ⟶ 3,517:
> Levenshtein("rosettacode","raisethysword");
8
</syntaxhighlight>
</lang>
 
=={{header|Mathematica}}/{{header|Wolfram Language}}==
<langsyntaxhighlight Mathematicalang="mathematica">EditDistance["kitten","sitting"]
EditDistance["rosettacode","raisethysword"]</syntaxhighlight>
->3
{{out}}
EditDistance["rosettacode","raisethysword"]
<pre>3
->8</lang>
7</pre>
 
=={{header|MATLAB}}==
<syntaxhighlight lang="matlab">
<lang MATLAB>
function score = levenshtein(s1, s2)
% score = levenshtein(s1, s2)
Line 3,079 ⟶ 3,558:
score = current_row(end);
end
</syntaxhighlight>
</lang>
Source : [https://github.com/benhamner/Metrics/blob/master/MATLAB/metrics/levenshtein.m]
 
=={{header|MiniScript}}==
In the Mini Micro environment, this function is part of the stringUtil library module, and can be used like so:
<syntaxhighlight lang="miniscript">import "stringUtil"
print "kitten".editDistance("sitting")</syntaxhighlight>
 
In environments where the stringUtil module is not available, you'd have to define it yourself:
<syntaxhighlight lang="miniscript">string.editDistance = function(s2)
n = self.len
m = s2.len
if n == 0 then return m
if m == 0 then return n
s1chars = self.split("")
s2chars = s2.split("")
d = range(0, m)
lastCost = 0
for i in range(1, n)
s1char = s1chars[i-1]
lastCost = i
jMinus1 = 0
for j in range(1, m)
if s1char == s2chars[jMinus1] then cost = 0 else cost = 1
// set nextCost to the minimum of the following three possibilities:
a = d[j] + 1
b = lastCost + 1
c = cost + d[jMinus1]
if a < b then
if c < a then nextCost = c else nextCost = a
else
if c < b then nextCost = c else nextCost = b
end if
d[jMinus1] = lastCost
lastCost = nextCost
jMinus1 = j
end for
d[m] = lastCost
end for
return nextCost
end function
 
print "kitten".editDistance("sitting")</syntaxhighlight>
 
{{out}}
<pre>3</pre>
 
=={{header|Modula-2}}==
<syntaxhighlight lang="modula2">MODULE LevenshteinDistance;
FROM InOut IMPORT WriteString, WriteCard, WriteLn;
FROM Strings IMPORT Length;
 
PROCEDURE levenshtein(s, t: ARRAY OF CHAR): CARDINAL;
CONST MaxLen = 15;
VAR d: ARRAY [0..MaxLen],[0..MaxLen] OF CARDINAL;
lenS, lenT, i, j: CARDINAL;
PROCEDURE min(a, b: CARDINAL): CARDINAL;
BEGIN
IF a<b THEN RETURN a;
ELSE RETURN b;
END;
END min;
BEGIN
lenS := Length(s);
lenT := Length(t);
IF lenS = 0 THEN RETURN lenT;
ELSIF lenT = 0 THEN RETURN lenS;
ELSE
FOR i := 0 TO lenS DO d[i,0] := i; END;
FOR j := 0 TO lenT DO d[0,j] := j; END;
FOR i := 1 TO lenS DO
FOR j := 1 TO lenT DO
IF s[i-1] = t[j-1] THEN
d[i,j] := d[i-1,j-1];
ELSE
d[i,j] :=
min(d[i-1,j] + 1,
min(d[i,j-1] + 1, d[i-1,j-1]+1));
END;
END;
END;
RETURN d[lenS,lenT];
END;
END levenshtein;
 
PROCEDURE ShowDistance(s, t: ARRAY OF CHAR);
BEGIN
WriteString(s);
WriteString(" -> ");
WriteString(t);
WriteString(": ");
WriteCard(levenshtein(s, t), 0);
WriteLn();
END ShowDistance;
 
BEGIN
ShowDistance("kitten", "sitting");
ShowDistance("rosettacode", "raisethysword");
END LevenshteinDistance.</syntaxhighlight>
{{out}}
<pre>kitten -> sitting: 3
rosettacode -> raisethysword: 8</pre>
 
=={{header|NetRexx}}==
{{trans|ooRexx}}
<langsyntaxhighlight NetRexxlang="netrexx">/* NetRexx */
options replace format comments java crossref symbols nobinary
 
Line 3,136 ⟶ 3,723:
 
return d[m + 1, n + 1]
</syntaxhighlight>
</lang>
'''Output:'''
<pre>
Line 3,144 ⟶ 3,731:
 
=={{header|Nim}}==
Nim provides a function in module "std/editdistance" to compute the Levenshtein distance between two strings containing ASCII characters only or containing UTF-8 encoded Unicode runes.
<lang nim>import strutils
<syntaxhighlight lang="nim">import std/editdistance
 
echo editDistanceeditDistanceAscii("kitten", "sitting")
echo editDistanceeditDistanceAscii("rosettacode", "raisethysword")</langsyntaxhighlight>
 
{{out}}
Line 3,154 ⟶ 3,742:
 
{{trans|Python}}
Here is a translation of the Python version.
<lang nim>import sequtils
<syntaxhighlight lang="nim">import sequtils
 
func min(a, b, c: int): int {.inline.} = min(a, min(b, c))
proc levenshteinDistance(s1, s2): int =
 
proc levenshteinDistance(s1, s2: string): int =
var (s1, s2) = (s1, s2)
 
Line 3,170 ⟶ 3,761:
newDistances.add(distances[i1])
else:
newDistances.add(1 + min(distances[i1], distances[i1+1], newDistances[newDistances.high]))
newDistances[newDistances.high]))
 
distances = newDistances
Line 3,177 ⟶ 3,767:
 
echo levenshteinDistance("kitten","sitting")
echo levenshteinDistance("rosettacode","raisethysword")</langsyntaxhighlight>
 
=={{header|Oberon-2}}==
{{trans|Modula-2}}
<syntaxhighlight lang="oberon2">MODULE LevesteinDistance;
 
IMPORT Out,Strings;
PROCEDURE Levestein(s,t:ARRAY OF CHAR):LONGINT;
CONST
maxlen = 15;
VAR
d:ARRAY maxlen,maxlen OF LONGINT;
lens,lent,i,j:LONGINT;
PROCEDURE Min(a,b:LONGINT):LONGINT;
BEGIN
IF a < b THEN RETURN a ELSE RETURN b END
END Min;
BEGIN
lens := Strings.Length(s);
lent := Strings.Length(t);
IF lens = 0 THEN RETURN lent
ELSIF lent = 0 THEN RETURN lens
ELSE
FOR i := 0 TO lens DO d[i,0] := i END;
FOR j := 0 TO lent DO d[0,j] := j END;
FOR i := 1 TO lens DO
FOR j := 1 TO lent DO
IF s[i-1] = t[j-1] THEN
d[i,j] := d[i-1,j-1]
ELSE
d[i,j] := Min((d[i-1,j] + 1),
Min(d[i,j-1] + 1, d[i-1,j-1] + 1));
END
END
END
END;
RETURN d[lens,lent];
END Levestein;
 
PROCEDURE ShowDistance(s,t:ARRAY OF CHAR);
BEGIN
Out.String(s);
Out.String(" -> ");
Out.String(t);
Out.String(": ");
Out.Int(Levestein(s,t),0);
Out.Ln
END ShowDistance;
BEGIN
ShowDistance("kitten", "sitting");
ShowDistance("rosettacode", "raisethysword");
END LevesteinDistance.
</syntaxhighlight>
 
{{out}}
<pre>kitten -> sitting: 3
rosettacode -> raisethysword: 8
</pre>
 
=={{header|Objeck}}==
{{trans|C#}}
<langsyntaxhighlight lang="objeck">class Levenshtein {
function : Main(args : String[]) ~ Nil {
if(args->Size() = 2) {
Line 3,214 ⟶ 3,865:
return d[s->Size(), t->Size()];
}
}</langsyntaxhighlight>
 
=={{header|Objective-C}}==
Translation of the C# code into a NSString category
<langsyntaxhighlight lang="objc">@interface NSString (levenshteinDistance)
- (NSUInteger)levenshteinDistanceToString:(NSString *)string;
@end
Line 3,252 ⟶ 3,903:
return r;
}
@end</langsyntaxhighlight>
 
=={{header|OCaml}}==
Translation of the pseudo-code of the Wikipedia article:
<langsyntaxhighlight lang="ocaml">let minimum a b c =
min a (min b c)
 
Line 3,296 ⟶ 3,947:
test "kitten" "sitting";
test "rosettacode" "raisethysword";
;;</langsyntaxhighlight>
=== A recursive functional version ===
This could be made faster with memoization
<langsyntaxhighlight OCamllang="ocaml">let levenshtein s t =
let rec dist i j = match (i,j) with
| (i,0) -> i
Line 3,315 ⟶ 3,966:
let () =
test "kitten" "sitting";
test "rosettacode" "raisethysword";</langsyntaxhighlight>
{{out}}
<pre>
Line 3,323 ⟶ 3,974:
 
=={{header|ooRexx}}==
<syntaxhighlight lang="oorexx">
<lang ooRexx>
say "kitten -> sitting:" levenshteinDistance("kitten", "sitting")
say "rosettacode -> raisethysword:" levenshteinDistance("rosettacode", "raisethysword")
Line 3,370 ⟶ 4,021:
 
return d[m + 1, n + 1 ]
</syntaxhighlight>
</lang>
Output:
<pre>
Line 3,380 ⟶ 4,031:
{{trans|JavaScript}}
{{Works with|PARI/GP|2.7.4 and above}}
<langsyntaxhighlight lang="parigp">
\\ Levenshtein distance between two words
\\ 6/21/16 aev
Line 3,404 ⟶ 4,055:
levensDist("X","oX");
}
</langsyntaxhighlight>
{{Output}}
Line 3,418 ⟶ 4,069:
=={{header|Pascal}}==
A fairly direct translation of the wikipedia pseudo code:
<langsyntaxhighlight lang="pascal">Program LevenshteinDistanceDemo(output);
 
uses
Line 3,455 ⟶ 4,106:
s2 := 'raisethysword';
writeln('The Levenshtein distance between "', s1, '" and "', s2, '" is: ', LevenshteinDistance(s1, s2));
end.</langsyntaxhighlight>
{{out}}
<pre>
Line 3,464 ⟶ 4,115:
=={{header|Perl}}==
Recursive algorithm, as in the C sample. You are invited to comment out the line where it says so, and see the speed difference. By the way, there's the <code>Memoize</code> standard module, but it requires setting quite a few parameters to work right for this example, so I'm just showing the simple minded caching scheme here.
<langsyntaxhighlight Perllang="perl">use List::Util qw(min);
 
my %cache;
Line 3,488 ⟶ 4,139:
}
 
print leven('rosettacode', 'raisethysword'), "\n";</langsyntaxhighlight>
 
Iterative solution:
 
<langsyntaxhighlight lang="perl">use List::Util qw(min);
 
sub leven {
Line 3,514 ⟶ 4,165:
}
 
print leven('rosettacode', 'raisethysword'), "\n";</langsyntaxhighlight>
 
=={{header|Phix}}==
<!--<syntaxhighlight lang="phix">(phixonline)-->
Copy of [[Levenshtein_distance#Euphoria|Euphoria]]
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span>
<lang Phix>function levenshtein(sequence s1, sequence s2)
integer n = length(s1)+1,
<span style="color: #7060A8;">requires</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"0.8.2"</span><span style="color: #0000FF;">)</span> <span style="color: #000080;font-style:italic;">-- (just the use of papply() at the end)</span>
m = length(s2)+1
sequence d
<span style="color: #008080;">function</span> <span style="color: #000000;">levenshtein</span><span style="color: #0000FF;">(</span><span style="color: #004080;">string</span> <span style="color: #000000;">a</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">b</span><span style="color: #0000FF;">)</span>
 
<span style="color: #004080;">integer</span> <span style="color: #000000;">n</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">a</span><span style="color: #0000FF;">),</span>
if n=1 then
<span style="color: #000000;">m</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">b</span><span style="color: #0000FF;">)</span>
return m-1
<span style="color: #008080;">if</span> <span style="color: #000000;">n</span><span style="color: #0000FF;">=</span><span style="color: #000000;">0</span> <span style="color: #008080;">then</span> <span style="color: #008080;">return</span> <span style="color: #000000;">m</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
elsif m=1 then
<span style="color: #008080;">if</span> <span style="color: #000000;">m</span><span style="color: #0000FF;">=</span><span style="color: #000000;">0</span> <span style="color: #008080;">then</span> <span style="color: #008080;">return</span> <span style="color: #000000;">n</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
return n-1
<span style="color: #004080;">sequence</span> <span style="color: #000000;">d</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">(</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">m</span><span style="color: #0000FF;">+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">),</span> <span style="color: #000000;">n</span><span style="color: #0000FF;">+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">)</span>
end if
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">n</span> <span style="color: #008080;">do</span>
 
<span style="color: #000000;">d</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">][</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">i</span>
d = repeat(repeat(0, m), n)
<span style="color: #008080;">for</span> <span style="color: #000000;">j</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">m</span> <span style="color: #008080;">do</span>
for i=1 to n do
<span style="color: #000000;">d</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">][</span><span style="color: #000000;">j</span><span style="color: #0000FF;">+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">j</span>
d[i][1] = i-1
<span style="color: #000080;font-style:italic;">-- next := min({ prev +substitution, deletion, or insertion }):</span>
end for
<span style="color: #000000;">d</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">][</span><span style="color: #000000;">j</span><span style="color: #0000FF;">+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">min</span><span style="color: #0000FF;">({</span><span style="color: #000000;">d</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">][</span><span style="color: #000000;">j</span><span style="color: #0000FF;">]+(</span><span style="color: #000000;">a</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]!=</span><span style="color: #000000;">b</span><span style="color: #0000FF;">[</span><span style="color: #000000;">j</span><span style="color: #0000FF;">]),</span> <span style="color: #000000;">d</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">][</span><span style="color: #000000;">j</span><span style="color: #0000FF;">+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">d</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">][</span><span style="color: #000000;">j</span><span style="color: #0000FF;">]+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">})</span>
 
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
for j=1 to m do
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
d[1][j] = j-1
<span style="color: #008080;">return</span> <span style="color: #000000;">d</span><span style="color: #0000FF;">[$][$]</span>
end for
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
 
for i=2 to n do
<span style="color: #008080;">procedure</span> <span style="color: #000000;">test</span><span style="color: #0000FF;">(</span><span style="color: #004080;">string</span> <span style="color: #000000;">s1</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">s2</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">integer</span> <span style="color: #000000;">expected</span><span style="color: #0000FF;">)</span>
for j=2 to m do
<span style="color: #004080;">integer</span> <span style="color: #000000;">actual</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">levenshtein</span><span style="color: #0000FF;">(</span><span style="color: #000000;">s1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">s2</span><span style="color: #0000FF;">)</span>
d[i][j] = min({
<span style="color: #008080;">if</span> <span style="color: #000000;">actual</span><span style="color: #0000FF;">!=</span><span style="color: #000000;">expected</span>
d[i-1][j]+1,
<span style="color: #008080;">or</span> <span style="color: #000000;">actual</span><span style="color: #0000FF;">!=</span><span style="color: #000000;">levenshtein</span><span style="color: #0000FF;">(</span><span style="color: #000000;">s2</span><span style="color: #0000FF;">,</span><span style="color: #000000;">s1</span><span style="color: #0000FF;">)</span>
d[i][j-1]+1,
<span style="color: #008080;">or</span> <span style="color: #000000;">actual</span><span style="color: #0000FF;">!=</span><span style="color: #000000;">levenshtein</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">reverse</span><span style="color: #0000FF;">(</span><span style="color: #000000;">s1</span><span style="color: #0000FF;">),</span><span style="color: #7060A8;">reverse</span><span style="color: #0000FF;">(</span><span style="color: #000000;">s2</span><span style="color: #0000FF;">))</span>
d[i-1][j-1]+(s1[i-1]!=s2[j-1])
<span style="color: #008080;">or</span> <span style="color: #000000;">actual</span><span style="color: #0000FF;">!=</span><span style="color: #000000;">levenshtein</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">reverse</span><span style="color: #0000FF;">(</span><span style="color: #000000;">s2</span><span style="color: #0000FF;">),</span><span style="color: #7060A8;">reverse</span><span style="color: #0000FF;">(</span><span style="color: #000000;">s1</span><span style="color: #0000FF;">))</span> <span style="color: #008080;">then</span>
})
<span style="color: #7060A8;">crash</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"oh dear..."</span><span style="color: #0000FF;">)</span>
end for
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
end for
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"%14q &lt;== %d ==&gt; %q\n"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">s1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">actual</span><span style="color: #0000FF;">,</span><span style="color: #000000;">s2</span><span style="color: #0000FF;">})</span>
 
<span style="color: #008080;">end</span> <span style="color: #008080;">procedure</span>
return d[n][m]
end function
<span style="color: #008080;">constant</span> <span style="color: #000000;">tests</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{{</span><span style="color: #008000;">"kitten"</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"sitting"</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">3</span><span style="color: #0000FF;">},</span>
 
<span style="color: #0000FF;">{</span><span style="color: #008000;">"rosettacode"</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"raisethysword"</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">8</span><span style="color: #0000FF;">},</span>
?levenshtein("kitten", "sitting")
<span style="color: #0000FF;">{</span><span style="color: #008000;">"abcdefgh"</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"defghabc"</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">6</span><span style="color: #0000FF;">},</span>
?levenshtein("rosettacode", "raisethysword")</lang>
<span style="color: #0000FF;">{</span><span style="color: #008000;">"saturday"</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"sunday"</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">3</span><span style="color: #0000FF;">},</span>
<span style="color: #0000FF;">{</span><span style="color: #008000;">"sleep"</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"fleeting"</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">5</span><span style="color: #0000FF;">},</span>
<span style="color: #0000FF;">{</span><span style="color: #008000;">""</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"four"</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">4</span><span style="color: #0000FF;">},</span>
<span style="color: #0000FF;">{</span><span style="color: #008000;">""</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">""</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">0</span><span style="color: #0000FF;">}}</span>
<span style="color: #7060A8;">papply</span><span style="color: #0000FF;">(</span><span style="color: #004600;">false</span><span style="color: #0000FF;">,</span><span style="color: #000000;">test</span><span style="color: #0000FF;">,</span><span style="color: #000000;">tests</span><span style="color: #0000FF;">)</span>
<!--</syntaxhighlight>-->
{{out}}
<pre>
"kitten" <== 3 ==> "sitting"
3
"rosettacode" <== 8 ==> "raisethysword"
8
"abcdefgh" <== 6 ==> "defghabc"
"saturday" <== 3 ==> "sunday"
"sleep" <== 5 ==> "fleeting"
"" <== 4 ==> "four"
"" <== 0 ==> ""
</pre>
 
=== alternative ===
Modelled after the Processing code, uses a single/smaller array, passes the same tests as above.
<!--<syntaxhighlight lang="phix">(phixonline)-->
<span style="color: #008080;">function</span> <span style="color: #000000;">levenshtein</span><span style="color: #0000FF;">(</span><span style="color: #004080;">string</span> <span style="color: #000000;">a</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">b</span><span style="color: #0000FF;">)</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">costs</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">tagset</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">b</span><span style="color: #0000FF;">)+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">0</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">a</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
<span style="color: #000000;">costs</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">i</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">newcost</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">pj</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">cj</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">j</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">b</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
<span style="color: #000000;">cj</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">costs</span><span style="color: #0000FF;">[</span><span style="color: #000000;">j</span><span style="color: #0000FF;">+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]</span>
<span style="color: #000000;">pj</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">min</span><span style="color: #0000FF;">({</span><span style="color: #000000;">pj</span><span style="color: #0000FF;">+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">cj</span><span style="color: #0000FF;">+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">newcost</span><span style="color: #0000FF;">+(</span><span style="color: #000000;">a</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]!=</span><span style="color: #000000;">b</span><span style="color: #0000FF;">[</span><span style="color: #000000;">j</span><span style="color: #0000FF;">])})</span>
<span style="color: #000000;">costs</span><span style="color: #0000FF;">[</span><span style="color: #000000;">j</span><span style="color: #0000FF;">+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">pj</span>
<span style="color: #000000;">newcost</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">cj</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">return</span> <span style="color: #000000;">costs</span><span style="color: #0000FF;">[$-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<!--</syntaxhighlight>-->
 
=={{header|PHP}}==
<syntaxhighlight lang="php">
<lang PHP>
echo levenshtein('kitten','sitting');
echo levenshtein('rosettacode', 'raisethysword');
</syntaxhighlight>
</lang>
 
{{out}}
<pre>3
8</pre>
 
=={{header|Picat}}==
===Iterative===
Based on the iterative algorithm at Wikipedia. Picat is 1-based so some adjustments are needed.
<syntaxhighlight lang="picat">levenshtein(S,T) = Dist =>
M = 1+S.length,
N = 1+T.length,
D = new_array(M,N),
 
foreach(I in 1..M)
D[I,1] := I-1
end,
foreach(J in 1..N)
D[1,J] := J-1
end,
foreach(J in 2..N, I in 2..M)
if S[I-1] == T[J-1] then
D[I,J] := D[I-1,J-1] % no operation required
else
D[I,J] := min([D[I-1,J ] + 1, % a deletion
D[I ,J-1] + 1, % an insertion
D[I-1,J-1] + 1] % a substitution
)
end
end,
 
Dist = D[M,N].</syntaxhighlight>
 
===Tabled recursive version===
<syntaxhighlight lang="picat">table
levenshtein_rec(S,T) = Dist =>
Dist1 = 0,
if S.length = 0 then Dist1 := T.length
elseif T.length = 0 then Dist1 := S.length
elseif S[1] = T[1] then Dist1 := levenshtein_rec(S.tail(), T.tail())
else
A = levenshtein_rec(S.tail(), T.tail()),
B = levenshtein_rec(S , T.tail()),
C = levenshtein_rec(S.tail(), T),
if A > B then
A := B
elseif A > C then
A := C
end,
Dist1 := A + 1
end,
Dist = Dist1.</syntaxhighlight>
 
===Mode-directed tabling===
{{trans|Prolog}}
<syntaxhighlight lang="picat">
levenshtein_mode(S,T) = Dist =>
lev(S, T, Dist).
table (+,+,min)
lev([], [], 0).
lev([X|L], [X|R], D) :- !, lev(L, R, D).
lev([_|L], [_|R], D) :- lev(L, R, H), D is H+1.
lev([_|L], R, D) :- lev(L, R, H), D is H+1.
lev(L, [_|R], D) :- lev(L, R, H), D is H+1.</syntaxhighlight>
 
 
===Test===
<syntaxhighlight lang="picat">go =>
S = [
["kitten","sitting"],
["rosettacode","raisethysword"],
["levenshtein","levenstein"],
["saturday", "sunday"],
["stop", "tops"],
["saturday", "sunday"]
],
foreach([W1,W2] in S)
% clear the table cache
initialize_table,
println(iter=[W1,W2,levenshtein(W1,W2)]),
println(recu=[W1,W2,levenshtein_rec(W1,W2)]),
println(mode=[W1,W2,levenshtein_mode(W1,W2)]),
nl
end,
nl.</syntaxhighlight>
 
{{out}}
<pre>goal = go
iter = [kitten,sitting,3]
recu = [kitten,sitting,3]
mode = [kitten,sitting,3]
 
iter = [rosettacode,raisethysword,8]
recu = [rosettacode,raisethysword,8]
mode = [rosettacode,raisethysword,8]
 
iter = [levenshtein,levenstein,1]
recu = [levenshtein,levenstein,1]
mode = [levenshtein,levenstein,1]
 
iter = [saturday,sunday,3]
recu = [saturday,sunday,3]
mode = [saturday,sunday,3]
 
iter = [stop,tops,2]
recu = [stop,tops,2]
mode = [stop,tops,2]
 
iter = [saturday,sunday,3]
recu = [saturday,sunday,3]
mode = [saturday,sunday,3]</pre>
 
 
===Benchmark on larger strings===
Benchmarking the methods with larger strings of random lengths (between 1 and 2000).
<syntaxhighlight lang="picat">go2 =>
_ = random2(),
Len = 2000,
S1 = generate_string(Len),
S2 = generate_string(Len),
println(len_s1=S1.len),
println(len_s2=S2.len),
nl,
println("iter:"),
time(L1 = levenshtein(S1,S2)),
println("rec:"),
time(L2 = levenshtein_rec(S1,S2)),
println("mode:"),
time(L3 = levenshtein_mode(S1,S2)),
println(distances=[iter=L1,rec=L2,mode=L3]),
nl.
 
%
% Generate a random string of max length MaxLen
%
generate_string(MaxLen) = S =>
Alpha = "abcdefghijklmnopqrstuvxyz",
Len = Alpha.length,
S := [Alpha[random(1,Len)] : _ in 1..random(1,MaxLen)].</syntaxhighlight>
 
Here is sample run. The version using mode-directed tabling is clearly the fastest.
{{out}}
<pre>len_s1 = 1968
len_s2 = 1529
 
iter:
CPU time 9.039 seconds.
 
rec:
CPU time 10.439 seconds.
 
mode:
CPU time 1.402 seconds.
 
distances=[iter = 1607,rec = 1607,mode = 1607]</pre>
 
=={{header|PicoLisp}}==
Translation of the pseudo-code in the Wikipedia article:
<langsyntaxhighlight PicoLisplang="picolisp">(de levenshtein (A B)
(let D
(cons
Line 3,588 ⟶ 4,424:
(get D J (inc I))
(get D (inc J) I)
(get D J I) ) ) ) ) ) ) ) )</langsyntaxhighlight>
or, using 'map' to avoid list indexing:
<langsyntaxhighlight PicoLisplang="picolisp">(de levenshtein (A B)
(let D
(cons
Line 3,609 ⟶ 4,445:
(cadr Y) ) )
B
D ) ) )</langsyntaxhighlight>
{{out|Output (both cases)}}
<pre>: (levenshtein (chop "kitten") (chop "sitting"))
Line 3,616 ⟶ 4,452:
=={{header|PL/I}}==
===version 1===
<langsyntaxhighlight lang="pli">*process source xref attributes or(!);
lsht: Proc Options(main);
Call test('kitten' ,'sitting');
Line 3,671 ⟶ 4,507:
Return(ld);
End;
End;</langsyntaxhighlight>
{{out}}
<pre> 1st string = >kitten<
Line 3,697 ⟶ 4,533:
Levenshtein distance = 3</pre>
===version 2 recursive with memoization===
<langsyntaxhighlight lang="pli">*process source attributes xref or(!);
ld3: Proc Options(main);
Dcl ld(0:30,0:30) Bin Fixed(31);
Line 3,741 ⟶ 4,577:
Return(ld(sl,tl));
End;
End;</langsyntaxhighlight>
Output is the same as for version 1.
 
=={{header|PL/M}}==
{{works with|8080 PL/M Compiler}} ... under CP/M (or an emulator)
{{Trans|Action!}}
<syntaxhighlight lang="pli">100H: /* CALCULATE THE LEVENSHTEIN DISTANCE BETWEEN STRINGS */
/* TRANS:ATED FROM THE ACTION! SAMPLE */
 
/* CP/M BDOS SYSTEM CALL, IGNORE THE RETURN VALUE */
BDOS: PROCEDURE( FN, ARG ); DECLARE FN BYTE, ARG ADDRESS; GOTO 5; END;
PR$CHAR: PROCEDURE( C ); DECLARE C BYTE; CALL BDOS( 2, C ); END;
PR$STRING: PROCEDURE( S ); DECLARE S ADDRESS; CALL BDOS( 9, S ); END;
PR$NL: PROCEDURE; CALL PR$CHAR( 0DH ); CALL PR$CHAR( 0AH ); END;
PR$NUMBER: PROCEDURE( N ); /* PRINTS A NUMBER IN THE MINIMUN FIELD WIDTH */
DECLARE N ADDRESS;
DECLARE V ADDRESS, N$STR ( 6 )BYTE, W BYTE;
V = N;
W = LAST( N$STR );
N$STR( W ) = '$';
N$STR( W := W - 1 ) = '0' + ( V MOD 10 );
DO WHILE( ( V := V / 10 ) > 0 );
N$STR( W := W - 1 ) = '0' + ( V MOD 10 );
END;
CALL PR$STRING( .N$STR( W ) );
END PR$NUMBER;
 
DECLARE WIDTH LITERALLY '17'; /* ALLOW STRINGS UP TO 16 CHARACTERS */
DECLARE MATRIX$SIZE LITERALLY '289'; /* 17*17 ELEMENTS */
DECLARE STRING LITERALLY '( WIDTH )BYTE';
SCOPY: PROCEDURE( WORD, STR ); /* CONVEET PL/M STYLE STRING TO ACTION! */
DECLARE ( WORD, STR ) ADDRESS;
DECLARE ( W BASED WORD, S BASED STR ) STRING;
DECLARE ( I, C ) BYTE;
 
I = 0;
DO WHILE( ( C := S( I ) ) <> '$' );
W( I := I + 1 ) = C;
END;
W( 0 ) = I;
END SCOPY;
 
SET2DM: PROCEDURE( MATRIX, X, Y, VAL );
DECLARE ( MATRIX, X, Y, VAL ) ADDRESS;
DECLARE M BASED MATRIX ( MATRIX$SIZE )ADDRESS;
M( X + ( Y * WIDTH ) ) = VAL;
END SET2DM;
GET2DM: PROCEDURE( MATRIX, X, Y )ADDRESS;
DECLARE ( MATRIX, X, Y, VAL ) ADDRESS;
DECLARE M BASED MATRIX ( MATRIX$SIZE )ADDRESS;
RETURN M( X + ( Y * WIDTH ) );
END GET2DM;
LEVENSHTEIN$DISTANCE: PROCEDURE( S1, S2 )ADDRESS;
DECLARE ( S1, S2 ) ADDRESS;
DECLARE STR1 BASED S1 STRING, STR2 BASED S2 STRING;
DECLARE MATRIX ( MATRIX$SIZE ) ADDRESS;
DECLARE ( MIN, K, L, I, J, M, N ) BYTE;
M = STR1( 0 );
N = STR2( 0 );
DO I = 0 TO MATRIX$SIZE - 1; MATRIX( I ) = 0; END;
DO I = 0 TO M; CALL SET2DM( .MATRIX, I, 1, I ); END;
DO J = 0 TO N; CALL SET2DM( .MATRIX, 1, J, J ); END;
DO J = 1 TO N;
DO I = 1 TO M;
IF STR1( I ) = STR2( J ) THEN DO;
CALL SET2DM( .MATRIX, I, J, GET2DM( .MATRIX, I - 1, J - 1 ) );
END;
ELSE DO;
MIN = GET2DM( .MATRIX, I - 1, J ) + 1; /* DELETION */
K = GET2DM( .MATRIX, I, J - 1 ) + 1; /* INSERTION */
L = GET2DM( .MATRIX, I - 1, J - 1 ) + 1; /* SUBSTITUTION */
IF K < MIN THEN MIN = K;
IF L < MIN THEN MIN = L;
CALL SET2DM( .MATRIX, I, J, MIN );
END;
END;
END;
RETURN GET2DM( .MATRIX, M, N );
END LEVENSHTEIN$DISTANCE;
 
TEST: PROCEDURE( W1, W2 );
DECLARE ( W1, W2 ) ADDRESS;
DECLARE ( WORD$1, WORD$2 ) STRING;
 
CALL SCOPY( .WORD$1, W1 );
CALL SCOPY( .WORD$2, W2 );
 
CALL PR$STRING( W1 ); CALL PR$STRING( .' -> $' ); CALL PR$STRING( W2 );
CALL PR$STRING( .', LEVENSHTEIN DISTANCE: $' );
CALL PR$NUMBER( LEVENSHTEIN$DISTANCE( .WORD$1, .WORD$2 ) );
CALL PR$NL;
END TEST;
 
/* TEST CASES */
CALL TEST( .'KITTEN$', .'SITTING$' );
CALL TEST( .'ROSETTACODE$', .'RAISETHYSWORD$' );
CALL TEST( .'QWERTY$', .'QWERYT$' );
CALL TEST( .( 'ACTION', 33, '$' ), .'PL/M$' );
 
EOF</syntaxhighlight>
{{out}}
<pre>
KITTEN -> SITTING, LEVENSHTEIN DISTANCE: 3
ROSETTACODE -> RAISETHYSWORD, LEVENSHTEIN DISTANCE: 8
QWERTY -> QWERYT, LEVENSHTEIN DISTANCE: 2
ACTION! -> PL/M, LEVENSHTEIN DISTANCE: 4
</pre>
 
=={{header|PowerShell}}==
This version does not allow empty strings.
<syntaxhighlight lang="powershell">
<lang PowerShell>
function Get-LevenshteinDistance
{
Line 3,806 ⟶ 4,753:
$outputObject
}
</syntaxhighlight>
</lang>
<syntaxhighlight lang="powershell">
<lang PowerShell>
Get-LevenshteinDistance "kitten" "sitting"
Get-LevenshteinDistance rosettacode raisethysword
</syntaxhighlight>
</lang>
{{Out}}
<pre>
Line 3,820 ⟶ 4,767:
 
=={{header|Processing}}==
<langsyntaxhighlight lang="processing">void setup() {
println(distance("kitten", "sitting"));
}
Line 3,837 ⟶ 4,784:
}
return costs[b.length()];
}</langsyntaxhighlight>
 
==={{header|Processing Python mode}}===
 
<langsyntaxhighlight lang="python">def setup():
println(distance("kitten", "sitting"))
 
Line 3,857 ⟶ 4,804:
costs[j] = cj
 
return costs[len(b)]</langsyntaxhighlight>
 
=={{header|Prolog}}==
===Without Tabling===
Works with SWI-Prolog.<br>
Based on Wikipedia's pseudocode.
<langsyntaxhighlight Prologlang="prolog">levenshtein(S, T, R) :-
length(S, M),
M1 is M+1,
Line 3,922 ⟶ 4,870:
 
init_n(N, L) :-
nth0(0, L, N).</langsyntaxhighlight>
{{out|Output examples}}
<pre> ?- levenshtein("kitten", "sitting", R).
Line 3,932 ⟶ 4,880:
?- levenshtein("rosettacode", "raisethysword", R).
R = 8.
</pre>
===With Tabling===
Using so called mode directed tabling:
<pre>
:- table lev(_,_,min).
lev([], [], 0).
lev([X|L], [X|R], D) :- !, lev(L, R, D).
lev([_|L], [_|R], D) :- lev(L, R, H), D is H+1.
lev([_|L], R, D) :- lev(L, R, H), D is H+1.
lev(L, [_|R], D) :- lev(L, R, H), D is H+1.
 
?- set_prolog_flag(double_quotes, codes).
true.
 
?- lev("kitten", "sitting", R).
R = 3.
</pre>
 
=={{header|PureBasic}}==
Based on Wikipedia's pseudocode.
<langsyntaxhighlight PureBasiclang="purebasic">Procedure LevenshteinDistance(A_string$, B_String$)
Protected m, n, i, j, min, k, l
m = Len(A_string$)
Line 3,964 ⟶ 4,928:
;- Testing
n = LevenshteinDistance("kitten", "sitting")
MessageRequester("Info","Levenshtein Distance= "+Str(n))</langsyntaxhighlight>
 
=={{header|Python}}==
===Iterative 1===
Faithful implementation of "Iterative with full matrix" from Wikipedia
Implementation of the wikipedia algorithm, optimized for memory
<langsyntaxhighlight lang="python">def minimumEditDistancelevenshteinDistance(s1str1,s2 str2):
m = len(str1)
n = len(str2)
d = [[i] for i in range(1, m + 1)] # d matrix rows
d.insert(0, list(range(0, n + 1))) # d matrix columns
for j in range(1, n + 1):
for i in range(1, m + 1):
if str1[i - 1] == str2[j - 1]: # Python (string) is 0-based
substitutionCost = 0
else:
substitutionCost = 1
d[i].insert(j, min(d[i - 1][j] + 1,
d[i][j - 1] + 1,
d[i - 1][j - 1] + substitutionCost))
return d[-1][-1]
 
print(levenshteinDistance("kitten","sitting"))
print(levenshteinDistance("rosettacode","raisethysword"))</syntaxhighlight>
{{out}}
<pre>3
8</pre>
 
===Iterative 2===
Implementation of the Wikipedia algorithm, optimized for memory
<syntaxhighlight lang="python">def minimumEditDistance(s1,s2):
if len(s1) > len(s2):
s1,s2 = s2,s1
Line 3,986 ⟶ 4,974:
print(minimumEditDistance("kitten","sitting"))
print(minimumEditDistance("rosettacode","raisethysword"))</syntaxhighlight>
</lang>
 
{{out}}
<pre>3
8</pre>
 
===Iterative 3===
<lang python>def levenshteinDistance(str1, str2):
Iterative space optimized (even bounded)
m = len(str1)
<syntaxhighlight lang="python">def ld(a, b, mx=-1):
n = len(str2)
lensum = float(m + n)
d = []
for i in range(m+1):
d.append([i])
del d[0][0]
for j in range(n+1):
d[0].append(j)
for j in range(1,n+1):
for i in range(1,m+1):
if str1[i-1] == str2[j-1]:
d[i].insert(j,d[i-1][j-1])
else:
minimum = min(d[i-1][j]+1, d[i][j-1]+1, d[i-1][j-1]+2)
d[i].insert(j, minimum)
ldist = d[-1][-1]
ratio = (lensum - ldist)/lensum
return {'distance':ldist, 'ratio':ratio}
 
print(levenshteinDistance("kitten","sitting"))
print(levenshteinDistance("rosettacode","raisethysword"))
 
</lang>
 
{{out}}
<pre>{'distance': 5, 'ratio': 0.6153846153846154}
{'distance': 12, 'ratio': 0.5}</pre>
 
===Iterative space optimized (even bounded) ===
<lang python>
def ld(a, b, mx=-1):
def result(d): return d if mx < 0 else False if d > mx else True
Line 4,066 ⟶ 5,022:
ld('kitten','kittenaaaaaaaaaaaaaaaaa',3), # False
ld('kittenaaaaaaaaaaaaaaaaa','kitten',3) # False
)</syntaxhighlight>
)
</lang>
{{out}}
<pre>0 1 2 3 4 8 17 17
True True True True False False False False</pre>
0 1 2 3 4 8 17 17
True True True True False False False False
</pre>
 
===Functional===
====Memoized recursion====
(Uses [http://docs.python.org/dev/library/functools.html?highlight=functools.lru_cache#functools.lru_cache this] cache from the standard library).
<langsyntaxhighlight lang="python">>>> from functools import lru_cache
>>> @lru_cache(maxsize=4095)
def ld(s, t):
Line 4,089 ⟶ 5,042:
 
>>> print( ld("kitten","sitting"),ld("rosettacode","raisethysword") )
3 8</langsyntaxhighlight>
 
====Non-recursive: reduce and scanl====
{{Works with|Python|3.7}}
<langsyntaxhighlight lang="python">'''Levenshtein distance'''
 
from itertools import (accumulate, chain, islice)
Line 4,239 ⟶ 5,192:
# MAIN ---
if __name__ == '__main__':
main()</langsyntaxhighlight>
{{Out}}
<pre>Levenshtein minimum edit distances:
Line 4,252 ⟶ 5,205:
=={{header|Racket}}==
A memoized recursive implementation.
<langsyntaxhighlight lang="racket">#lang racket
 
(define (levenshtein a b)
Line 4,271 ⟶ 5,224:
 
(levenshtein "kitten" "sitting")
(levenshtein "rosettacode" "raisethysword")</langsyntaxhighlight>
{{out}}
<pre>3
Line 4,278 ⟶ 5,231:
=={{header|Raku}}==
(formerly Perl 6)
 
{{works with|rakudo|2015-09-16}}
Implementation of the wikipediaWikipedia algorithm. Since column 0 and row 0 are used for base distances, the original algorithm would require us to compare "@s[$i-1] eq @t[$j-1]", and reference the $m and $n separately. Prepending an unused value (undef) onto @s and @t makes their indices align with the $i,$j numbering of @d, and lets us use .end instead of $m,$n.
<syntaxhighlight lang="raku" perl6line>sub levenshtein_distancelevenshtein-distance ( Str $s, Str $t --> Int ) {
my @s = *, |$s.comb;
my @t = *, |$t.comb;
Line 4,297 ⟶ 5,250:
}
 
return @d[*-1][*-1];
}
 
myfor @a = [<kitten sitting>], [<saturday sunday>], [<rosettacode raisethysword>]; -> ($s, $t) {
say "Levenshtein distance('$s', '$t') == ", levenshtein-distance($s, $t)
}</syntaxhighlight>
{{out}}
<pre>Levenshtein distance('kitten', 'sitting') == 3
Levenshtein distance('saturday', 'sunday') == 3
Levenshtein distance('rosettacode', 'raisethysword') == 8</pre>
 
=={{header|Refal}}==
for @a -> [$s, $t] {
<syntaxhighlight lang="refal">$ENTRY Go {
say "levenshtein_distance('$s', '$t') == ", levenshtein_distance($s, $t);
= <Show ('kitten') ('sitting')>
}</lang>
<Show ('rosettacode') ('raisethysword')>;
};
 
Show {
(e.A) (e.B) = <Prout e.A ' -> ' e.B ': ' <Lev (e.A) (e.B)>>;
};
 
Lev {
(e.A) (), <Lenw e.A>: s.L e.A = s.L;
() (e.B), <Lenw e.B>: s.L e.B = s.L;
(s.C e.A) (s.C e.B) = <Lev (e.A) (e.B)>;
(e.A) (e.B), e.A: s.HA e.LA, e.B: s.HB e.LB =
<+ 1 <Min <Lev (e.LA) (e.B)>
<Lev (e.A) (e.LB)>
<Lev (e.LA) (e.LB)>>>;
}
 
Min {
s.N = s.N;
s.M s.N e.X, <Compare s.M s.N>: {
'-' = <Min s.M e.X>;
s.X = <Min s.N e.X>;
};
};</syntaxhighlight>
{{out}}
<pre>levenshtein_distance('kitten', 'sitting')-> ==sitting: 3
rosettacode -> raisethysword: 8</pre>
levenshtein_distance('saturday', 'sunday') == 3
levenshtein_distance('rosettacode', 'raisethysword') == 8</pre>
 
=={{header|REXX}}==
===version 1===
As per the task's requirements, this version includes a driver to display the results.
<langsyntaxhighlight lang="rexx">/*REXX program calculates and displays the Levenshtein distance between two strings. */
call Levenshtein 'kitten' , "sitting"
call Levenshtein 'rosettacode' , "raisethysword"
Line 4,332 ⟶ 5,314:
end /*k*/
end /*j*/ /* [↑] best choice.*/
say ' Levenshtein distance = ' @.oL.tL; say; return</langsyntaxhighlight>
{{out|output|text=&nbsp; when using the internal default inputs:}}
<pre>
Line 4,357 ⟶ 5,339:
 
===version 2===
<strike>same as</strike> Similar to version 1 <strike>(but does not include a driver for testing)</strike>, reformatted and commented
<syntaxhighlight lang="rexx">
<lang rexx>Levenshtein: Procedure
/*rexx*/
 
call test 'kitten' ,'sitting'
call test 'rosettacode' ,'raisethysword'
call test 'Sunday' ,'Saturday'
call test 'Vladimir_Levenshtein[1965]',,
'Vladimir_Levenshtein[1965]'
call test 'this_algorithm_is_similar_to',,
'Damerau-Levenshtein_distance'
call test '','abc'
exit 0
 
 
test: Procedure
Parse Arg s,t
ld.=''
Say ' 1st string = >'s'<'
Say ' 2nd string = >'t'<'
Say 'Levenshtein distance =' Levenshtein(s,length(s),t,length(t))
Say ''
Return
 
 
Levenshtein: Procedure
Parse Arg s,t
/* for all i and j, d[i,j] will hold the Levenshtein distance between */
Line 4,387 ⟶ 5,393:
Say ' 2nd string = ' t
say 'Levenshtein distance = ' d.m.n; say ''
Return d.m.n</lang>
</syntaxhighlight>
{{output}}
<pre>
1st string = >kitten<
2nd string = >sitting<
1st string = kitten
2nd string = 6
Levenshtein distance = 6
 
Levenshtein distance = 6
 
1st string = >rosettacode<
2nd string = >raisethysword<
1st string = rosettacode
2nd string = 11
Levenshtein distance = 11
 
Levenshtein distance = 11
 
1st string = >Sunday<
2nd string = >Saturday<
1st string = Sunday
2nd string = 6
Levenshtein distance = 6
 
Levenshtein distance = 6
 
1st string = >Vladimir_Levenshtein[1965]<
2nd string = >Vladimir_Levenshtein[1965]<
1st string = Vladimir_Levenshtein[1965]
2nd string = 26
Levenshtein distance = 25
 
Levenshtein distance = 25
 
1st string = >this_algorithm_is_similar_to<
2nd string = >Damerau-Levenshtein_distance<
1st string = this_algorithm_is_similar_to
2nd string = 28
Levenshtein distance = 28
 
Levenshtein distance = 28
 
1st string = ><
2nd string = >abc<
1st string =
2nd string = 0
Levenshtein distance = 1
 
Levenshtein distance = 1
</pre>
 
===version 3===
Alternate algorithm from Wikipedia <strike>(but does not include a driver for testing)</strike>.
<syntaxhighlight lang="rexx">
<lang rexx>LevenshteinDistance: Procedure
/*rexx*/
 
call test 'kitten' ,'sitting'
call test 'rosettacode' ,'raisethysword'
call test 'Sunday' ,'Saturday'
call test 'Vladimir_Levenshtein[1965]',,
'Vladimir_Levenshtein[1965]'
call test 'this_algorithm_is_similar_to',,
'Damerau-Levenshtein_distance'
call test '','abc'
exit 0
 
 
test: Procedure
Parse Arg s,t
ld.=''
Say ' 1st string = >'s'<'
Say ' 2nd string = >'t'<'
Say 'Levenshtein distance =' LevenshteinDistance(s,length(s),t,length(t))
Say ''
Return
 
 
LevenshteinDistance: Procedure
Parse Arg s,t
If s==t Then Return 0;
Line 4,412 ⟶ 5,493:
End
End
return v1.tl</lang>
</syntaxhighlight>
{{output}}
<pre>
1st string = >kitten<
2nd string = >sitting<
Levenshtein distance = 2
 
1st string = >rosettacode<
2nd string = >raisethysword<
Levenshtein distance = 3
 
1st string = >Sunday<
2nd string = >Saturday<
Levenshtein distance = 2
 
1st string = >Vladimir_Levenshtein[1965]<
2nd string = >Vladimir_Levenshtein[1965]<
Levenshtein distance = 3
 
1st string = >this_algorithm_is_similar_to<
2nd string = >Damerau-Levenshtein_distance<
Levenshtein distance = 3
 
1st string = ><
2nd string = >abc<
Levenshtein distance = 1
</pre>
 
===version 4 (recursive)===
Recursive algorithm from Wikipedia with memoization
<syntaxhighlight lang="rexx">
<lang rexx>call test 'kitten' ,'sitting'
/*rexx*/
 
call test 'kitten' ,'sitting'
call test 'rosettacode' ,'raisethysword'
call test 'Sunday' ,'Saturday'
Line 4,425 ⟶ 5,536:
call test '','abc'
Exit
 
 
test: Procedure
Line 4,434 ⟶ 5,546:
Say ''
Return
 
 
LevenshteinDistance: Procedure Expose ld.
Line 4,446 ⟶ 5,559:
/* test if last characters of the strings match */
cost=substr(s,sl,1)<>substr(t,tl,1)
/* return minimum of delete char from s, delete char from t,
and delete char from both */
ld.sl.tl=min(LevenshteinDistance(s,sl-1,t,tl )+1,,
Line 4,453 ⟶ 5,566:
End
End
Return ld.sl.tl</lang>
</syntaxhighlight>
{{output}}
<pre>
1st string = >kitten<
2nd string = >sitting<
Levenshtein distance = 3
 
1st string = >rosettacode<
2nd string = >raisethysword<
Levenshtein distance = 8
 
1st string = >Sunday<
2nd string = >Saturday<
Levenshtein distance = 3
 
1st string = >Vladimir_Levenshtein[1965]<
2nd string = >Vladimir_Levenshtein[1965]<
Levenshtein distance = 0
 
1st string = >this_algorithm_is_similar_to<
2nd string = >Damerau-Levenshtein_distance<
Levenshtein distance = 24
 
1st string = ><
2nd string = >abc<
Levenshtein distance = 3
</pre>
 
=={{header|Ring}}==
<langsyntaxhighlight lang="ring">
# Project : Levenshtein distance
 
Line 4,496 ⟶ 5,636:
levenshteindistance = d[n][m]
return levenshteindistance
</syntaxhighlight>
</lang>
Output:
<pre>
Line 4,502 ⟶ 5,642:
distance(saturday, sunday) = 3
distance(rosettacode, raisethysword) = 8
</pre>
 
=={{header|RPL}}==
{{works with|HP|28}}
{| class="wikitable"
! RPL code
! Comment
|-
|
≪ DUP2 SIZE SWAP SIZE → a b lb la
≪ '''IF''' la lb * NOT '''THEN''' la lb +
'''ELSE'''
a 2 la SUB b 2 lb SUB DUP2 <span style="color:blue">LEV</span>
'''IF''' a 1 1 SUB b 1 1 SUB == '''THEN'''
ROT ROT DROP2
'''ELSE'''
a ROT <span style="color:blue">LEV</span> ROT b <span style="color:blue">LEV</span>
MIN MIN 1 +
'''END END'''
≫ ≫ '<span style="color:blue">LEV</span>' STO
|
<span style="color:blue">LEV</span> ''( "a" "b" → distance )''
if |a|=0 or [b|=0 then return resp. [b| or |a|
else
put tail(a), tail(b) and lev(tail(a),tail(b)) in stack
if a[1]=b[1} then
clean stack and return lev(tail(a),tail(b))
else
put lev(a,tail(b)) and lev(tail(a),b) in stack
return min of the 3 values in stack and add 1
|}
"kitten" "sitting" <span style="color:blue">LEV</span>
"Summer" "Winter" <span style="color:blue">LEV</span>
"Levenshtein" "Levenshtein" <span style="color:blue">LEV</span>
{{out}}
<pre>
3: 3
2: 4
1: 0
</pre>
 
===Iterative implementation (Wagner-Fischer algorithm)===
 
index of arrays and strings start with 1 in RPL, so the main trick in translating the algorithm given by Wikipedia was to manage the offsets properly. The distance between "rosettacode" and "raisethysword" is within the reach of a calculator (emulated or not), unlike the above recursive approach.
{{works with|HP|48}}
{| class="wikitable"
! RPL code
! Comment
|-
|
DUP2 { } + + ≪ SIZE ≫ DOLIST 1 ADD 0 CON → a b d
≪ 1 a SIZE '''FOR''' h
'd' h 1 + 1 2 →LIST h PUT '''NEXT'''
1 b SIZE '''FOR''' j
'd' 1 j 1 + 2 →LIST j PUT '''NEXT'''
1 b SIZE '''FOR''' j
1 a SIZE '''FOR''' h
a h DUP SUB b j DUP SUB ≠
'd' h j 2 →LIST GET +
'd' h j 1 + 2 →LIST GET 1 +
'd' h 1 + j 2 →LIST GET 1 +
MIN MIN 'd' h 1 + j 1 + 2 →LIST ROT PUT
'''NEXT NEXT'''
'd' DUP SIZE GET
≫ ≫ '<span style="color:blue">LEV2</span>' STO
|
<span style="color:blue">LEV2</span> ''( "a" "b" → distance )''
declare int d[0..m, 0..n] and set each element in d to zero
for h from 1 to m: <span style="color:grey>// h replaces i, which is √-1 in RPL</span>
d[h, 0] := i <span style="color:grey>// RPL array indexes start with 1</span>
for j from 1 to n:
d[0, j] := j
for j from 1 to n:
for h from 1 to m:
substitutionCost := ( s[h] <> t[j] )
d[h, j] := minimum(d[h-1, j-1] + substitutionCost,
d[h-1, j] + 1,
d[h, j-1] + 1)
return d[m, n]
|}
"rosettacode" "raisethysword" <span style="color:blue">LEV2</span>
{{out}}
<pre>
1: 8
</pre>
 
Line 4,509 ⟶ 5,739:
and for <code>k >= j</code> contains ''lev(i-1, k)''. The inner loop body restores the invariant for the
new value of <code>j</code>.
<langsyntaxhighlight lang="ruby">module Levenshtein
def self.distance(a, b)
Line 4,531 ⟶ 5,761:
end
 
Levenshtein.test</langsyntaxhighlight>
{{out}}
<pre>
Line 4,540 ⟶ 5,770:
A variant can be found used in Rubygems [https://github.com/rubygems/rubygems/blob/master/lib/rubygems/text.rb]
 
<langsyntaxhighlight lang="ruby">def levenshtein_distance(str1, str2)
n = str1.length
m = str2.length
Line 4,573 ⟶ 5,803:
%w{kitten sitting saturday sunday rosettacode raisethysword}.each_slice(2) do |a, b|
puts "distance(#{a}, #{b}) = #{levenshtein_distance(a, b)}"
end</langsyntaxhighlight>
same output
 
=={{header|Run BASIC}}==
<langsyntaxhighlight lang="runbasic">print levenshteinDistance("kitten", "sitting")
print levenshteinDistance("rosettacode", "raisethysword")
end
Line 4,608 ⟶ 5,838:
levenshteinDistance = d(n, m)
[ex]
end function</langsyntaxhighlight>Output:<pre>3
8</pre>
 
=={{header|Rust}}==
Implementation of the wikipedia algorithm.
{{works with|Rust|1.145}}
<langsyntaxhighlight lang="rust">fn main() {
println!("{}", levenshtein_distance("kitten", "sitting"));
println!("{}", levenshtein_distance("saturday", "sunday"));
println!("{}", levenshtein_distance("rosettacode", "raisethysword"));
}
 
fn levenshtein_distance(word1: &str, word2: &str) -> usize {
let w1 = word1.chars().collect::<Vec<_>>();
let w2 = word2.chars().collect::<Vec<_>>();
 
let word1_length = w1.len() + 1;
let word2_length = w2.len() + 1;
 
let mut matrix = vec![vec![0; word1_length]; word2_length];
 
for i in 1..word1_length { matrix[0].push([i] = i); }
for j in 1..word2_length { matrix.push(vec![j])[0] = j; }
 
for j in 1..word2_length {
for i in 1..word1_length {
Line 4,641 ⟶ 5,871:
, matrix[j-1][i-1])
};
matrix[j].push([i] = x);
}
}
matrix[word2_length-1][word1_length-1]
}</langsyntaxhighlight>
{{out}}
<pre>3
Line 4,653 ⟶ 5,883:
=={{header|Scala}}==
===Translated Wikipedia algorithm.===
<langsyntaxhighlight lang="scala">object Levenshtein0 extends App {
 
def distance(s1: String, s2: String): Int = {
Line 4,676 ⟶ 5,906:
printDistance("rosettacode", "raisethysword")
 
}</langsyntaxhighlight>
{{out}}
<pre>kitten -> sitting : 3
Line 4,682 ⟶ 5,912:
===Functional programmed, memoized===
{{Out}}Best seen running in your browser either by [https://scalafiddle.io/sf/zj7bHC7/0 (ES aka JavaScript, non JVM)] or [https://scastie.scala-lang.org/qHhDWl68QgWv1uwOYzzNqw Scastie (remote JVM)].
<langsyntaxhighlight Scalalang="scala">import scala.collection.mutable
import scala.collection.parallel.ParSeq
 
Line 4,715 ⟶ 5,945:
printDistance("sleep", "fleeting")
 
}</langsyntaxhighlight>
 
=={{header|Scheme}}==
Line 4,721 ⟶ 5,951:
Recursive version from wikipedia article.
 
<langsyntaxhighlight lang="scheme">
(define (levenshtein s t)
(define (%levenshtein s sl t tl)
Line 4,735 ⟶ 5,965:
(string->list t)
(string-length t)))
</syntaxhighlight>
</lang>
 
{{out}}
Line 4,746 ⟶ 5,976:
 
=={{header|Seed7}}==
<langsyntaxhighlight lang="seed7">$ include "seed7_05.s7i";
 
const func integer: levenshteinDistance (in string: s, in string: t) is func
Line 4,777 ⟶ 6,007:
writeln("kitten -> sitting: " <& levenshteinDistance("kitten", "sitting"));
writeln("rosettacode -> raisethysword: " <& levenshteinDistance("rosettacode", "raisethysword"));
end func;</langsyntaxhighlight>
 
{{out}}
Line 4,787 ⟶ 6,017:
=={{header|SenseTalk}}==
SenseTalk has a built-in TextDifference function for this.
<syntaxhighlight lang="sensetalk">
<lang SenseTalk>
put textDifference("kitten", "sitting") // --> 3
put textDifference("rosettacode", "raisethysword") // --> 8
 
</syntaxhighlight>
</lang>
 
=={{header|SequenceL}}==
This implementation is based on the "Iterative with two matrix rows" version on Wikipedia.
<syntaxhighlight lang="sequencel">
<lang sequenceL>
import <Utilities/Sequence.sl>;
import <Utilities/Math.sl>;
Line 4,817 ⟶ 6,047:
min(min(v1[n] + 1, v0[n + 1] + 1), v0[n] + (0 when s = t[n] else 1))),
n + 1);
</syntaxhighlight>
</lang>
 
=={{header|Sidef}}==
===Recursive===
<langsyntaxhighlight lang="ruby">func lev(s, t) is cached {
 
s || return t.len
t || return s.len
 
var s1 = s.ftslice(1)
var t1 = t.ftslice(1)
 
s[0] == t[0] ? __FUNC__(s1, t1)
Line 4,835 ⟶ 6,065:
__FUNC__(s1, t )
)
}</langsyntaxhighlight>
 
===Iterative===
<langsyntaxhighlight lang="ruby">func lev(s, t) {
var d = [@(0 .. t.len), s.len.of {[_]}...]
for i,j in (^s ~X ^t) {
Line 4,848 ⟶ 6,078:
}
d[-1][-1]
}</langsyntaxhighlight>
 
Calling the function:
<langsyntaxhighlight lang="ruby">say lev(%c'kitten', %c'sitting'); # prints: 3
say lev(%c'rosettacode', %c'raisethysword'); # prints: 8</langsyntaxhighlight>
 
=={{header|Simula}}==
<langsyntaxhighlight lang="simula">BEGIN
 
INTEGER PROCEDURE LEVENSHTEINDISTANCE(S1, S2); TEXT S1, S2;
Line 4,891 ⟶ 6,121:
 
END
</syntaxhighlight>
</lang>
{{out}}
<pre>
Line 4,903 ⟶ 6,133:
{{works with|Smalltalk/X}}
ST/X provides a customizable levenshtein method in the String class (weights for individual operations can be passed in):
<langsyntaxhighlight lang="smalltalk">'kitten' levenshteinTo: 'sitting' s:1 k:1 c:1 i:1 d:1 -> 3
'rosettacode' levenshteinTo: 'raisethysword' s:1 k:1 c:1 i:1 d:1 -> 8</langsyntaxhighlight>
 
=={{header|Swift}}==
Line 4,910 ⟶ 6,140:
Version using entire matrix:
 
<langsyntaxhighlight lang="swift">func levDis(w1: String, w2: String) -> Int {
let (t, s) = (w1.characters, w2.characters)
Line 4,924 ⟶ 6,154:
}
return mat.last!.last!
}</langsyntaxhighlight>
 
Version using only two rows at a time:
 
<langsyntaxhighlight lang="swift">func levDis(w1: String, w2: String) -> Int {
let (t, s) = (w1.characters, w2.characters)
Line 4,943 ⟶ 6,173:
}
return last.last!
}</langsyntaxhighlight>
 
===Single array version===
{{trans|C++}}
<syntaxhighlight lang="swift">func levenshteinDistance(string1: String, string2: String) -> Int {
let m = string1.count
let n = string2.count
if m == 0 {
return n
}
if n == 0 {
return m
}
var costs = Array(0...n)
for (i, c1) in string1.enumerated() {
costs[0] = i + 1
var corner = i
for (j, c2) in string2.enumerated() {
let upper = costs[j + 1]
if c1 == c2 {
costs[j + 1] = corner
} else {
costs[j + 1] = 1 + min(costs[j], upper, corner)
}
corner = upper
}
}
return costs[n]
}
 
print(levenshteinDistance(string1: "rosettacode", string2: "raisethysword"))</syntaxhighlight>
 
{{out}}
<pre>
8
</pre>
 
=={{header|Tcl}}==
<langsyntaxhighlight lang="tcl">proc levenshteinDistance {s t} {
# Edge cases
if {![set n [string length $t]]} {
Line 4,974 ⟶ 6,239:
# The score is at the end of the last-computed row
return [lindex $p end]
}</langsyntaxhighlight>
{{out|Usage}}
<langsyntaxhighlight lang="tcl">puts [levenshteinDistance "kitten" "sitting"]; # Prints 3</langsyntaxhighlight>
 
=={{header|TSE SAL}}==
<langsyntaxhighlight TSESALlang="tsesal">// library: math: get: damerau: levenshtein <description></description> <version>1.0.0.0.23</version> <version control></version control> (filenamemacro=getmadle.s) [kn, ri, th, 08-09-2011 23:04:55]
INTEGER PROC FNMathGetDamerauLevenshteinDistanceI( STRING s1, STRING s2 )
INTEGER L1 = Length( s1 )
Line 5,013 ⟶ 6,278:
s2 = "altruistic"
Warn( "Minimum amount of steps to convert ", s1, " to ", s2, " = ", FNMathGetDamerauLevenshteinDistanceI( s1, s2 ) ) // gives e.g. 6
END</langsyntaxhighlight>
 
=={{header|Turbo-Basic XL}}==
<langsyntaxhighlight lang="turbobasic">
10 DIM Word_1$(20), Word_2$(20), DLDm(21, 21)
11 CLS
Line 5,026 ⟶ 6,291:
11600 PROC _DLD_
11610 Result=0 : M=LEN(Word_1$) : N=LEN(Word_2$)
11620 FOR I=0 TO M : DLDm(I,10)=I : NEXT I
11630 FOR J=0 TO N : DLDm(10,J)=J : NEXT J
11640 FOR J=1 TO N
11650 FOR I=1 TO M
Line 5,052 ⟶ 6,317:
11846 ? "Damerau Distance=";Result
11850 ENDPROC
</syntaxhighlight>
</lang>
{{out}}
<pre>kitten, sitting: 3
Line 5,059 ⟶ 6,324:
 
=={{header|TUSCRIPT}}==
<langsyntaxhighlight lang="tuscript">
$$ MODE TUSCRIPT
distance=DISTANCE ("kitten", "sitting")
PRINT distance
</syntaxhighlight>
</lang>
Output:
<pre>
3
</pre>
 
=={{header|TypeScript}}==
{{Trans|JavaScript}}
<syntaxhighlight lang="typescript">
function levenshtein(a: string, b: string): number {
const m: number = a.length,
n: number = b.length;
let t: number[] = [...Array(n + 1).keys()],
u: number[] = [];
for (let i: number = 0; i < m; i++) {
u = [i + 1];
for (let j: number = 0; j < n; j++) {
u[j + 1] = a[i] === b[j] ? t[j] : Math.min(t[j], t[j + 1], u[j]) + 1;
}
t = u;
}
return u[n];
}
 
</syntaxhighlight>
 
=={{header|uBasic/4tH}}==
{{trans|FreeBASIC}}
<syntaxhighlight lang="ubasic-4th">
' Uses the "iterative with two matrix rows" algorithm
' referred to in the Wikipedia article.
 
' create two integer arrays of distances
Dim @u(128) ' previous
Dim @v(128) ' current
 
Print "'kitten' to 'sitting' => ";
Print FUNC(_Levenshtein ("kitten", "sitting"))
 
Print "'rosettacode' to 'raisethysword' => ";
Print FUNC(_Levenshtein ("rosettacode", "raisethysword"))
 
Print "'sleep' to 'fleeting' => ";
Print FUNC(_Levenshtein ("sleep", "fleeting"))
 
End
 
_Levenshtein
Param (2)
Local (3)
 
' degenerate cases
If Comp(a@, b@) = 0 Then Return (0)
If Len(a@) = 0 Then Return (Len(b@))
If Len(b@) = 0 Then Return (Len(a@))
 
' initialize v0
For c@ = 0 To Len(b@)
@u(c@) = c@
Next
 
For c@ = 0 To Len(a@) - 1
' calculate @v() from @u()
@v(0) = c@ + 1
For d@ = 0 To Len(b@) - 1
e@ = IIf(Peek (a@, c@) = Peek (b@, d@), 0, 1)
@v(d@ + 1) = min(@v(d@) + 1, Min(@u(d@ + 1) + 1, @u(d@) + e@))
Next
 
' copy @v() to @u() for next iteration
For d@ = 0 To Len(b@)
@u(d@) = @v(d@)
Next
Next
 
Return (@v(Len(b@)))
</syntaxhighlight>
 
=={{header|Vala}}==
<langsyntaxhighlight lang="vala">class LevenshteinDistance : Object {
public static int compute (owned string s, owned string t, bool case_sensitive = false) {
var n = s.length;
Line 5,096 ⟶ 6,434:
}
}
</syntaxhighlight>
</lang>
 
=={{header|VBA}}==
{{trans|Phix}}<langsyntaxhighlight lang="vb">Option Base 1
Function levenshtein(s1 As String, s2 As String) As Integer
Dim n As Integer: n = Len(s1) + 1
Line 5,139 ⟶ 6,477:
Debug.Print levenshtein("kitten", "sitting")
Debug.Print levenshtein("rosettacode", "raisethysword")
End Sub</langsyntaxhighlight>{{out}}
<pre> 3
8 </pre>
 
=={{header|VBScript}}==
<langsyntaxhighlight lang="vb">' Levenshtein distance - 23/04/2020
 
Function Min(a,b)
Line 5,187 ⟶ 6,525:
PrintLevenshtein "rosettacode", "raisethysword"
PrintLevenshtein "saturday", "sunday"
PrintLevenshtein "sleep", "fleeting"</langsyntaxhighlight>
{{out}}
<pre>
Line 5,204 ⟶ 6,542:
{{works with|VBA|6.5}}
{{works with|VBA|7.1}}
<langsyntaxhighlight lang="vb">Function min(x As Integer, y As Integer) As Integer
If x < y Then
min = x
Line 5,264 ⟶ 6,602:
Debug.Print "'sleep' to 'fleeting' => "; levenshtein("sleep", "fleeting")
End Sub
</syntaxhighlight>
</lang>
{{out}}
<pre>
<pre>'kitten' to 'sitting' => 3
'kitten' to 'sitting' => 3
'sitting' to 'kitten' => 3
'rosettacode' to 'raisethysword' => 8
'sleep' to 'fleeting' => 5</pre>
</pre>
 
=={{header|Visual Basic .NET}}==
<langsyntaxhighlight lang="vbnet"> Function LevenshteinDistance(ByVal String1 As String, ByVal String2 As String) As Integer
Dim Matrix(String1.Length, String2.Length) As Integer
Dim Key As Integer
Line 5,291 ⟶ 6,631:
Next
Return Matrix(String1.Length - 1, String2.Length - 1)
End Function</langsyntaxhighlight>
 
=={{header|V (Vlang)}}==
<syntaxhighlight lang="Zig">
import strings
 
fn main() {
println(strings.levenshtein_distance("kitten", "sitting"))
println(strings.levenshtein_distance("rosettacode", "raisethysword"))
}
</syntaxhighlight>
 
{{out}}
<pre>
3
8
</pre>
 
=={{header|Wren}}==
{{trans|Go}}
<syntaxhighlight lang="wren">var levenshtein = Fn.new { |s, t|
var ls = s.count
var lt = t.count
var d = List.filled(ls + 1, null)
for (i in 0..ls) {
d[i] = List.filled(lt + 1, 0)
d[i][0] = i
}
for (j in 0..lt) d[0][j] = j
for (j in 1..lt) {
for (i in 1..ls) {
if (s[i-1] == t[j-1]) {
d[i][j] = d[i-1][j-1]
} else {
var min = d[i-1][j]
if (d[i][j-1] < min) min = d[i][j-1]
if (d[i-1][j-1] < min) min = d[i-1][j-1]
d[i][j] = min + 1
}
}
}
return d[-1][-1]
}
 
System.print(levenshtein.call("kitten", "sitting"))</syntaxhighlight>
 
{{out}}
<pre>
3
</pre>
 
=={{header|Zig}}==
{{trans|C}}
 
'''Works with:''' 0.11.x, 0.12.0-dev.1381+61861ef39
 
For 0.10.x, replace @min(a, b, c) with std.math.min3(a, b, c).
 
Recursive method without memoization.
 
<syntaxhighlight lang="zig">const std = @import("std");
 
fn levenshtein(s: []const u8, t: []const u8) usize {
// If either string is empty, difference is inserting all chars
// from the other
if (s.len == 0) return t.len;
if (t.len == 0) return s.len;
 
// If last letters are the same, the difference is whatever is
// required to edit the rest of the strings
if (s[s.len - 1] == t[t.len - 1])
return levenshtein(s[0 .. s.len - 1], t[0 .. t.len - 1]);
 
// Else try:
// changing last letter of s to that of t; or
// remove last letter of s; or
// remove last letter of t,
// any of which is 1 edit plus editing the rest of the strings
const a = levenshtein(s[0 .. s.len - 1], t[0 .. t.len - 1]);
const b = levenshtein(s, t[0 .. t.len - 1]);
const c = levenshtein(s[0 .. s.len - 1], t);
 
return @min(a, b, c) + 1;
}
 
pub fn main() std.fs.File.WriteError!void {
const stdout = std.io.getStdOut();
const stdout_w = stdout.writer();
 
const s1 = "rosettacode";
const s2 = "raisethysword";
try stdout_w.print("distance between '{s}' and '{s}': {d}\n", .{ s1, s2, levenshtein(s1, s2) });
return;
}</syntaxhighlight>
 
=={{header|zkl}}==
{{trans|D}}
<langsyntaxhighlight lang="zkl">fcn levenshtein(s1,s2){
sz2,costs:=s2.len() + 1, List.createLong(sz2,0); // -->zero filled List
foreach i in (s1.len() + 1){
Line 5,312 ⟶ 6,745:
}
costs[-1]
}</langsyntaxhighlight>
<langsyntaxhighlight lang="zkl">foreach a,b in (T(T("kitten","sitting"), T("rosettacode","raisethysword"),
T("yo",""), T("","yo"), T("abc","abc")) ){
println(a," --> ",b,": ",levenshtein(a,b));
}</langsyntaxhighlight>
{{out}}
<pre>
Line 5,327 ⟶ 6,760:
 
=={{header|ZX Spectrum Basic}}==
<langsyntaxhighlight lang="zxbasic">10 REM ZX Spectrum Basic - Levenshtein distance
20 INPUT "first word:",n$
30 INPUT "second word:",m$
Line 5,340 ⟶ 6,773:
120 NEXT i
130 NEXT j
140 PRINT "The Levenshtein distance between """;n$;""", """;m$;""" is ";d(m+1,n+1);"."</langsyntaxhighlight>
{{out}}
<pre>
55

edits