/* l5.c - Don Yang (uguu.org) 04/17/05 */ #include #include #include #include typedef union { char *w; int i; } Element; typedef struct { int size, max; Element *d; } List; List Index[26], AllWords; char *t; int SLen(char *d) { int r; for(r = 0; *d != '\0'; d++, r++); return r; } void PutStr(char *d) { printf("%s", d); } void Reset(List *l) { l->d = NULL; l->size = l->max = 0; } void AddToList(List *l, char *d) { Element *tmp, *a, *b; int size; if( l->d == NULL ) { if( (l->d = (Element*)malloc((l->max = 32) * sizeof(Element))) == NULL ) return; } if( l->size + 1 > l->max ) { if( (tmp = (Element*)malloc((l->max * 2) * sizeof(Element))) == NULL ) return; a = tmp; b = l->d; for(size = l->size; size-- > 0; a++->i = b++->i); free(l->d); l->d = tmp; l->max <<= 1; } l->d[l->size++].w = d; } void FreeList(List *l) { if( l->d != NULL ) free(l->d); } void Tokenize(char *text, int size) { for(t = text; size-- > 0; *(t++) = '\0') { if( isalpha(*t) ) { *t = tolower(*t); AddToList(&Index[*t - 'a'], (char*)AllWords.size); AddToList(&AllWords, t); for(; size-- > 0 ? isalnum(*t) : 0; t++) *t = tolower(*t); size++; } } } int PartialMatch(char *a, char *b) { int c; for(c = 0; *a != '\0' && *b != '\0' && *a == *b; a++, b++, c++); return c; } int main(int argc, char **argv) { FILE *infile; char *text; int size, i, j, k, k0, k1, a, c0, column, margin; if( argc < 2 ) return printf("%s [width] [...]\n", *argv); if( (infile = fopen(argv[1], "rb")) == NULL ) return printf("Can not open %s\n", argv[1]); fseek(infile, 0, SEEK_END); if( (size = ftell(infile)) < 1 ) { fclose(infile); return printf("%s too small\n", argv[1]); } fseek(infile, 0, SEEK_SET); if( (text = (char*)malloc(size + 1)) == NULL ) return fclose(infile); fread(text, size, 1, infile); text[size] = '\0'; fclose(infile); for(i = 0; i < 26; Reset(&Index[i++])); Reset(&AllWords); Tokenize(text, size); if( (size = (argc > 2) ? atoi(argv[2]) : 80) < 1 ) size = 80; srand(time(NULL)); if( argc > 3 ) { for(a = argc; a-- > 3;) { putchar('\n'); t = argv[a]; column = SLen(t); for(i = 0; i < column; i++) t[i] = tolower(t[i]); PutStr(t); margin = size - 1 - SLen(argv[a - 1]); while( column < margin ) { do { c0 = *t - 'a'; do { i = rand() % AllWords.size; if( c0 < 0 || c0 >= 26 ) break; if( Index[c0].size == 0 ) break; i = Index[c0].d[rand() % Index[c0].size].i; k0 = PartialMatch(t, AllWords.d[i].w); for(j = 0; j < Index[c0].size / 2; j++) { k = Index[c0].d[rand() % Index[c0].size].i; if( (k1 = PartialMatch(t, AllWords.d[k].w)) > k0 ) { i = k; k0 = k1; } } i = (i + 1) % AllWords.size; } while(0); } while( column + 1 + SLen(AllWords.d[i].w) >= size ); putchar(' '); PutStr(t = AllWords.d[i].w); column += 1 + SLen(t); } } } else { column = size; for(i = 0; i < AllWords.size; i++) { if( (column + 1 + SLen(AllWords.d[i].w)) >= size ) { putchar('\n'); column = 0; } else { putchar(' '); column++; } printf(AllWords.d[i].w); column += SLen(AllWords.d[i].w); } } PutStr("\n\n"); for(i = 0; i < 26; FreeList(&Index[i++])); FreeList(&AllWords); free(text); return 0; }