Penney Game - mapping macros to strings The SPOJ problem:


  Given a 40 character string representing outcomes of 40 coin tosses,
  find the frequency destribution of all the possible outcome triplets.
  So, for string like : HHHH....40 Hs ,the result is HHH : 38 and the
  rest 0. The exact input output format is given in the link.


My approach, as is clear from the code, is to iterate through the string and match all consecutive sub-strings of length 3, while increasing the frequency count.

My solution got accepted, but I am not really happy with what I have done here. As you can see, there is a lot of redundant code I could not remove.

For instance, if string "TTT" could be directly mapped to the macro TTT, somehow, and so on, a large number of lines of code could have been reduced. I know technically strings and macros are two different things, but is there some trick that I am missing?

#include&lt;stdio.h&gt;
#include&lt;stdlib.h&gt;
#include&lt;string.h&gt;
#include&lt;limits.h&gt;
#define TTT 0
#define TTH 1
#define THT 2
#define THH 3
#define HTT 4
#define HTH 5
#define HHT 6
#define HHH 7
void getCount(char str[] , int count[]){
    int i;
    for(i=0;i&lt;8;++i)
        count[i]=0;

    int l = strlen(str);
    for(i=2;i&lt;l;++i){
        if(strncmp(str+i-2 , "TTT" , 3)==0)
            ++count[TTT];
        if(strncmp(str+i-2 , "TTH" , 3)==0)
            ++count[TTH];
        if(strncmp(str+i-2 , "THT" , 3)==0)
            ++count[THT];
        if(strncmp(str+i-2 , "THH" , 3)==0)
            ++count[THH];
        if(strncmp(str+i-2 , "HTT" , 3)==0)
            ++count[HTT];
        if(strncmp(str+i-2 , "HTH" , 3)==0)
            ++count[HTH];
        if(strncmp(str+i-2 , "HHT" , 3)==0)
            ++count[HHT];
        if(strncmp(str+i-2 , "HHH" , 3)==0)
            ++count[HHH];
    }
}
int main()
{
    char str[41];
    int t,n,count[8],i;
    scanf("%d",&amp;t);
    while(t--){
        scanf("%d",&amp;n);
        printf("%d ",n);

        scanf("%s",str);
        getCount(str,count);

        for(i=0;i&lt;8;++i){
            printf("%d ",count[i]);
        }
        printf("\n");
    }
    return 0;
}
Associating a set of constants with corresponding strings is difficult in C.  One approach is to define a structure, such as

struct patterns {
    const char combination[4];
    int count;
};


Here we have space for a string and an integer to count occurrences.
Creating an array of these and initializing it gives us this:

struct patterns patterns[N_PATTERNS] = {
    {"HHH", 0}, {"HHT", 0}, {"HTH", 0}, {"HTT", 0},
    {"THH", 0}, {"THT", 0}, {"TTH", 0}, {"TTT", 0},
};


Then you can loop through the strings by accessing each array member and
incrementing the counts.  The count and string are kept together so that
indexing errors cannot happen.

Also, your main is too complicated.  Just reading the string from the
command line is easier.

Putting it together, gives me this:

#include &lt;stdio.h&gt;
#include &lt;string.h&gt;
#include &lt;stdlib.h&gt;

#define N_PATTERNS 8
struct patterns {
    const char combination[4];
    int count;
};

static int increment_occurance(struct patterns *p, const char *s)
{
    for (int i = 0; i &lt; N_PATTERNS; ++i) {
        if (!memcmp(s, p[i].combination, 3)) {
            p[i].count += 1;
            return 1;
        }
    }
    return 0;
}

static void count_occurances(struct patterns *p, const char *s)
{
    const char *end = s + strlen(s) - 2;

    for (; s &lt; end; ++s) {
        increment_occurance(p, s);
    }
}

int main(int argc, char **argv)
{
    struct patterns patterns[N_PATTERNS] = {
        {"HHH", 0}, {"HHT", 0}, {"HTH", 0}, {"HTT", 0},
        {"THH", 0}, {"THT", 0}, {"TTH", 0}, {"TTT", 0},
    };
    if (argc &lt; 2) {
        fprintf(stderr, "Usage: %s string\n", argv[0]);
        return EXIT_FAILURE;
    }
    count_occurances(patterns, argv[1]);

    for (int i = 0; i &lt; N_PATTERNS; ++i) {
        printf("%s %d\n", patterns[i].combination, patterns[i].count);
    }
    return EXIT_SUCCESS;
}


EDIT: note that we can use the more efficient memcmp instead of strncmp in increment_occurance.