Wednesday, January 11, 2012

Run Length Encoding of String

You have a character array containing upper and lower case letters of the English alphabet. Do a run-length encoding of the array.
e.g. if the array is aaaBBAcc, its run-length encoding is a3B2Ac2.
Function prototype is
char * runLengthEncode(char * A)
Note: Make sure you take care of critical cases like when the count of a character exceeds 9

http://algorithms.tutorialhorizon.com/string-compression-using-count-of-repeated-characters-run-length-encoding/
http://www.geeksforgeeks.org/run-length-encoding/

Method:
You will need to make two pointers for this, one stays at an index and one moves ahead till we keep finding duplicates for that character. Once the count has been obtained the next index of the 1st pointer is replaced by the count, if the count is in two digits as many characters are replaced. Then both the pointers are incremented.

At the beginning of each loop the character at the 1st index is replaced by that of the second index. In the beginning both are same so it does not matter and if the string contains no repeated chars then we just replace the character.

Code:
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// function that finds number of digits in the
// repeated count of the character
int numberOfDigits(int num)
{
    int digits=0;
    while(num!=0)
    {
        num/=10;
        digits++;
    }
    return digits;
}

void replaceDuplicateByCount(char *str)
{
   //return if the string is null
   if(*str=='\0')
     return;

   int len=strlen(str);
   int j=0;
   //i and j are the indices used as pointers

   for(int i=0;i < len;i++)
   {
       if(str[j]=='\0')
           {
          str[i]='\0';
                  break;
           }

           //replace i by j
       str[i]=str[j];
       int count=0;
      
           // find out the repeated count if the
           // character
       while(str[j]==str[j+1])
       {
          j++;
          count++;
       }
           // if the character appears 4 times then we
           // get count as 3 because it is repeated that many times
       if(count!=0)
       {
           i++;
                   //increment count to actual character occurrence
           count++;
                   //find number of digits
           int digits=numberOfDigits(count);
                  
                   // if there is only 1 digit then we need go through
                   // the loop, here we extract the first digit and
                   // store it in the string
           while(digits!=1)
           {
              int divisor=(int)pow((double)10,digits-1);
              int num = count/divisor;
              count=count%divisor;
              str[i]=(char)(num+48);
              i++;
              digits--;
           }
           str[i]=(char)(count+48);                        
        }
    
        j++;
   }
}

int main()
{
  char arr[] = "aaaabbbbbbbbccd";
  int x,y;
  replaceDuplicateByCount(arr);
  //get2NonRepeatingNos(arr, 12, &x, &y);
  printf(" The non-repeating elements are %s",arr);
  getchar();
  return 0;
}

Note: If we want to print numbers before the alphabets then the code should be changed as follows:
void replaceDuplicateByCount(char *str)
{
   //return if the string is null
   if(*str=='\0')
     return;

   int len=strlen(str);
   int j=0;
   //i and j are the indices used as pointers

   for(int i=0;i < len;)
   {
       if(str[j]=='\0')
           {
          str[i]='\0';
                  break;
           }

           //replace i by j
      // str[i]=str[j];
       int count=0;
     
           // find out the repeated count if the
           // character
       while(str[j]==str[j+1])
       {
          j++;
          count++;
       }
           // if the character appears 4 times then we
           // get count as 3 because it is repeated that many times
       if(count!=0)
       {
          // i++;
                   //increment count to actual character occurrence
           count++;
                   //find number of digits
           int digits=numberOfDigits(count);
                 
                   // if there is only 1 digit then we need go through
                   // the loop, here we extract the first digit and
                   // store it in the string
           while(digits!=1)
           {
              int divisor=(int)pow((double)10,digits-1);
              int num = count/divisor;
              count=count%divisor;
              str[i]=(char)(num+48);
              i++;
              digits--;
           }
           str[i++]=(char)(count+48);
           str[i]=str[j];
           i++;  
                    
        }
        j++;
     
   }
}

No comments:

Post a Comment