-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathhamlevdist.pl
executable file
·72 lines (66 loc) · 1.74 KB
/
hamlevdist.pl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
#! /usr/bin/perl
use strict;
use warnings;
use feature "say";
use List::Util qw[min max];
#Robin Greim, 4069775
#Berechnung der Hamming- und Levenshtein-Distanz zweier Sequenzen
#Syntax -> ./hamlevdist.pl <ham or lev> Seq1 Seq2
main();
sub main {
if ($ARGV[0] eq "ham") {
hammingD($ARGV[1], $ARGV[2]);
} elsif ($ARGV[0] eq "lev") {
say "Die Levenshtein-Distanz von $ARGV[1] und $ARGV[2] beträgt: " . levenshteinD($ARGV[1], $ARGV[2]) . ".";
} else {
say "Method specification is needed. Please insert ham (for hammilton-distance) or lev (for levenshtein-distance)."
}
}
sub hammingD {
my $seq1 = $_[0];
my $seq2 = $_[1];
my $dist = 0;
if (length($seq1) == length($seq2)) {
for (my $i = 0; $i < length($seq1); $i++) {
if (substr($seq1, $i, 1) ne substr($seq2, $i, 1)) {
$dist+=1;
}
}
say "Hamming-Distanz von $seq1 und $seq2 = $dist";
} else {
say "Fehler. Sequenzen nicht gleich lang.";
}
}
sub levenshteinD {
my $seq1 = $_[0];
my $seq2 = $_[1];
my $lseq1 = length($_[0]);
my $lseq2 = length($_[1]);
my %levmatrix;
my @ch1 = split (//, $seq1);
my @ch2 = split (//, $seq2);
my $penalty = 0;
for (my $i = 0; $i <= $lseq1; $i++) {
for (my $j = 0; $j <= $lseq2; $j++) {
$levmatrix {$i} {$j} = 0;
$levmatrix {0} {$j} = $j;
}
$levmatrix {$i} {0} = $i;
}
for (my $i = 1; $i <= $lseq1; $i++) {
for (my $j = 1; $j <= $lseq2; $j++) {
$penalty = (($ch1[$i-1] eq $ch2[$j-1]) ? 0 : 1);
if ($i == 0) {
return $j;
} elsif ($j == 0) {
return $i;
} else {
$levmatrix {$i}{$j} = min ( $levmatrix {$i - 1} {$j} + 1,
$levmatrix {$i} {$j - 1} + 1,
$levmatrix {$i - 1} {$j - 1}
+ $penalty );
}
}
}
return $levmatrix {$lseq1}{$lseq2};
}