/* Problem 6--Triangles At first glance, I thought this was the hardest problem. After doing it, I no longer think this. I think this was very reasonable. This solution counts isosceles triangles and computes equilaterals as an equilateral is two isosceles's pasted together. */ #include #include #include #define MIN(a,b) ((a)<(b)?(a):(b)) int main (int argc, char **argv); int Read (void); int CountIsos (int i, int j, int v, int h); void Process (void); FILE *in, *out; int sz; /* size of letter matrix */ char **M; /* letter matrix */ int L[26], total; /* number of each kind of triangle, and the total ct*/ int main (int argc, char **argv) { int i=0; in = fopen ("prob6.in","r"); out = fopen ("prob6.out","w"); while (Read ()) { /* Read in a letter matrix */ Process (); /* Count triangles */ fprintf (out,"(%d) ",total); for (i=0;i<26;i++) /* If a letter ct is -1, that means it didn't */ if (L[i]!=-1) fprintf (out,"%d %c ",L[i],i+'A'); /* appear */ fprintf (out,"\n"); for (i=0; i < sz; i++) free (M[i]); free (M); } fclose (in); fclose (out); return EXIT_SUCCESS; } /* Read gets the next data set. It returns 0 if the data is exhausted, 1 otherwise. */ int Read (void) { int i, j; fscanf (in,"%d",&sz); /* get matrix size */ fgetc (in); /* get eoln character */ if (sz==0) return 0; memset (L,-1,sizeof L); /* Initialize L to -1's */ M = malloc (sz*sizeof (char *)); for (i=0; i < sz; i++) { /* Read in matrix characters */ M[i] = malloc (sz); for (j=0; j < sz; j++) { fscanf (in,"%c",&M[i][j]); L[M[i][j]-'A'] = 0; } fgetc (in); /* get eoln character */ } total = 0; return 1; } /* CountIsos accepts a position in the matrix and a vertical and horizontal direction and returns the number of isosceles triangles with that corner extending in that direction. */ int CountIsos (int i, int j, int v, int h) { int ct = 0, lev = 1, ok, k; /* ct is the number of triangles found. lev is the size of triangle currently sought. */ while (1) { if (i+v*lev >= sz) break; /* We're done if the matrix is too small */ if (i+v*lev < 0) break; /* the triangle. */ if (j+h*lev >= sz) break; if (j+h*lev < 0) break; ok = 1; for (k=0; ok && k <= lev; k++) /* Check whether this diagonal */ ok = M[i+(lev-k)*v][j+k*h] == M[i][j]; /* matches the corner */ if (!ok) break; L[M[i][j]-'A']++; /* If so, add another triangle! */ total++; ct++; lev++; } return ct; } /* Process counts the number of triangles in a given data set. */ void Process (void) { int i, j, a, b, c, d, eq; for (i=0; i < sz; i++) for (j=0; j < sz; j++) { a = CountIsos (i,j,1,1); /* For each position in the matrix, count*/ b = CountIsos (i,j,1,-1); /* the isosceles triangles cornered there*/ c = CountIsos (i,j,-1,1); d = CountIsos (i,j,-1,-1); /* The equilateral triangles can be */ eq = MIN(a,b) + MIN(a,c) + MIN(b,d) + MIN(c,d); /* found by pasting*/ L[M[i][j]-'A'] += eq; /* isosceles triangles together */ total += eq; } }