Levenshtein distance/Alignment: Difference between revisions
Content deleted Content added
→Tcl: Added implementation |
→{{header|Racket}}: Extends solution to show the alignments |
||
Line 269: | Line 269: | ||
=={{header|Racket}}== |
=={{header|Racket}}== |
||
==Simple version (no aligment)== |
|||
{{incorrect|Racket|This task ''explicitly'' requires the computation of indications of the delta operations. It also asks for the indications to be printed. Was this intended as a solution for the separate [[Levenshtein distance]] task?}} |
|||
First we will analyze this solution that only computes the distance. |
|||
See http://blog.racket-lang.org/2012/08/dynamic-programming-versus-memoization.html |
See http://blog.racket-lang.org/2012/08/dynamic-programming-versus-memoization.html |
||
for a discussion of the code. |
for a discussion of the code. |
||
Line 294: | Line 294: | ||
(add1 (levenshtein s (rest t))) |
(add1 (levenshtein s (rest t))) |
||
(add1 (levenshtein (rest s) (rest t)))))]))))</lang> |
(add1 (levenshtein (rest s) (rest t)))))]))))</lang> |
||
Demonstration: |
'''Demonstration:''' |
||
<lang racket>(levenshtein (string->list "rosettacode") |
<lang racket>(levenshtein (string->list "rosettacode") |
||
(string->list "raisethysword"))</lang> |
(string->list "raisethysword"))</lang> |
||
{{out}} |
|||
<pre>8</pre> |
|||
==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. |
|||
<lang Racket>#lang racket |
|||
(struct lev (n s t)) |
|||
(define (lev-add old n sx tx) |
|||
(lev (+ n (lev-n old)) |
|||
(cons sx (lev-s old)) |
|||
(cons tx (lev-t old)))) |
|||
(define (min/lev-n . l) |
|||
(car (sort l < #:key lev-n))) |
|||
(define (list-repeat n v) |
|||
(build-list n (lambda (_) v))) |
|||
(define (memoize f) |
|||
(local ([define table (make-hash)]) |
|||
(lambda args |
|||
(dict-ref! table args (λ () (apply f args)))))) |
|||
(define levenshtein/list |
|||
(memoize |
|||
(lambda (s t) |
|||
(cond |
|||
[(and (empty? s) (empty? t)) |
|||
(lev 0 '() '())] |
|||
[(empty? s) |
|||
(lev (length t) (list-repeat (length t) #\-) t)] |
|||
[(empty? t) |
|||
(lev (length s) s (list-repeat (length s) #\-))] |
|||
[else |
|||
(if (equal? (first s) (first t)) |
|||
(lev-add (levenshtein/list (rest s) (rest t)) |
|||
0 (first s) (first t)) |
|||
(min/lev-n (lev-add (levenshtein/list (rest s) t) |
|||
1 (first s) #\-) |
|||
(lev-add (levenshtein/list s (rest t)) |
|||
1 #\- (first t)) |
|||
(lev-add (levenshtein/list (rest s) (rest t)) |
|||
1 (first s) (first t))))])))) |
|||
(define (levenshtein s t) |
|||
(let ([result (levenshtein/list (string->list s) |
|||
(string->list t))]) |
|||
(values (lev-n result) |
|||
(list->string (lev-s result)) |
|||
(list->string (lev-t result)))))</lang> |
|||
'''Demonstration:''' |
|||
<lang racket>(let-values ([(dist exp-s exp-t) |
|||
(levenshtein "rosettacode" "raisethysword")]) |
|||
(printf "levenshtein: ~a edits\n" dist) |
|||
(displayln exp-s) |
|||
(displayln exp-t))</lang> |
|||
{{out}} |
|||
<pre>levenshtein: 8 edits |
|||
r-oset-taco-de |
|||
raisethysword-</pre> |
|||
=={{header|Tcl}}== |
=={{header|Tcl}}== |