The weekly challenge 296 - Task 1: String Compression

 1 #!/usr/bin/env perl
 2 # https://theweeklychallenge.org/blog/perl-weekly-challenge-296/#TASK1
 3 #
 4 # Task 1: String Compression
 5 # ==========================
 6 #
 7 # You are given a string of alphabetic characters, $chars.
 8 #
 9 # Write a script to compress the string with run-length encoding, as shown in
10 # the examples.
11 #
12 # A compressed unit can be either a single character or a count followed by a
13 # character.
14 #
15 # BONUS: Write a decompression function.
16 #
17 ## Example 1
18 ##
19 ## Input: $chars = "abbc"
20 ## Output: "a2bc"
21 #
22 ## Example 2
23 ##
24 ## Input: $chars = "aaabccc"
25 ## Output: "3ab3c"
26 #
27 ## Example 3
28 ##
29 ## Input: $chars = "abcc"
30 ## Output: "ab2c"
31 #
32 ############################################################
33 ##
34 ## discussion
35 ##
36 ############################################################
37 #
38 # For compression, we count the same character. If another character
39 # comes up, we either have more than one, which we replace by the
40 # number and the character, or we have exactly one which we just add
41 # to the end.
42 # For decompression, if there is a number at the beginning of the string,
43 # we just take it as the count (otherwise we take 1 as the count), and
44 # multiply the next character accordingly.
45 use strict;
46 use warnings;
47 
48 foreach my $string ( ("abbc", "aaabccc", "abcc") ) {
49    print "Input: $string\n";
50    my $compressed = string_compression($string);
51    print "Output: $compressed\n";
52    print "Uncompressed: " . string_decompression($compressed) . "\n";
53 }
54 
55 sub string_compression {
56    my $chars = shift;
57    my $count = 1;
58    my ($prev, @rest) = split //, $chars;
59    my $result = "";
60    while(@rest) {
61       my $next = shift @rest;
62       if($next eq $prev) {
63          $count++;
64       } else {
65          if($count > 1) {
66             $result .= "$count$prev";
67             $count = 1;
68          } else {
69             $result .= $prev;
70          }
71          $prev = $next;
72       }
73    }
74    if($count > 1) {
75       $result .= $count;
76    }
77    $result .= $prev;
78    return $result;
79 }
80 
81 sub string_decompression {
82    my $input = shift;
83    my $result = "";
84    my $count;
85    while(length($input)) {
86       $count = 1;
87       if($input =~ m/^\d/) {
88          $input =~ s/(\d+)//;
89          $count = $1;
90       }
91       $input =~ s/^(.)//;
92       my $char = $1;
93       $result .= $char x $count;
94    }
95    return $result;
96 }