patterncMinor
Penney Game - mapping macros to strings
Viewed 0 times
penneymacrosgamemappingstrings
Problem
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
#include
#include
#include
#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<8;++i)
count[i]=0;
int l = strlen(str);
for(i=2;i<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",&t);
while(t--){
scanf("%d",&n);
printf("%d ",n);
scanf("%s",str);
getCount(str,count);
for(i=0;i<8;++i){
printf("%d ",count[i]);
}
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
#include
#include
#include
#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<8;++i)
count[i]=0;
int l = strlen(str);
for(i=2;i<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",&t);
while(t--){
scanf("%d",&n);
printf("%d ",n);
scanf("%s",str);
getCount(str,count);
for(i=0;i<8;++i){
printf("%d ",count[i]);
}
Solution
Associating a set of constants with corresponding strings is difficult in C. One approach is to define a structure, such as
Here we have space for a string and an integer to count occurrences.
Creating an array of these and initializing it gives us this:
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
command line is easier.
Putting it together, gives me this:
EDIT: note that we can use the more efficient
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 thecommand line is easier.
Putting it together, gives me this:
#include
#include
#include
#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 < 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 < 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 < 2) {
fprintf(stderr, "Usage: %s string\n", argv[0]);
return EXIT_FAILURE;
}
count_occurances(patterns, argv[1]);
for (int i = 0; i < 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.Code Snippets
struct patterns {
const char combination[4];
int count;
};struct patterns patterns[N_PATTERNS] = {
{"HHH", 0}, {"HHT", 0}, {"HTH", 0}, {"HTT", 0},
{"THH", 0}, {"THT", 0}, {"TTH", 0}, {"TTT", 0},
};#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#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 < 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 < 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 < 2) {
fprintf(stderr, "Usage: %s string\n", argv[0]);
return EXIT_FAILURE;
}
count_occurances(patterns, argv[1]);
for (int i = 0; i < N_PATTERNS; ++i) {
printf("%s %d\n", patterns[i].combination, patterns[i].count);
}
return EXIT_SUCCESS;
}Context
StackExchange Code Review Q#51747, answer score: 4
Revisions (0)
No revisions yet.