File Coverage

blib/lib/LCS/Similar.pm
Criterion Covered Total %
statement 45 45 100.0
branch 16 16 100.0
condition 19 20 100.0
subroutine 9 9 100.0
pod 4 4 100.0
total 93 94 100.0


line stmt bran cond sub pod time code
1             package LCS::Similar;
2              
3 2     2   13366 use 5.010001;
  2         7  
4 2     2   12 use strict;
  2         4  
  2         53  
5 2     2   11 use warnings;
  2         11  
  2         1401  
6             our $VERSION = '0.04';
7             #use utf8;
8             #use Data::Dumper;
9              
10             sub new {
11 12     12 1 2131 my $class = shift;
12             # uncoverable condition false
13 12 100 66     87 bless @_ ? @_ > 1 ? {@_} : {%{$_[0]}} : {}, ref $class || $class;
  4 100       30  
14             }
15              
16             sub LCS {
17 51     51 1 322363 my ($self, $a, $b, $compare, $threshold) = @_;
18              
19 51         136 my ($amin, $amax, $bmin, $bmax) = (0, $#$a, 0, $#$b);
20              
21 51   100     364 while ($amin <= $amax and $bmin <= $bmax and $a->[$amin] eq $b->[$bmin]) {
      100        
22 101         132 $amin++;
23 101         361 $bmin++;
24             }
25 51   100     245 while ($amin <= $amax and $bmin <= $bmax and $a->[$amax] eq $b->[$bmax]) {
      100        
26 111         128 $amax--;
27 111         409 $bmax--;
28             }
29              
30 51   100 8029   254 $compare //= sub { $_[0] eq $_[1] };
  8029         17042  
31              
32             #my $m = scalar @$a;
33 51         104 my $m = $amax - $amin +1;
34             #my $n = scalar @$b;
35 51         73 my $n = $bmax - $bmin +1;
36              
37 51         88 my $c = [];
38 51         78 my ($i,$j);
39 51         130 for ($i=0; $i<=$m; $i++) {
40 463         766 for ($j=0;$j<=$n;$j++) {
41 9373         15633 $c->[$i][$j]=0;
42             }
43             }
44 51         105 for ($i=1; $i<=$m; $i++) { # my $j ($bmin..$bmax)
45 412         726 for ($j=1; $j<=$n; $j++) {
46 8546         14469 $c->[$i][$j] = $self->max3(
47             &$compare(
48             $a->[$amin + $i-1],
49             $b->[$bmin + $j-1],
50             $threshold
51             ) + $c->[$i-1][$j-1],
52             $c->[$i][$j-1],
53             $c->[$i-1][$j],
54             );
55             }
56             }
57 51         144 my $path = $self->_lcs($a, $b, $amin, $bmin, $c, $m, $n,[],$compare, $threshold);
58             ##return $path;
59             return [
60 51         586 map([$_ => $_], 0 .. ($bmin-1)), ## no critic qw(BuiltinFunctions::RequireBlockMap)
61             @$path,
62             map([++$amax => $_], ($bmax+1) .. $#$b) ## no critic qw(BuiltinFunctions::RequireBlockMap)
63             ];
64             }
65              
66              
67 8 100   8 1 922 sub max { ($_[1] > $_[2]) ? $_[1] : $_[2]; }
68              
69             sub max3 {
70 8558 100   8558 1 94467 ($_[1] >= $_[2])
    100          
    100          
71             ? ($_[1] >= $_[3]
72             ? $_[1] : $_[3]
73             )
74             : ($_[2] >= $_[3]
75             ? $_[2] : $_[3]
76             );
77             }
78              
79             sub _lcs {
80 51     51   134 my ($self, $a, $b, $amin, $bmin, $c, $i, $j, $L, $compare, $threshold) = @_;
81              
82 51   100     193 while ($i > 0 && $j > 0) {
83 423 100       746 if ( &$compare($a->[$amin + $i-1],$b->[$bmin + $j-1], $threshold) ) {
    100          
84 228         23002 unshift @{$L},[$amin + $i-1, $bmin + $j-1];
  228         525  
85 228         298 $i--;
86 228         606 $j--;
87             }
88             elsif ( $c->[$i][$j] == $c->[$i-1][$j] ) {
89 160         7502 $i--;
90             }
91             else {
92 35         500 $j--;
93             }
94             }
95 51         110 return $L;
96             }
97              
98             1;
99              
100             __END__