/* l7.c - Don Yang (uguu.org) 04/17/05 */ #include #include #include typedef union { char *w; int i; } Element; typedef struct { int size, max; Element *d; } List; List Index[26], AllWords; char *t, *text; int size, r, i, j, k, k0, k1, c0, column, margin; FILE *infile; int SLen(char *d) { for(r = 0; *d++; r++); return r; } void PutChar(int c) { putchar(c); } int ToLower(char *d) { return (int)(*d = (*d >= 'A' && *d <= 'Z') ? (*d += ((int)'a' - (int)'A')) : *d); } void PutStr(char *d) { for(; *d; PutChar(*d++)); } void FSeek(int o) { fseek(infile, 0, o); } void Reset(List *l) { l->d = (Element*)0; l->size = l->max = 0; } void AddToList(List *l, char *d) { Element *tmp, *a, *b; r = sizeof(Element); if( !l->d ) l->d = (Element*)malloc((l->max = 32) * r); if( l->d && l->size + 1 > l->max ) { if( (a = tmp = (Element*)malloc((l->max * 2) * r)) ) { b = l->d; for(r = l->size; r--; a++->i = b++->i); free(l->d); l->d = tmp; l->max *= 2; } } if( l->d ) l->d[l->size++].w = d; } void FreeList(List *l) { if( l->d ) free(l->d); } void PartialMatch(char *a, char *b) { for(k1 = 0; *a && *b && *a == *b; a++, b++, k1++); } int main(int argc, char **argv) { if( argc < 2 ) { PutStr(" [width] [...]\n"); } else { if( (infile = fopen(argv[1], "rb")) ) { FSeek(2); size = ftell(infile); if( size > 9 && (text = (char*)malloc(size + 1)) ) { FSeek(0); text[fread(text, 1, size, infile)] = 0; fclose(infile); for(i = 0; i < 26; Reset(&Index[i++])); Reset(&AllWords); for(t = text; size--; *(t++) = 0) { if( (*t >= 'A' && *t <= 'Z') || (*t >= 'a' && *t <= 'z') ) { AddToList(&Index[ToLower(t) - 97], (char*)AllWords.size); for(AddToList(&AllWords, t); size-- ? (*t >= 'A' && *t <= 'Z') || (*t >= 'a' && *t <= 'z') || (*t >= '0' && *t <= '9') : 0; t++) ToLower(t); size++; } } if( (size = (argc > 2) ? atoi(argv[2]) : 80) < 1 ) size = 80; if( argc > 3 ) { for(srand(time(0)); argc-- > 3;) { PutChar(10); column = SLen(t = argv[argc]); for(i = 0; i < column; i++) ToLower(t + i); PutStr(t); for(margin = size - 1 - SLen(argv[argc - 1]); column < margin; column += 1 + SLen(t)) { do { c0 = *t - 97; i = rand() % AllWords.size; if( c0 >= 0 && c0 < 26 ) { if( Index[c0].size ) { i = Index[c0].d[rand() % Index[c0].size].i; PartialMatch(t, AllWords.d[i].w); k0 = k1; for(j = 0; j < Index[c0].size / 2; j++) { k = Index[c0].d[rand() % Index[c0].size].i; PartialMatch(t, AllWords.d[k].w); if( k1 > k0 ) { i = k; k0 = k1; } } i = (i + 1) % AllWords.size; } } } while( column + 1 + SLen(AllWords.d[i].w) >= size ); PutChar(32); PutStr(t = AllWords.d[i].w); } } } else { column = size; for(i = 0; i < AllWords.size; i++) { if( (column + 1 + SLen(AllWords.d[i].w)) >= size ) { PutChar(10); column = 0; } else { PutChar(32); column++; } PutStr(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); } else { fclose(infile); } } else { PutStr("open error\n"); } } return 0; }