List-1 List-2 one one two three three three four four five six six seven eight eighttt nine nine
Looking to output
one | one PASS two | * FAIL MISSING three | three PASS * | three FAIL EXTRA four | four PASS five | * FAIL MISSING six | six PASS * | seven FAIL EXTRA eight | eighttt FAIL INVALID nine | nine PASS
Actually the return from my current solution is a reference to the two modified lists and a reference to a "fail" list describing the failure for the index as either "no fail", "missing", "extra", or "invalid" which is also (obviously) fine output.
My current solution is:
sub compare {
local $thisfound = shift;
local $thatfound = shift;
local @thisorig = @{ $thisfound };
local @thatorig = @{ $thatfound };
local $best = 9999;
foreach $n (1..6) {
local $diff = 0;
local @thisfound = @thisorig;
local @thatfound = @thatorig;
local @fail = ();
for (local $i=0;$i<scalar(@thisfound) || $i<scalar(@thatfound);$i++) {
if($thisfound[$i] eq $thatfound[$i]) {
$fail[$i] = 'NO_FAIL';
next;
}
if($n == 1) { # 1 2 3
next unless __compare_missing__();
next unless __compare_extra__();
next unless __compare_invalid__();
} elsif($n == 2) { # 1 3 2
next unless __compare_missing__();
next unless __compare_invalid__();
next unless __compare_extra__();
} elsif($n == 3) { # 2 1 3
next unless __compare_extra__();
next unless __compare_missing__();
next unless __compare_invalid__();
} elsif($n == 4) { # 2 3 1
next unless __compare_extra__();
next unless __compare_invalid__();
next unless __compare_missing__();
} elsif($n == 5) { # 3 1 2
next unless __compare_invalid__();
next unless __compare_missing__();
next unless __compare_extra__();
} elsif($n == 6) { # 3 2 1
next unless __compare_invalid__();
next unless __compare_extra__();
next unless __compare_missing__();
}
push @fail,'INVALID';
$diff += 1;
}
if ($diff<$best) {
$best = $diff;
@thisbest = @thisfound;
@thatbest = @thatfound;
@failbest = @fail;
}
}
return (\@thisbest,\@thatbest,\@failbest)
}
sub __compare_missing__ {
my $j;
### Does that command match a later this command? ###
### If so most likely a MISSING command ###
for($j=$i+1;$j<scalar(@thisfound);$j++) {
if($thisfound[$j] eq $thatfound[$i]) {
$diff += $j-$i;
for ($i..$j-1) { push(@fail,'MISSING'); }
@end = @thatfound[$i..$#thatfound];
@thatfound = @thatfound[0..$i-1];
for ($i..$j-1) { push(@thatfound,'*'); }
push(@thatfound,@end);
$i=$j-1;
last;
}
}
$j == scalar(@thisfound);
}
sub __compare_extra__ {
my $j;
### Does this command match a later that command? ###
### If so, most likely an EXTRA command ###
for($j=$i+1;$j<scalar(@thatfound);$j++) {
if($thatfound[$j] eq $thisfound[$i]) {
$diff += $j-$i;
for ($i..$j-1) { push(@fail,'EXTRA'); }
@end = @thisfound[$i..$#thisfound];
@thisfound = @thisfound[0..$i-1];
for ($i..$j-1) { push (@thisfound,'*'); }
push(@thisfound,@end);
$i=$j-1;
last;
}
}
$j == scalar(@thatfound);
}
sub __compare_invalid__ {
my $j;
### Do later commands match? ###
### If so most likely an INVALID command ###
for($j=$i+1;$j<scalar(@thisfound);$j++) {
if($thisfound[$j] eq $thatfound[$j]) {
$diff += $j-$i;
for ($i..$j-1) { push(@fail,'INVALID'); }
$i=$j-1;
last;
}
}
$j == scalar(@thisfound);
}
But this isn't perfect ... who wants to simplify and improve? Specifically ... within a single data set, one order of searching is better for a subset and another order is better for a different subset.