use strict;
use warnings;
use Data::Dumper;
my $str1 = 'Perlmonks is the best perl community';
my $str2 = 'Perlmonks is one of the best community of perl users';
if ( $str1 eq $str2 ) {
print "$str1\n$str2\n";
exit;
}
my @wl1 = split /\s+/, $str1;
my @wl2 = split /\s+/, $str2;
my $diff_str1 = '';
my $diff_str2 = '';
my %wc1;
my %wc2;
foreach my $word (@wl1) {
$wc1{$word}++;
}
foreach my $word (@wl2) {
$wc2{$word}++;
}
while (@wl1 || @wl2) {
my $word1 = '';
my $word2 = '';
# being sloppy and not decrementing word counts for new words
# since we only use them for moves
while (!$wc2{$word1}) {
$diff_str1 .= "<$word1> " if $word1;
$wc1{$word1}-- if $word1;
$word1 = ''; # prevent fall through if this is the last word
last if !@wl1;
$word1 = shift @wl1;
}
while (!$wc1{$word2}) {
$diff_str2 .= "<$word2> " if $word2;
$wc2{$word2}-- if $word2;
$word2 = '';
last if !@wl2;
$word2 = shift @wl2;
}
if ( $word1 && $word2 && $word1 eq $word2 ) {
$diff_str1 .= $word1 . ' '; # pairing the word from the origional string with it's output
$diff_str2 .= $word2 . ' '; # lets us do things like case insensitive, but preserving match later
}
else {
$diff_str1 .= "[$word1] " if $word1;
$diff_str2 .= "[$word2] " if $word2;
}
$wc1{$word2}--;
$wc2{$word1}--;
}
print "$diff_str1\n$diff_str2\n";
####
Perlmonks is the best [perl] [community]
Perlmonks is the best [community] [perl]
####
$str1 = 'Perlmonks is the best perl perl community';
$str2 = 'Perlmonks is one of the best community of perl users';
---------
Perlmonks is the best [perl] [community]
Perlmonks is the best [community] [perl]