/* Problem 8--Acceptable Strings This was a straightforward emulation of a finite state automaton. There was nothing particularly tricky about this one. */ #include #include typedef struct ST { /* state info: where do I go on 0 and 1, and is it a final state? */ int on0, on1, f; } ST; int main (int argc, char **argv); void Process (FILE *out, ST *states, int N, int *cs); void ProcessCase (FILE *out, ST *states, int N); int next (char *bstr); int main (int argc, char **argv) { int r, N, S, F, i, f, cs; FILE *in, *out; ST *states; in = fopen ("prob8.in","r"); out = fopen ("prob8.out","w"); cs = 0; for (;;) { fscanf (in,"%d %d %d",&N,&S,&F); if (N+S+F==0) break; states = malloc (S*sizeof (ST)); i = 0; /* Read in states, and scale: the problem has them start */ for (;;) { /* at 1; we will start them at 0. */ if (i==S) break; fscanf (in,"%d %d",&states[i].on0,&states[i].on1); states[i].on0--; states[i].on1--; states[i].f = 0; i++; } i = 0; /* Read in the final states. */ for (;;) { if (i==F) break; fscanf (in,"%d",&f); states[f-1].f = 1; i++; } Process (out,states,N,&cs); free (states); } fclose (in); fclose (out); r = EXIT_SUCCESS; return r; } /* Process computes the number strings the machine accepts and prints the results to out. states is the list of states, N is the maximum string length and cs is the case number. */ void Process (FILE *out, ST *states, int N, int *cs) { int i; fprintf (out,"Case %d:\n",++*cs); i = 0; for (;;) { if (i > N) break; /* Process them one at a time. */ ProcessCase (out,states,i); i++; } } /* ProcessCase prints to out the number of strings of length N accepted by the machine represented by states. */ void ProcessCase (FILE *out, ST *states, int N) { char bstr[11]; int i, ct, st; i = 0; /* Initialize string to all 0's. */ for (;;) { if (i==N) break; bstr[i] = '0'; i++; } bstr[N] = 0; ct = 0; for (;;) { i = st = 0; for (;;) { /* go through the machine for this string */ if (i==N) break; if (bstr[i]=='0') { st = states[st].on0; } else { st = states[st].on1; } i++; } ct += states[st].f; /* Was it accepted? */ if (next (bstr)) break; /* Get the next string to try. */ } if (ct==1) { fprintf (out," Length = %d, 1 string accepted.\n",N); } else { fprintf (out," Length = %d, %d strings accepted.\n",N,ct); } } /* next updates bstr to contain the next bit string to try. It returns true if there are no more to try, false otherwise. */ int next (char *bstr) { int done, i; i = 0; for (;;) { if (bstr[i] == '0' || bstr[i] == 0) break; bstr[i] = '0'; i++; } if (bstr[i] == '0') { /* If the string is not all 1's, we have more */ bstr[i] = '1'; /* to try. */ done = 0; } else { done = 1; } return done; }