/* * Usage: $0 ncol npeg guess score [guess score ... [guess score ...]] */ #include #include #include extern const char *__progname; typedef struct info INFO; struct info { INFO *link; unsigned char *pegs; int nb; int nw; } ; static int ncol; static int npeg; static INFO *info; static int score_b_w(const char *str, INFO *i) { int j; i->nb = 0; i->nw = 0; for (j=0;str[j];j++) { if (j >= npeg) return(0); switch (str[j]) { case 'b': i->nb ++; break; case 'w': i->nw ++; break; default: return(0); break; } } return(1); } static int score_digits(const char *str, INFO *i) { int j; int v[2]; if (!str[0] || !str[1] || str[2]) return(0); for (j=1;j>=0;j--) { switch (str[j]) { case '0': v[j] = 0; break; case '1': v[j] = 1; break; case '2': v[j] = 2; break; case '3': v[j] = 3; break; case '4': v[j] = 4; break; case '5': v[j] = 5; break; case '6': v[j] = 6; break; case '7': v[j] = 7; break; case '8': v[j] = 8; break; case '9': v[j] = 9; break; default: return(0); break; } if (v[j] > npeg) return(0); } if (v[0] + v[1] > npeg) return(0); i->nb = v[0]; i->nw = v[1]; return(1); } static void add_info(const char *guess, const char *score) { int peg; unsigned char *pegs; int nb; int nw; int j; INFO *i; pegs = malloc(npeg); if (strlen(guess) != npeg) { fprintf(stderr,"%s: guess `%s' conflicts with peg count %d\n",__progname,guess,npeg); exit(1); } for (j=npeg-1;j>=0;j--) { switch (guess[j]) { case '1': case 'a': peg = 0; break; case '2': case 'b': peg = 1; break; case '3': case 'c': peg = 2; break; case '4': case 'd': peg = 3; break; case '5': case 'e': peg = 4; break; case '6': case 'f': peg = 5; break; case '7': case 'g': peg = 6; break; case '8': case 'h': peg = 7; break; case '9': case 'i': peg = 8; break; case '0': case 'j': peg = 9; break; default: peg = -1; break; } if ((peg < 0) || (peg >= ncol)) { fprintf(stderr,"%s: guess `%s' contains character `%c' invalid for colour count %d\n",__progname,guess,guess[j],ncol); exit(1); } pegs[j] = peg; } i = malloc(sizeof(INFO)); i->pegs = pegs; i->nb = nb; i->nw = nw; if (!( score_b_w(score,i) || score_digits(score,i) )) { fprintf(stderr,"%s: invalid score `%s'\n",__progname,score); exit(1); } i->link = info; info = i; } static void compute_score(const unsigned char *a, const unsigned char *b, int *nbp, int *nwp) { unsigned int am; unsigned int bm; int i; int j; int n; am = 0; n = 0; for (i=npeg-1;i>=0;i--) { if (a[i] == b[i]) { am |= 1U << i; n ++; } } *nbp = n; bm = am; n = 0; for <"i"> (i=npeg-1;i>=0;i--) { if (am & (1U << i)) continue; for (j=npeg-1;j>=0;j--) { if (j == i) continue; if (bm & (1U << j)) continue; if (a[i] == b[j]) { am |= 1U << i; bm |= 1U << j; n ++; continue <"i">; } } } *nwp = n; } static void printit(const unsigned char *v) { int i; for (i=0;ilink) { compute_score(v,i->pegs,&nb,&nw); if ((nb != i->nb) || (nw != i->nw)) return; } printit(v); } static void count(unsigned char *v, int x) { int i; if (x < 0) { scoreit(v); return; } for (i=ncol-1;i>=0;i--) { v[x] = i; count(v,x-1); } } static void enumerate(void) { unsigned char *v; v = malloc(npeg); count(v,npeg-1); } int main(int, char **); int main(int ac, char **av) { int i; // { int b; int w; ncol = 6; npeg = 4; compute_score("\1\1\2\3","\5\4\1\5",&b,&w); printf("%d %d\n",b,w); if (b < 100) exit(0); } if ((ac < 5) || ! (ac & 1)) { fprintf(stderr,"Usage: %s ncol npeg guess score [guess score ...]\n",__progname); fprintf(stderr,"score can be two digits, nblack first, or zero or more `b's and `w's.\n"); exit(1); } ncol = atoi(av[1]); npeg = atoi(av[2]); if ((ncol < 2) || (ncol > 10)) { fprintf(stderr,"Colour count %d out of range 2..10\n",ncol); exit(1); } if ((npeg < 2) || (npeg > 10)) { fprintf(stderr,"Peg count %d out of range 2..10\n",npeg); exit(1); } info = 0; for (i=3;i