Run-length encoding

You are encouraged to solve this task according to the task description, using any language you may know.


Task

Given a string containing uppercase characters (A-Z), compress repeated 'runs' of the same character by storing the length of that run, and provide a function to reverse the compression.

The output can be anything, as long as you can recreate the input with it.



Example

 Input: WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW
 Output: 12W1B12W3B24W1B14W


Note: the encoding step in the above example is the same as a step of the Look-and-say sequence.




use RegEx;
 
class RunLengthEncoding {
  function : Main(args : String[]) ~ Nil {
    input := "WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW";
 
    encoded := Encode(input);
    "encoding: {$encoded}"->PrintLine();
    test := encoded->Equals("12W1B12W3B24W1B14W");
    "encoding match: {$test}"->PrintLine();
 
    decoded := Decode(encoded);
    test := input->Equals(decoded);
    "decoding match: {$test}"->PrintLine();
  }
 
  function : Encode(source : String) ~ String {
    dest := "";
    each(i : source) {
      runLength := 1;
      while(i+1 < source->Size() & source->Get(i) = source->Get(i+1)) {
        runLength+= 1;
        i+= 1;
      };
      dest->Append(runLength);
      dest->Append(source->Get(i));
    };
 
    return dest;
  }
 
  function : Decode(source : String) ~ String {
    output := "";
    regex := RegEx->New("[0-9]+|([A-Z]|[a-z])");
    found := regex->Find(source);
    count : Int;
    each(i : found) {
      if(i % 2 = 0) {
        count := found->Get(i)->As(String)->ToInt();
      }
      else {
        letter := found->Get(i)->As(String);
        while(count <> 0) {
          output->Append(letter);
          count -= 1;
        };
      };
    };
 
    return output;
  }
}