Run-length encoding: Difference between revisions

→‎{{header|Perl}}: add advanced version that fully complies with the spec of the C solution
(→‎{{header|Perl}}: clean up & modernize)
(→‎{{header|Perl}}: add advanced version that fully complies with the spec of the C solution)
Line 2,434:
=={{header|Perl}}==
 
Simple version using ASCII numerals as shownlength markers, like the example in the task description (won't work correctly on input strings that already contain digits):
 
<lang perl>sub encode {
Line 2,444:
}</lang>
 
ModifiedImproved version that can take arbitrary byte strings as input (produces encoded byte strings that are compatible with the [[#C|C solution]]):
 
<lang perl>sub encode {
Line 2,453:
shift =~ s/(.)(.)/$2 x unpack("C", $1)/grse;
}</lang>
 
Further modified version that supports compact representation of longer non-repeating substrings, just like the [[#C|C solution]] (so should be fully compatible with that solution for both encoding and decoding):
 
<lang perl>sub encode {
my $str = shift;
my $ret = "";
my $nonrep = "";
while ($str =~ m/(.)\1{0,127}|\z/gs) {
my $len = length($&);
if (length($nonrep) && (length($nonrep) == 127 || $len != 1)) {
$ret .= pack("C", 128 + length($nonrep)) . $nonrep;
$nonrep = "";
}
if ($len == 1) { $nonrep .= $1 }
elsif ($len > 1) { $ret .= pack("C", $len) . $1 }
}
return $ret;
}
 
sub decode {
my $str = shift;
my $ret = "";
for (my $i = 0; $i < length($str);) {
my $len = unpack("C", substr($str, $i, 1));
if ($len <= 128) {
$ret .= substr($str, $i + 1, 1) x $len;
$i += 2;
}
else {
$ret .= substr($str, $i + 1, $len - 128);
$i += 1 + $len - 128;
}
}
return $ret;
}</lang>
 
Demonstration of the third version:
 
<lang perl>use Data::Dump qw(dd);
dd my $str = "XXXXXABCDEFGHIoooooooooooooooooooooooooAAAAAA";
dd my $enc = encode($str);
dd decode($enc);</lang>
 
{{out}}
<pre>
"XXXXXABCDEFGHIoooooooooooooooooooooooooAAAAAA"
"\5X\x89ABCDEFGHI\31o\6A"
"XXXXXABCDEFGHIoooooooooooooooooooooooooAAAAAA"
</pre>
 
=={{header|Perl 6}}==
Anonymous user