Annotation of researchv10no/games/ana.c, revision 1.1

1.1     ! root        1: #include       <stdlib.h>
        !             2: #include       <string.h>
        !             3: #include       <stdio.h>
        !             4: #include       <ctype.h>
        !             5: #include       <signal.h>
        !             6: 
        !             7: #ifndef WORD_LIST
        !             8: #define WORD_LIST      "/usr/lib/spell/amspell"
        !             9: #endif
        !            10: #ifndef WORD_LISTB
        !            11: #define WORD_LISTB     "/usr/lib/spell/brspell"
        !            12: #endif
        !            13: /* the next string should be the first word in spell's stop list */
        !            14: #define STOPWORD       "Argentinan"
        !            15: #define        VOWELS          "aeiouy"
        !            16: #define        ALPHAS          26
        !            17: #define        LENLIMIT        64
        !            18: #define        talloc(t)       salloc(sizeof (t))
        !            19: #define        MAP(c)          ((c) - 'a')
        !            20: 
        !            21: typedef        long    Bits;           /* must agree with spell's pcode */
        !            22: 
        !            23: typedef struct word    word;
        !            24: typedef unsigned long  ulong;
        !            25: 
        !            26: struct word
        !            27: {
        !            28:        char    *text;
        !            29:        int     length;
        !            30:        ulong   mask;
        !            31:        word    *next;
        !            32: };
        !            33: 
        !            34: typedef word   *set[LENLIMIT];
        !            35: 
        !            36: typedef struct
        !            37: {
        !            38:        int     count[ALPHAS];
        !            39:        int     length;
        !            40:        ulong   mask;
        !            41: }
        !            42:        target;
        !            43: 
        !            44: char   *myname;
        !            45: char   *dict_name = WORD_LIST;
        !            46: int    interrupt = 0;
        !            47: int    allwords = 0;
        !            48: int    fixed;
        !            49: int    maxwords;
        !            50: set    words;
        !            51: word   *list[LENLIMIT];
        !            52: FILE   *f_dict;
        !            53: 
        !            54: void
        !            55: error(char *s)
        !            56: {
        !            57:        fprintf(stderr, "%s: %s\n", myname, s);
        !            58:        exit(1);
        !            59: }
        !            60: 
        !            61: void   *
        !            62: salloc(ulong z)
        !            63: {
        !            64:        void    *p;
        !            65: 
        !            66:        if ((p = malloc(z)) == NULL)
        !            67:                error("ran out of memory");
        !            68: 
        !            69:        return p;
        !            70: }
        !            71: 
        !            72: int
        !            73: word_ok(char *s)
        !            74: {
        !            75:        int     vowel = 0;
        !            76: 
        !            77:        while (*s != '\0')
        !            78:        {
        !            79:                if (!islower(*s))
        !            80:                        if (allwords) *s = tolower(*s);
        !            81:                        else    return 0;
        !            82: 
        !            83:                switch (*s)
        !            84:                {
        !            85:                case 'a':
        !            86:                case 'e':
        !            87:                case 'i':
        !            88:                case 'o':
        !            89:                case 'u':
        !            90:                case 'y':
        !            91:                        vowel = 1;
        !            92:                }
        !            93: 
        !            94:                s++;
        !            95:        }
        !            96: 
        !            97:        return vowel;
        !            98: }
        !            99: 
        !           100: ulong
        !           101: str_to_mask(char *s)
        !           102: {
        !           103:        ulong   m;
        !           104: 
        !           105:        m = 0;
        !           106: 
        !           107:        while (*s != '\0')
        !           108:                m |= 1 << MAP(*s++);
        !           109: 
        !           110:        return m;
        !           111: }
        !           112: 
        !           113: char   *
        !           114: get_word(char *bp)
        !           115: {
        !           116:        int     c, i, affix;
        !           117:        static int n = 0, stop = 0, naffix = 0;
        !           118: 
        !           119: retry:
        !           120:        if (n == -1)  return NULL;
        !           121:        c = getc(f_dict);       /* affix encoding */
        !           122:        affix = naffix | c;
        !           123:        for (i = n; i < LENLIMIT && !((c = getc(f_dict)) & 0x80); i++) 
        !           124:                        bp[i] = c;
        !           125:        if (i >= LENLIMIT || i == 0)
        !           126:                error("Internal dictionary format bad");
        !           127:        if (c == EOF) n = -1;
        !           128:        else    {
        !           129:                n = (c>>3)&017; /* prefix count, next word */
        !           130:                naffix = (c&07)<<8;
        !           131:        }
        !           132:        bp[i] = '\0';
        !           133: /* the dictionary includes "stop" (illegal) words, flagged
        !           134:    by a magic affix that will be different each time pcode is
        !           135:    run.  Determine the flag dynamically by looking for a
        !           136:    known word in the stop list, STOPWORD
        !           137: */
        !           138:        if (stop == 0 && strcmp(bp, STOPWORD) == 0)
        !           139:                stop = affix;   /* magic affix! */
        !           140:        if ((stop && (affix == stop)) || !word_ok(bp)) goto retry;
        !           141:        return bp;
        !           142: }
        !           143: 
        !           144: void
        !           145: make_word(char *s)
        !           146: {
        !           147:        word    *w;
        !           148:        word    **p;
        !           149:        int     i;
        !           150: 
        !           151:        w = talloc(word);
        !           152:        w->length = i = strlen(s);
        !           153:        w->text = strcpy(salloc(i+1), s);
        !           154:        w->mask = str_to_mask(s);
        !           155:        p = &words[w->length];
        !           156:        w->next = *p;
        !           157:        *p = w;
        !           158: }
        !           159: 
        !           160: void
        !           161: build_wordlist(void)
        !           162: {
        !           163:        char    bp[LENLIMIT];
        !           164:        short   n;
        !           165: 
        !           166:        if ( (f_dict = fopen(dict_name, "r")) == NULL )
        !           167:                error("can't open word list");
        !           168: 
        !           169:        n = (getc(f_dict)&0xFF) << 8;
        !           170:        n |= getc(f_dict)&0xFF;
        !           171: 
        !           172:        if (fseek(f_dict, n*sizeof(Bits)+1, 1) != 0) {
        !           173:                perror(WORD_LIST);
        !           174:                exit(2);
        !           175:        }
        !           176: 
        !           177:        if (allwords) {
        !           178:                make_word("a");
        !           179:                make_word("i");
        !           180:                make_word("o");
        !           181:        }
        !           182:        while (get_word(bp) != NULL)
        !           183:                make_word(bp);
        !           184: }
        !           185: 
        !           186: void
        !           187: count_letters(target *t, char *s)
        !           188: {
        !           189:        int     i;
        !           190: 
        !           191:        for (i = 0; i < ALPHAS; i++)
        !           192:                t->count[i] = 0;
        !           193: 
        !           194:        t->length = 0;
        !           195: 
        !           196:        while (*s != '\0')
        !           197:        {
        !           198:                t->count[MAP(*s++)]++;
        !           199:                t->length++;
        !           200:        }
        !           201: }
        !           202: 
        !           203: int
        !           204: contained(word *i, target *t)
        !           205: {
        !           206:        int     n;
        !           207:        char    *v;
        !           208:        target  it;
        !           209: 
        !           210:        if ((i->mask & t->mask) != i->mask)
        !           211:                return 0;
        !           212: 
        !           213:        count_letters(&it, i->text);
        !           214: 
        !           215:        for (n = 0; n < ALPHAS; n++)
        !           216:        {
        !           217:                if (it.count[n] > t->count[n])
        !           218:                        return 0;
        !           219:        }
        !           220: 
        !           221:        if (it.length == t->length)
        !           222:                return 1;
        !           223: 
        !           224:        for (v = VOWELS; *v != '\0'; v++)
        !           225:        {
        !           226:                if (t->count[MAP(*v)] > it.count[MAP(*v)])
        !           227:                        return 1;
        !           228:        }
        !           229: 
        !           230:        return 0;
        !           231: }
        !           232: 
        !           233: int
        !           234: prune(set in, int m, target *filter, set out)
        !           235: {
        !           236:        word    *i, *o, *t;
        !           237:        int     n;
        !           238:        int     nz;
        !           239: 
        !           240:        nz = 0;
        !           241: 
        !           242:        for (n = 1; n < LENLIMIT; n++)
        !           243:        {
        !           244:                if (n > m)
        !           245:                {
        !           246:                        out[n] = NULL;
        !           247:                        continue;
        !           248:                }
        !           249: 
        !           250:                o = NULL;
        !           251: 
        !           252:                for (i = in[n]; i != NULL; i = i->next)
        !           253:                {
        !           254:                        if (contained(i, filter))
        !           255:                        {
        !           256:                                t = talloc(word);
        !           257:                                *t = *i;
        !           258:                                t->next = o;
        !           259:                                o = t;
        !           260:                                nz = 1;
        !           261:                        }
        !           262:                }
        !           263: 
        !           264:                out[n] = o;
        !           265:        }
        !           266: 
        !           267:        return nz;
        !           268: }
        !           269: 
        !           270: ulong
        !           271: target_mask(int c[])
        !           272: {
        !           273:        ulong   m;
        !           274:        int     i;
        !           275: 
        !           276:        m = 0;
        !           277: 
        !           278:        for (i = 0; i < ALPHAS; i++)
        !           279:        {
        !           280:                if (c[i] != 0)
        !           281:                        m |= 1 << i;
        !           282:        }
        !           283: 
        !           284:        return m;
        !           285: }
        !           286: 
        !           287: void
        !           288: dump_list(word **e)
        !           289: {
        !           290:        word    **p;
        !           291: 
        !           292: /*     fprintf(stdout, "%d", (int)(e - list + 1));
        !           293: */
        !           294:        for (p = list; p < e; p++) {
        !           295:                fputs((*p)->text, stdout);
        !           296:                putchar(' ');
        !           297:        }
        !           298:        puts((*e)->text);
        !           299: }
        !           300: 
        !           301: void
        !           302: free_set(set s)
        !           303: {
        !           304:        int     i;
        !           305:        word    *p, *q;
        !           306: 
        !           307:        for (i = 1; i < LENLIMIT; i++)
        !           308:        {
        !           309:                for (p = s[i]; p != NULL; p = q)
        !           310:                {
        !           311:                        q = p->next;
        !           312:                        free(p);
        !           313:                }
        !           314:        }
        !           315: }
        !           316: 
        !           317: void
        !           318: enumerate(word **p, target *i, set c)
        !           319: {
        !           320:        target  t;
        !           321:        set     o;
        !           322:        word    *w, *h;
        !           323:        char    *s;
        !           324:        int     l, m, b;
        !           325: 
        !           326:        l = p - list;
        !           327:        b = (i->length + (maxwords - l - 1)) / (maxwords - l);
        !           328: 
        !           329:        for (m = i->length; m >= b; m--)
        !           330:        {
        !           331:                h = c[m];
        !           332: 
        !           333:                for (w = h; w != NULL; w = w->next)
        !           334:                {
        !           335:                        if (interrupt) return;
        !           336:                        if (i->length == m)
        !           337:                        {
        !           338:                                *p = w;
        !           339:                                dump_list(p);
        !           340:                                continue;
        !           341:                        }
        !           342: 
        !           343:                        if (l == maxwords - 1)
        !           344:                                continue;
        !           345: 
        !           346:                        t = *i;
        !           347:                        t.length -= m;
        !           348: 
        !           349:                        for (s = w->text; *s != '\0'; s++)
        !           350:                                t.count[MAP(*s)]--;
        !           351: 
        !           352:                        t.mask = target_mask(t.count);
        !           353:                        c[m] = w->next;
        !           354: 
        !           355:                        if (prune(c, m, &t, o))
        !           356:                        {
        !           357:                                *p = w;
        !           358:                                enumerate(p + 1, &t, o);
        !           359:                                free_set(o);
        !           360:                        }
        !           361:                }
        !           362: 
        !           363:                c[m] = h;
        !           364:        }
        !           365: }
        !           366: 
        !           367: void
        !           368: clean(char *s)
        !           369: {
        !           370:        char    *p, *q;
        !           371: 
        !           372:        for (p = s, q = s; *p != '\0'; p++)
        !           373:        {
        !           374:                if (islower(*p))
        !           375:                        *q++ = *p;
        !           376:                else if (isupper(*p))
        !           377:                        *q++ = tolower(*p);
        !           378:        }
        !           379: 
        !           380:        *q = '\0';
        !           381: }
        !           382: 
        !           383: void
        !           384: anagramulate(char *s)
        !           385: {
        !           386:        target  t;
        !           387:        set     subjects;
        !           388: 
        !           389:        clean(s);
        !           390: 
        !           391:        if (fixed)
        !           392:                maxwords = fixed;
        !           393:        else if ((maxwords = strlen(s) / 4) < 3)
        !           394:                maxwords = 3;
        !           395: 
        !           396:        fprintf(stdout, "%s:\n", s);
        !           397:        t.mask = str_to_mask(s);
        !           398:        count_letters(&t, s);
        !           399: 
        !           400:        if (!prune(words,t.length, &t, subjects))
        !           401:                return;
        !           402: 
        !           403:        enumerate(&list[0], &t, subjects);
        !           404: }
        !           405: 
        !           406: void
        !           407: set_fixed(char *s)
        !           408: {
        !           409:        if ((fixed = atoi(s)) < 1)
        !           410:                fixed = 1;
        !           411: }
        !           412: 
        !           413: void
        !           414: read_words(void)
        !           415: {
        !           416:        char    *s;
        !           417:        char    b[LENLIMIT];
        !           418:        char    b2[LENLIMIT];
        !           419: 
        !           420: 
        !           421:        while ((s = fgets(b, LENLIMIT, stdin)) != NULL) {
        !           422:                if (b[0] == 'q' && b[1] == '\n') exit(0);
        !           423:                if (isdigit(b[0]))
        !           424:                {
        !           425:                        set_fixed(s);
        !           426:                        continue;
        !           427:                }
        !           428:                if ( b[0] == '\n' )
        !           429:                        s = &b2[0];
        !           430:                else    s = strcpy(b2, b);
        !           431: 
        !           432:                anagramulate(s);
        !           433:                if (interrupt) {
        !           434:                        interrupt = 0;
        !           435:                        puts("Interrupt");
        !           436:                }
        !           437:                else    puts("Done.");
        !           438:        }
        !           439: }
        !           440: 
        !           441: void
        !           442: fbreak(int dummy)
        !           443: {
        !           444:        dummy = dummy;          /* avert use/set diagnostics */
        !           445:        interrupt += 1;
        !           446:        signal(SIGINT, fbreak);
        !           447:        return;
        !           448: }
        !           449: void
        !           450: main(int argc, char **argv)
        !           451: {
        !           452:        myname = argv[0];
        !           453:        if (argc > 1)
        !           454:                if (argv[1][0] == '-') {
        !           455:                        if (argv[1][1] == 'b')
        !           456:                                dict_name = WORD_LISTB;
        !           457:                        else if (argv[1][1] == 'a')
        !           458:                                allwords = 1;
        !           459:                        else    error("invalid command argument");
        !           460:                        if (argc > 2) set_fixed(argv[2]);
        !           461:                }
        !           462:                else    set_fixed(argv[1]);
        !           463: 
        !           464:        build_wordlist();
        !           465:        signal(SIGINT, fbreak);
        !           466:        read_words();
        !           467:        exit(0);
        !           468: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.