Levenshtein distance/Alignment: Difference between revisions

m
(Added Arturo implementation)
 
(15 intermediate revisions by 11 users not shown)
Line 19:
<br><br>
 
=={{header|Arturo11l}}==
{{trans|Nim}}
 
<syntaxhighlight lang="11l">F levenshteinAlign(aa, bb)
<lang rebol>print join.with:"\n" levenshtein.align "place" "palace"
V a = aa.lowercase()
print join.with:"\n" levenshtein.align "rosettacode" "raisethysword"</lang>
V b = bb.lowercase()
V costs = [[0] * (b.len + 1)] * (a.len + 1)
L(j) 0 .. b.len
costs[0][j] = j
L(i) 1 .. a.len
costs[i][0] = i
L(j) 1 .. b.len
V tmp = costs[i - 1][j - 1] + Int(a[i - 1] != b[j - 1])
costs[i][j] = min(1 + min(costs[i - 1][j], costs[i][j - 1]), tmp)
 
V aPathRev = ‘’
V bPathRev = ‘’
V i = a.len
V j = b.len
L i != 0 & j != 0
V tmp = costs[i - 1][j - 1] + Int(a[i - 1] != b[j - 1])
I costs[i][j] == tmp
aPathRev ‘’= a[--i]
bPathRev ‘’= b[--j]
E I costs[i][j] == 1 + costs[i - 1][j]
aPathRev ‘’= a[--i]
bPathRev ‘’= ‘-’
E I costs[i][j] == 1 + costs[i][j - 1]
aPathRev ‘’= ‘-’
bPathRev ‘’= b[--j]
E
assert(0B, ‘Internal error’)
 
R (reversed(aPathRev), reversed(bPathRev))
 
V result = levenshteinAlign(‘place’, ‘palace’)
print(result[0])
print(result[1])
print()
 
result = levenshteinAlign(‘rosettacode’, ‘raisethysword’)
print(result[0])
print(result[1])</syntaxhighlight>
 
{{out}}
<pre>
p-lace
palace
 
r-oset-tacode
raisethysword
</pre>
 
=={{header|Arturo}}==
 
<syntaxhighlight lang="rebol">print join.with:"\n" levenshtein.align "place" "palace"
print join.with:"\n" levenshtein.align "rosettacode" "raisethysword"</syntaxhighlight>
 
{{out}}
Line 32 ⟶ 85:
 
=={{header|C}}==
<langsyntaxhighlight lang="c">#include <stdio.h>
#include <stdlib.h>
#include <string.h>
Line 120 ⟶ 173:
leven("raisethysword", "rosettacode");
return 0;
}</langsyntaxhighlight>
{{out}}
<pre>
raisethysword -> rosettacode: 8 edits
r(a,o)(i,)set(h,t)(y,a)(s,c)(w,)o(r,d)(d,e)
</pre>
 
=={{header|C#}}==
{{trans|Java}}
<syntaxhighlight lang="C#">
using System;
using System.Text;
 
public class LevenshteinAlignment
{
public static string[] Alignment(string a, string b)
{
a = a.ToLower();
b = b.ToLower();
 
int[,] costs = new int[a.Length + 1, b.Length + 1];
 
for (int j = 0; j <= b.Length; j++)
costs[0, j] = j;
 
for (int i = 1; i <= a.Length; i++)
{
costs[i, 0] = i;
for (int j = 1; j <= b.Length; j++)
{
costs[i, j] = Math.Min(1 + Math.Min(costs[i - 1, j], costs[i, j - 1]),
a[i - 1] == b[j - 1] ? costs[i - 1, j - 1] : costs[i - 1, j - 1] + 1);
}
}
 
StringBuilder aPathRev = new StringBuilder();
StringBuilder bPathRev = new StringBuilder();
 
for (int i = a.Length, j = b.Length; i != 0 && j != 0;)
{
if (costs[i, j] == (a[i - 1] == b[j - 1] ? costs[i - 1, j - 1] : costs[i - 1, j - 1] + 1))
{
aPathRev.Append(a[--i]);
bPathRev.Append(b[--j]);
}
else if (costs[i, j] == 1 + costs[i - 1, j])
{
aPathRev.Append(a[--i]);
bPathRev.Append('-');
}
else if (costs[i, j] == 1 + costs[i, j - 1])
{
aPathRev.Append('-');
bPathRev.Append(b[--j]);
}
}
 
return new string[] { Reverse(aPathRev.ToString()), Reverse(bPathRev.ToString()) };
}
 
private static string Reverse(string s)
{
char[] charArray = s.ToCharArray();
Array.Reverse(charArray);
return new string(charArray);
}
 
public static void Main(string[] args)
{
string[] result = Alignment("rosettacode", "raisethysword");
Console.WriteLine(result[0]);
Console.WriteLine(result[1]);
}
}
</syntaxhighlight>
{{out}}
<pre>
r-oset-tacode
raisethysword
 
</pre>
 
=={{header|C++}}==
<syntaxhighlight lang="c++">
#include <algorithm>
#include <cstdint>
#include <iostream>
#include <string>
#include <vector>
 
std::string to_lower_case(const std::string& text) {
std::string result = text;
std::transform(result.begin(), result.end(), result.begin(),
[](char ch){ return std::tolower(ch); });
return result;
}
 
std::vector<std::string> levenshtein_alignment(std::string a, std::string b) {
a = to_lower_case(a);
b = to_lower_case(b);
 
std::vector<std::vector<int32_t>> costs{ a.length() + 1, std::vector<int32_t>( b.length() + 1, 0 ) };
for ( uint64_t j = 0; j <= b.length(); ++j )
costs[0][j] = j;
for ( uint64_t i = 1; i <= a.length(); ++i ) {
costs[i][0] = i;
for ( uint64_t j = 1; j <= b.length(); ++j ) {
costs[i][j] = std::min(std::min( costs[i - 1][j], costs[i][j - 1]) + 1,
a[i - 1] == b[j - 1] ? costs[i - 1][j - 1] : costs[i - 1][j - 1] + 1);
}
}
 
std::string a_path_reversed, b_path_reversed;
uint64_t i = a.length(), j = b.length();
while ( i != 0 && j != 0 ) {
if ( costs[i][j] == ( a[i - 1] == b[j - 1] ? costs[i - 1][j - 1] : costs[i - 1][j - 1] + 1 ) ) {
a_path_reversed += a[--i];
b_path_reversed += b[--j];
} else if ( costs[i][j] == costs[i - 1][j] + 1 ) {
a_path_reversed += a[--i];
b_path_reversed += "-";
} else if ( costs[i][j] == costs[i][j - 1] + 1 ) {
a_path_reversed += "-";
b_path_reversed += b[--j];
}
}
 
std::reverse(a_path_reversed.begin(), a_path_reversed.end());
std::reverse(b_path_reversed.begin(), b_path_reversed.end());
return std::vector<std::string>{ a_path_reversed, b_path_reversed };
}
 
int main() {
std::vector<std::string> result = levenshtein_alignment("place", "palace");
std::cout << result[0] << std::endl;
std::cout << result[1] << std::endl;
std::cout << std::endl;
 
result = levenshtein_alignment("rosettacode", "raisethysword");
std::cout << result[0] << std::endl;
std::cout << result[1] << std::endl;
}
</syntaxhighlight>
{{ out }}
<pre>
p-lace
palace
 
r-oset-tacode
raisethysword
</pre>
 
=={{header|D}}==
Using the standard library.
<langsyntaxhighlight lang="d">void main() {
import std.stdio, std.algorithm;
 
Line 156 ⟶ 354:
 
writeln(s1b, "\n", s2b);
}</langsyntaxhighlight>
{{out}}
<pre>r_oset_tacode
raisethysword</pre>
 
=={{header|EasyLang}}==
{{trans|FreeBASIC}}
<syntaxhighlight>
global dparr[] dpcols .
proc dpnew a b . .
len dparr[] a * b
dpcols = b
.
func dp r c .
return dparr[r * dpcols + c + 1]
.
proc dps r c v . .
dparr[r * dpcols + c + 1] = v
.
proc align a$ b$ . ar$ br$ .
dpnew (len a$ + 1) (len b$ + 1)
for i = 1 to len a$
dps i 0 i
.
for j = 0 to len b$
dps 0 j j
.
for i = 1 to len a$
for j = 1 to len b$
if substr a$ i 1 = substr b$ j 1
dps i j dp (i - 1) (j - 1)
else
dps i j lower (lower dp (i - 1) j dp i (j - 1)) dp (i - 1) (j - 1) + 1
.
.
.
ar$ = "" ; br$ = ""
i = len a$ ; j = len b$
while i <> 0 and j <> 0
if substr a$ i 1 = substr b$ j 1 or dp i j = dp (i - 1) (j - 1) + 1
ar$ = substr a$ i 1 & ar$
i -= 1
br$ = substr b$ j 1 & br$
j -= 1
elif dp i j = dp (i - 1) j + 1
ar$ = substr a$ i 1 & ar$
i -= 1
br$ = "-" & br$
else
ar$ = "-" & ar$
br$ = substr b$ j 1 & br$
j -= 1
.
.
.
align "rosettacode" "raisethysword" ar$ br$
print ar$ ; print br$
</syntaxhighlight>
{{out}}
<pre>
r-oset-tacode
raisethysword
</pre>
 
=={{header|Eiffel}}==
<langsyntaxhighlight lang="eiffel">
distance (source, target: STRING): INTEGER
-- Minimum number of operations to turn `source' into `target'.
Line 187 ⟶ 444:
Result:= l_distance [source.count, target.count]
end
</langsyntaxhighlight>{{out}}
Result = 8
 
Line 193 ⟶ 450:
 
Also—the `ic' is this programmers shorthand for ITERATION_CURSOR. Therefore, in the nested loops, the `ic' is the iteration cursor following `i' and the `ij' is following `j' as indexes on the source, target, and l_distance.
 
=={{header|FreeBASIC}}==
<syntaxhighlight lang="vbnet">#define min(a, b) iif((a) < (b), (a), (b))
 
Sub LevenshteinAlignment(s1 As String, s2 As String)
Dim As String align1 = "", align2 = ""
Dim As Integer i, j, len1, len2
len1 = Len(s1):
len2 = Len(s2)
Dim As Integer dp(len1+1, len2+1)
For i = 0 To len1
dp(i, 0) = i
Next i
For j = 0 To len2
dp(0, j) = j
Next j
For i = 1 To len1
For j = 1 To len2
If Mid(s1, i, 1) = Mid(s2, j, 1) Then
dp(i, j) = dp(i-1, j-1)
Else
dp(i, j) = min(min(dp(i-1, j), dp(i, j-1)), dp(i-1, j-1)) + 1
End If
Next j
Next i
i = len1: j = len2
While i > 0 And j > 0
If Mid(s1, i, 1) = Mid(s2, j, 1) Then
align1 = Mid(s1, i, 1) + align1
align2 = Mid(s2, j, 1) + align2
i -= 1: j -= 1
Elseif dp(i, j) = dp(i-1, j-1) + 1 Then
align1 = Mid(s1, i, 1) + align1
align2 = Mid(s2, j, 1) + align2
i -= 1: j -= 1
Elseif dp(i, j) = dp(i-1, j) + 1 Then
align1 = Mid(s1, i, 1) + align1
align2 = "-" + align2
i -= 1
Else
align1 = "-" + align1
align2 = Mid(s2, j, 1) + align2
j -= 1
End If
Wend
While i > 0
align1 = Mid(s1, i, 1) + align1
align2 = "-" + align2
i -= 1
Wend
While j > 0
align1 = "-" + align1
align2 = Mid(s2, j, 1) + align2
j -= 1
Wend
Print "Levenshtein Distance: "; dp(len1, len2)
Print align1
Print align2
Print
End Sub
 
LevenshteinAlignment("rosettacode", "raisethysword")
LevenshteinAlignment("place", "palace")
 
Sleep</syntaxhighlight>
{{out}}
<pre>Levenshtein Distance: 8
r-oset-tacode
raisethysword
 
Levenshtein Distance: 1
p-lace
palace</pre>
 
=={{header|Go}}==
{{libheader|biogo}}
Alignment computed by the Needleman-Wunch algorithm, which is used in bioinformatics.
<langsyntaxhighlight lang="go">package main
 
import (
Line 252 ⟶ 588:
}
fmt.Println(string(ma))
}</langsyntaxhighlight>
{{out}}
The lines after the alignment point out the 8 edits.
Line 263 ⟶ 599:
=={{header|Haskell}}==
The Wagner–Fischer matrix construction is adopted from [[Levenshtein_distance#Haskell]], however it is reversed in order to simplify it's traversing.
<langsyntaxhighlight lang="haskell">costs :: String -> String -> [[Int]]
costs s1 s2 = reverse $ reverse <$> matrix
where
Line 273 ⟶ 609:
 
levenshteinDistance :: String -> String -> Int
levenshteinDistance s1 s2 = head.head $ costs s1 s2</langsyntaxhighlight>
 
 
Line 280 ⟶ 616:
Instead of indices the Wagner–Fischer matrix and strings are traversed by list truncation, as zippers.
 
<langsyntaxhighlight lang="haskell">alignment :: String -> String -> (String, String)
alignment s1 s2 = go (costs s1 s2) (reverse s1) (reverse s2) ([],[])
where
Line 297 ⟶ 633:
nextRow = map tail
nextCol = tail
isEmpty c = null c || null (head c)</langsyntaxhighlight>
 
<pre>λ> alignment "palace" "place"
Line 311 ⟶ 647:
The alternative solution, which extensively produces all minimal alignments for given strings.
 
<langsyntaxhighlight lang="haskell">-- Produces all possible alignments for two strings.
allAlignments :: String -> String -> [[(Char, Char)]]
allAlignments s1 s2 = go (length s2 - length s1) s1 s2
Line 331 ⟶ 667:
best = filter ((lev ==) . dist) $ allAlignments s1 s2
lev = levenshteinDistance s1 s2
dist = length . filter (uncurry (/=))</langsyntaxhighlight>
 
 
Line 357 ⟶ 693:
("rosettacode","r-----a---t")</pre>
 
 
=={{header|J}}==
 
Translation of java:
 
<syntaxhighlight lang="j">levalign=:4 :0
assert. x <:&# y
D=. x +/&i.&>:&# y
for_i. 1+i.#x do.
for_j. 1+i.#y do.
if. ((<:i){x)=(<:j){y do.
D=. (D {~<<:i,j) (<i,j)} D
else.
min=. 1+<./D{~(i,j) <@:-"1#:1 2 3
D=. min (<i,j)} D
end.
end.
end.
A=. B=. ''
ij=. x ,&# y
while. */ij do.
'd00 d01 d10 d11'=. D{~ ij <@:-"1#:i.4
'x1 y1'=. (ij-1){each x;y
if. d00 = d11+x1~:y1 do.
A=. A,x1 [ B=. B,y1 [ ij=. ij-1
elseif. d00 = 1+d10 do.
A=. A,x1 [ B=. B,'-'[ ij=. ij-1 0
elseif. d00 = 1+d01 do.
A=. A,'-'[ B=. B,y1 [ ij=. ij-0 1
end.
end.
A,:&|.B
)</syntaxhighlight>
 
Task examples:
 
<syntaxhighlight lang="j"> 'place' levalign 'palace'
p-lace
palace
'rosettacode' levalign 'raisethysword'
r-oset-tacode
raisethysword
</syntaxhighlight>
 
=={{header|Java}}==
<langsyntaxhighlight lang="java">public class LevenshteinAlignment {
 
public static String[] alignment(String a, String b) {
Line 398 ⟶ 777:
System.out.println(result[1]);
}
}</langsyntaxhighlight>
{{out}}
<pre>
Line 409 ⟶ 788:
{{trans|Java}}
 
<langsyntaxhighlight lang="julia">function levenshteinalign(a::AbstractString, b::AbstractString)
a = lowercase(a)
b = lowercase(b)
Line 451 ⟶ 830:
 
foreach(println, levenshteinalign("rosettacode", "raisethysword"))
foreach(println, levenshteinalign("place", "palace"))</langsyntaxhighlight>
 
{{out}}
Line 461 ⟶ 840:
=={{header|Kotlin}}==
{{trans|Java}}
<langsyntaxhighlight lang="scala">// version 1.1.3
 
fun levenshteinAlign(a: String, b: String): Array<String> {
Line 511 ⟶ 890:
println(result[0])
println(result[1])
}</langsyntaxhighlight>
 
{{out}}
Line 525 ⟶ 904:
{{incorrect}}
{{works with|Mathematica|7}}
<langsyntaxhighlight Mathematicalang="mathematica">DamerauLevenshteinDistance["rosettacode", "raisethysword"]</langsyntaxhighlight>
 
{{out}}<pre>8</pre>
Line 531 ⟶ 910:
=={{header|Nim}}==
{{trans|Kotlin}}
<langsyntaxhighlight Nimlang="nim">import algorithm, sequtils, strutils
 
proc levenshteinAlign(a, b: string): tuple[a, b: string] =
Line 577 ⟶ 956:
result = levenshteinAlign("rosettacode","raisethysword")
echo result.a
echo result.b</langsyntaxhighlight>
 
{{out}}
Line 587 ⟶ 966:
 
=={{header|Perl}}==
<langsyntaxhighlight lang="perl">use strict;
use warnings;
 
Line 622 ⟶ 1,001:
}
print join "\n", levenshtein_distance_alignment "rosettacode", "raisethysword";</langsyntaxhighlight>
{{out}}
<pre>ro-settac-o-de
Line 629 ⟶ 1,008:
=={{header|Phix}}==
{{trans|Kotlin}} plus the indicator from Go
<!--<syntaxhighlight lang="phix">(phixonline)-->
<lang Phix>function LevenshteinAlignment(string a, b)
<span style="color: #008080;">function</span> <span style="color: #000000;">LevenshteinAlignment</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>
integer la = length(a)+1,
<span style="color: #004080;">integer</span> <span style="color: #000000;">la</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><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span>
lb = length(b)+1
<span style="color: #000000;">lb</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>
sequence costs = repeat(repeat(0,lb),la)
<span style="color: #004080;">sequence</span> <span style="color: #000000;">costs</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;">lb</span><span style="color: #0000FF;">),</span><span style="color: #000000;">la</span><span style="color: #0000FF;">)</span>
for j=1 to lb do
<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;">lb</span> <span style="color: #008080;">do</span>
costs[1][j] = j
<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: #000000;">j</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">j</span>
end for
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
for i=2 to la do
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">2</span> <span style="color: #008080;">to</span> <span style="color: #000000;">la</span> <span style="color: #008080;">do</span>
costs[i][1] = i
<span style="color: #000000;">costs</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: #0000FF;">=</span> <span style="color: #000000;">i</span>
for j=2 to lb do
<span style="color: #008080;">for</span> <span style="color: #000000;">j</span><span style="color: #0000FF;">=</span><span style="color: #000000;">2</span> <span style="color: #008080;">to</span> <span style="color: #000000;">lb</span> <span style="color: #008080;">do</span>
integer tmp1 = 1+min(costs[i-1][j], costs[i][j-1]),
<span style="color: #004080;">integer</span> <span style="color: #000000;">tmp1</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">1</span><span style="color: #0000FF;">+</span><span style="color: #7060A8;">min</span><span style="color: #0000FF;">(</span><span style="color: #000000;">costs</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;">costs</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>
tmp2 = costs[i-1][j-1] + (a[i-1]!=b[j-1])
<span style="color: #000000;">tmp2</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">costs</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: #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;">1</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;">1</span><span style="color: #0000FF;">])</span>
costs[i][j] = min(tmp1, tmp2)
<span style="color: #000000;">costs</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: #0000FF;">=</span> <span style="color: #7060A8;">min</span><span style="color: #0000FF;">(</span><span style="color: #000000;">tmp1</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">tmp2</span><span style="color: #0000FF;">)</span>
end for
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
end for
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
-- walk back through matrix to figure out the path
<span style="color: #000080;font-style:italic;">-- walk back through matrix to figure out the path</span>
string arev = "",
<span style="color: #004080;">string</span> <span style="color: #000000;">arev</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">""</span><span style="color: #0000FF;">,</span>
brev = ""
<span style="color: #000000;">brev</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">""</span>
integer i = la, j = lb
<span style="color: #004080;">integer</span> <span style="color: #000000;">i</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">la</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">j</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">lb</span>
while i>1 and j>1 do
<span style="color: #008080;">while</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">></span><span style="color: #000000;">1</span> <span style="color: #008080;">and</span> <span style="color: #000000;">j</span><span style="color: #0000FF;">></span><span style="color: #000000;">1</span> <span style="color: #008080;">do</span>
integer tmp = costs[i-1][j-1] + (a[i-1]!=b[j-1])
<span style="color: #004080;">integer</span> <span style="color: #000000;">tmp</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">costs</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: #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;">1</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;">1</span><span style="color: #0000FF;">])</span>
switch costs[i][j] do
<span style="color: #008080;">switch</span> <span style="color: #000000;">costs</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: #008080;">do</span>
case tmp: i -= 1; arev &= a[i]
<span style="color: #008080;">case</span> <span style="color: #000000;">tmp</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;">arev</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>
j -= 1; brev &= b[j]
<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;">brev</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>
case 1 + costs[i-1][j]: i -= 1; arev &= a[i]
<span style="color: #008080;">case</span> <span style="color: #000000;">1</span> <span style="color: #0000FF;">+</span> <span style="color: #000000;">costs</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;">i</span> <span style="color: #0000FF;">-=</span> <span style="color: #000000;">1</span><span style="color: #0000FF;">;</span> <span style="color: #000000;">arev</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>
brev &= '-'
<span style="color: #000000;">brev</span> <span style="color: #0000FF;">&=</span> <span style="color: #008000;">'-'</span>
case 1 + costs[i][j-1]: arev &= '-'
<span style="color: #008080;">case</span> <span style="color: #000000;">1</span> <span style="color: #0000FF;">+</span> <span style="color: #000000;">costs</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;">arev</span> <span style="color: #0000FF;">&=</span> <span style="color: #008000;">'-'</span>
j -= 1; brev &= b[j]
<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;">brev</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>
end switch
<span style="color: #008080;">end</span> <span style="color: #008080;">switch</span>
end while
<span style="color: #008080;">end</span> <span style="color: #008080;">while</span>
return {reverse(arev),reverse(brev)}
<span style="color: #008080;">return</span> <span style="color: #0000FF;">{</span><span style="color: #7060A8;">reverse</span><span style="color: #0000FF;">(</span><span style="color: #000000;">arev</span><span style="color: #0000FF;">),</span><span style="color: #7060A8;">reverse</span><span style="color: #0000FF;">(</span><span style="color: #000000;">brev</span><span style="color: #0000FF;">)}</span>
end function
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
procedure test(string a,b)
<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;">a</span><span style="color: #0000FF;">,</span><span style="color: #000000;">b</span><span style="color: #0000FF;">)</span>
{a,b} = LevenshteinAlignment(a,b)
<span style="color: #0000FF;">{</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: #0000FF;">=</span> <span style="color: #000000;">LevenshteinAlignment</span><span style="color: #0000FF;">(</span><span style="color: #000000;">a</span><span style="color: #0000FF;">,</span><span style="color: #000000;">b</span><span style="color: #0000FF;">)</span>
string c = sq_add(repeat(' ',length(a)),sq_mul(sq_ne(a,b),'|'-' '))
<span style="color: #004080;">string</span> <span style="color: #000000;">c</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">sq_add</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">(</span><span style="color: #008000;">' '</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><span style="color: #7060A8;">sq_mul</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">sq_ne</span><span style="color: #0000FF;">(</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: #008000;">'|'</span><span style="color: #0000FF;">-</span><span style="color: #008000;">' '</span><span style="color: #0000FF;">))</span>
printf(1,"%s\n%s\n%s\n\n",{a,b,c})
<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;">"%s\n%s\n%s\n\n"</span><span style="color: #0000FF;">,{</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: #000000;">c</span><span style="color: #0000FF;">})</span>
end procedure
<span style="color: #008080;">end</span> <span style="color: #008080;">procedure</span>
test("rosettacode", "raisethysword")
<span style="color: #000000;">test</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>
test("place", "palace")</lang>
<span style="color: #000000;">test</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"place"</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"palace"</span><span style="color: #0000FF;">)</span>
<!--</syntaxhighlight>-->
{{out}}
<pre>
Line 681 ⟶ 1,062:
 
=={{header|Python}}==
<langsyntaxhighlight Pythonlang="python">from difflib import ndiff
 
def levenshtein(str1, str2):
Line 701 ⟶ 1,082:
 
levenshtein("place","palace")
levenshtein("rosettacode","raisethysword")</langsyntaxhighlight>
{{out}}
<pre>
Line 714 ⟶ 1,095:
for a discussion of the code.
 
<langsyntaxhighlight lang="racket">#lang racket
 
(define (memoize f)
Line 733 ⟶ 1,114:
(min (add1 (levenshtein (rest s) t))
(add1 (levenshtein s (rest t)))
(add1 (levenshtein (rest s) (rest t)))))]))))</langsyntaxhighlight>
'''Demonstration:'''
<langsyntaxhighlight lang="racket">(levenshtein (string->list "rosettacode")
(string->list "raisethysword"))</langsyntaxhighlight>
{{out}}
<pre>8</pre>
Line 742 ⟶ 1,123:
===Complete version===
Now we extend the code from http://blog.racket-lang.org/2012/08/dynamic-programming-versus-memoization.html to show also the alignment. The code is very similar, but it stores the partial results (number of edits and alignment of each substring) in a lev structure.
<langsyntaxhighlight Racketlang="racket">#lang racket
 
(struct lev (n s t))
Line 785 ⟶ 1,166:
(values (lev-n result)
(list->string (lev-s result))
(list->string (lev-t result)))))</langsyntaxhighlight>
'''Demonstration:'''
<langsyntaxhighlight lang="racket">(let-values ([(dist exp-s exp-t)
(levenshtein "rosettacode" "raisethysword")])
(printf "levenshtein: ~a edits\n" dist)
(displayln exp-s)
(displayln exp-t))</langsyntaxhighlight>
{{out}}
<pre>levenshtein: 8 edits
Line 800 ⟶ 1,181:
(formerly Perl 6)
{{trans|Perl}}
<syntaxhighlight lang="raku" perl6line>sub align ( Str $σ, Str $t ) {
my @s = flat *, $σ.comb;
my @t = flat *, $t.comb;
Line 824 ⟶ 1,205:
}
.say for align 'rosettacode', 'raisethysword';</langsyntaxhighlight>
{{out}}
<pre>ro-settac-o-de
Line 832 ⟶ 1,213:
{{trans|Tcl}}
uses "lcs" from [[Longest common subsequence#Ruby|here]]
<langsyntaxhighlight lang="ruby">require 'lcs'
 
def levenshtein_align(a, b)
Line 867 ⟶ 1,248:
end
 
puts levenshtein_align("rosettacode", "raisethysword")</langsyntaxhighlight>
 
{{out}}
Line 881 ⟶ 1,262:
 
'''src/main.rs'''
<langsyntaxhighlight Rustlang="rust">extern crate edit_distance;
 
edit_distance("rosettacode", "raisethysword");</langsyntaxhighlight>
 
=={{header|Scala}}==
{{Out}}Best seen running in your browser either by [https://scastie.scala-lang.org/I8BAESkNTjukVPzsWOUyPA ScalaFiddle (ES aka JavaScript, non JVM)] or [https://scastie.scala-lang.org/I8BAESkNTjukVPzsWOUyPA].
<langsyntaxhighlight Scalalang="scala">import scala.collection.mutable
import scala.collection.parallel.ParSeq
 
Line 937 ⟶ 1,318:
println(alignment._2)
 
}</langsyntaxhighlight>
 
=={{header|Sidef}}==
{{trans|Perl}}
<langsyntaxhighlight lang="ruby">func align(s, t) {
s.chars!.prepend!('^')
t.chars!.prepend!('^')
 
var A = []
{|i| A[i][0]{@|<d s t>} = (i, s.ftslice(1, ).first(i).join, '~' * i) } << ^s
{|i| A[0][i]{@|<d s t>} = (i, '-' * i, t.ftslice(1, ).first(i).join) } << ^t
 
for i (1 .. s.end) {
Line 973 ⟶ 1,354:
}
 
align("rosettacode", "raisethysword").each { .say }</langsyntaxhighlight>
{{out}}
ro-settac-o-de
Line 980 ⟶ 1,361:
=={{header|Tcl}}==
{{tcllib|struct::list}}
<langsyntaxhighlight lang="tcl">package require struct::list
proc levenshtein/align {a b} {
lassign [struct::list longestCommonSubsequence [split $a ""] [split $b ""]]\
Line 1,015 ⟶ 1,396:
}
 
puts [levenshtein/align "rosettacode" "raisethysword"]</langsyntaxhighlight>
{{out}}
<pre>
Line 1,025 ⟶ 1,406:
{{trans|Kotlin}}
{{libheader|Wren-str}}
<syntaxhighlight lang="wren">import "./str" for Str
{{libheader|Wren-math}}
<lang ecmascript>import "/str" for Str
import "/math" for Math
 
var levenshteinAlign = Fn.new { |a, b|
Line 1,039 ⟶ 1,418:
for (j in 1..b.count) {
var temp = costs[i - 1][j - 1] + ((a[i - 1] == b[j - 1]) ? 0 : 1)
costs[i][j] = Mathtemp.min(1 + Math.min(costs[i - 1][j], .min(costs[i][j - 1]), temp)
}
}
Line 1,074 ⟶ 1,453:
result = levenshteinAlign.call("rosettacode","raisethysword")
System.print(result[0])
System.print(result[1])</langsyntaxhighlight>
 
{{out}}
Line 1,087 ⟶ 1,466:
=={{header|zkl}}==
{{trans|Java}}
<langsyntaxhighlight lang="zkl">fcn alignment(a,b){
a,b = a.toLower(), b.toLower();
costs := (a.len()+1).pump(List(),'wrap(a){ [1..b.len()].pump(List(a)) });
Line 1,111 ⟶ 1,490:
}
return(aPathRev.text.reverse(), bPathRev.text.reverse())
}</langsyntaxhighlight>
<langsyntaxhighlight lang="zkl">result := alignment("rosettacode", "raisethysword");
println(result[0]);
println(result[1]);</langsyntaxhighlight>
{{out}}
<pre>
1,983

edits