lzw_encoding.pl 1.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. #!/usr/bin/perl
  2. use 5.020;
  3. use strict;
  4. use warnings;
  5. use constant DICT_SIZE => 256;
  6. use experimental qw(signatures);
  7. binmode(STDOUT, ':utf8');
  8. sub create_dictionary() {
  9. my %dictionary;
  10. foreach my $i (0 .. DICT_SIZE - 1) {
  11. $dictionary{chr $i} = chr $i;
  12. }
  13. return %dictionary;
  14. }
  15. sub compress ($uncompressed) {
  16. my $dict_size = DICT_SIZE;
  17. my %dictionary = create_dictionary();
  18. my $w = '';
  19. my @compressed;
  20. foreach my $c (split(//, $uncompressed)) {
  21. my $wc = $w . $c;
  22. if (exists $dictionary{$wc}) {
  23. $w = $wc;
  24. }
  25. else {
  26. push @compressed, $dictionary{$w};
  27. $dictionary{$wc} = chr($dict_size++);
  28. $w = $c;
  29. }
  30. }
  31. if ($w ne '') {
  32. push @compressed, $dictionary{$w};
  33. }
  34. return @compressed;
  35. }
  36. sub decompress (@compressed) {
  37. my $dict_size = DICT_SIZE;
  38. my %dictionary = create_dictionary();
  39. my $w = shift(@compressed);
  40. my $result = $w;
  41. foreach my $k (@compressed) {
  42. my $entry = do {
  43. if (exists $dictionary{$k}) {
  44. $dictionary{$k};
  45. }
  46. elsif ($k eq chr($dict_size)) {
  47. $w . substr($w, 0, 1);
  48. }
  49. else {
  50. die "Invalid compression: $k";
  51. }
  52. };
  53. $result .= $entry;
  54. $dictionary{chr($dict_size++)} = $w . substr($entry, 0, 1);
  55. $w = $entry;
  56. }
  57. return $result;
  58. }
  59. my $orig = 'TOBEORNOTTOBEORTOBEORNOT';
  60. my @compressed = compress($orig);
  61. my $enc = join('', @compressed);
  62. my $dec = decompress(@compressed);
  63. say "Encoded: $enc";
  64. say "Decoded: $dec";
  65. say '-' x 33;
  66. if ($dec ne $orig) {
  67. die "Decompression failed!";
  68. }
  69. printf("Original size : %s\n", length($orig));
  70. printf("Compressed size : %s\n", length($enc));
  71. printf("Compression ratio : %.2f%%\n", (length($orig) - length($enc)) / length($orig) * 100);