#include /* wordprob.c - calculate the probabilities of drawing words at random out * of a bag of letter tiles. * * Copyright (C) 1993 by John J. Chew, III . * All Rights Reserved. * * wordprob.c * * $Header: wordprob.c,v 1.1 93/07/28 09:11:05 jjchew Locked $ */ #undef DEBUG #define MAX_BINGO_LENGTH 15 /* configurable */ unsigned char *gBag = "aaaaaaaaabbccddddeeeeeeeeeeeeffggghhiiiiiiiiijkllllmm\ nnnnnnooooooooppqrrrrrrssssttttttuuuuvvwwxyyz__"; unsigned char gBlank = '_'; /* calculated */ int gBagSize; int gBlankCount; int gFrequency[256]; double gChooseSmall[MAX_BINGO_LENGTH+1][MAX_BINGO_LENGTH+1]; double gChooseBag[MAX_BINGO_LENGTH+1]; /* general external variables */ char *gProgramName; enum { none, reciprocal, ppb, numerator } gResultMode = none; /* functions in this file */ int main(); void init(); void process(); int main(argc, argv) int argc; char **argv; { int ch; int errflg = 0; extern int optind; extern char *optarg; while ((ch = getopt(argc, argv, "B:bnr")) != EOF) switch(ch) { case 'B': gBag = optarg; break; case 'b': if (gResultMode != ppb && gResultMode != none) errflg++; else gResultMode = ppb; break; case 'n': if (gResultMode != numerator && gResultMode != none) errflg++; else gResultMode = numerator; break; case 'r': if (gResultMode != reciprocal && gResultMode != none) errflg++; else gResultMode = reciprocal; break; case '?': default: errflg++; break; } if (errflg) { fputs("Usage: wordprob [-b|-n|-r] [file...]\n", stderr); fputs(" -B bag set non-standard bag (blank=_)\n", stderr); fputs(" -b display parts per billion\n", stderr); fputs(" -n display numerator only\n", stderr); fputs(" -r display reciprocal of probability\n", stderr); exit(2); } if (gResultMode == none) gResultMode = reciprocal; init(&argc, &argv); if (optind == argc) process(stdin, "(stdin)"); else for (; optind < argc; optind++) process(fopen(argv[optind], "r"), argv[optind]); return 0; } void init(argcp, argvp) int *argcp; char ***argvp; { double a, r; int i, j; char *cp; /* command-line argument processing */ gProgramName = **argvp; /* bag analysis */ gBagSize = strlen(gBag); for (cp=gBag; *cp; ) gFrequency[*cp++]++; gBlankCount = gFrequency[gBlank]; if (gBlankCount != 2) { fprintf(stderr, "%s: current code supports only two-blank bags\n", gProgramName); exit(1); } /* combinatorial precalculation */ gChooseSmall[0][0] = gChooseBag[0] = a = 1.0; for (r=i=1; i<=MAX_BINGO_LENGTH; i++, r++) { gChooseBag[i] = a *= (gBagSize + 1.0 - r)/r; gChooseSmall[i][0] = gChooseSmall[i][i] = 1.0; for (j=1; j MAX_BINGO_LENGTH) { putchar('\n'); fflush(stdout); fprintf(stderr, "%s: word too long in line %d of %s.\n", gProgramName, lineNumber, aFileName); exit(1); } else { word[charNumber-1] = ch; for (i=0; i