ivector stringIndexer:: checkstring(char * here, const char * delim2) { char * next; ivector out(0); here += strspn(here, delim2); // strtoupper(here); while (here && *here) { next = strpbrk(here, delim2); if (next) { *(next++) = 0; next += strspn(next, delim2); } out.push_back(checkword(here)); here = next; } return out; }
ivector stringIndexer:: checkstrings(char ** here, const char * delim2, int len) { int i; char * next; ivector out(0); // strtoupper(*here); for (i = 0; i < len; i++) { next = strpbrk(*here, delim2); if (next) { *(next++) = 0; } if (strlen(*here) > 0) out.push_back(checkword(*here)); else out.push_back(0); *here = next; } return out; }
/* * Read a line from the given stream and check if it is legal * Return a pointer to a legal word or a null pointer when EOF is reached */ char * batchword(FILE *fp) { int *p, *q; char *w; q = &wordpath[MAXWORDLEN + 1]; p = wordpath; while (p < q) *p++ = -1; while ((w = nextword(fp)) != NULL) { if (wordlen < minlength) continue; p = wordpath; while (p < q && *p != -1) *p++ = -1; usedbits = 0; if (checkword(w, -1, wordpath) != -1) return (w); } return (NULL); }
int main(void) { int memory[MEMSIZE] = { 0 }; int accumulator = 0, i; int m_loc, cmd; /* the memory location and the command */ int program[BUFSIZE] = { /* Calculate the sum of 2 numbers +1009, +1010, +2009, +3110, +4107, +1109, +4300, +1110, +4300, +0000, +0000 */ /* Calculate the largest of 2 numbers +1007, +1008, +2007, +3008, +2109, +1109, +4300, +0000, +0000, +0000 */ /* 7.18 (a): take 10 numbers (in a loop with a dummy value) and calculate its sum */ /* +1008, +2008, +4106, +3009, +2109, +4000, +1109, +4300, +0000, +0000 */ /* 7.18 (b): take 7 numbers positive or negative (in a loop with a counter) and calculate the media */ /* 7, 7, 1, +1020, +2020, +3021, +2121, +2001, +3102, +2101, +4212, +4003, +2021, +3200, +2120, +1120, +4300, +0000, +0000, +0000, +0000 */ /* 7.18 (c): take a serie of numbers and determine and print the largest. The first number readed set how many values will be inserted */ +1000, 1, +2000, +2117, +2000, +3101, +2100, +4214, +1018, +2018, +3117, +4104, +2018, +4003, +2017, +1117, +4300 }; /* Load the program into the memory */ for(i = 0; i < BUFSIZE; i++) { checkword(program[i], MEMSIZE); /* check the word */ memory[i] = program[i]; /* passed - loaded */ } /* Execute the program: i use BUFSIZE to optimize */ for(i = 0; i < MEMSIZE; i++) { m_loc = memory[i] % 100; cmd = memory[i] / 100; /* this is required because after the switch() statement the 'i' counter is incremented of 1. */ if(cmd >= BRANCH) --m_loc; switch(cmd) { case READ: printf("Insert a word: "); scanf("%d", &memory[m_loc]); break; case WRITE: printf("\nMemory location: %d\nWord: %d\n", m_loc, memory[m_loc]); break; case LOAD: accumulator = memory[m_loc]; break; case STORE: memory[m_loc] = accumulator; break; case ADD: accumulator += memory[m_loc]; break; case SUBTRACT: accumulator -= memory[m_loc]; break; case DIVIDE: accumulator /= memory[m_loc]; break; case MULTIPLY: accumulator *= memory[m_loc]; break; case BRANCH: i = m_loc; break; case BRANCHNEG: if(accumulator < 0) i = m_loc; break; case BRANCHZERO: if(!accumulator) i = m_loc; break; case HALT: return 0; case 0: break; default: printf("simpletron: unknown error.\n"); exit(-1); } } /* end for (i) */ return 0; } /* E0F main */
/* * Check each word in the dictionary against the board * Delete words from the machine list that the player has found * Assume both the dictionary and the player's words are already sorted */ void checkdict(void) { char **pw, *w; int i; int prevch, previndex, *pi, *qi, st; mwordsp = mwords; nmwords = 0; pw = pword; prevch ='a'; qi = &wordpath[MAXWORDLEN + 1]; (void) dictseek(dictfp, 0L, SEEK_SET); while ((w = nextword(dictfp)) != NULL) { if (wordlen < minlength) continue; if (*w != prevch) { /* * If we've moved on to a word with a different first * letter then we can speed things up by skipping all * words starting with a letter that doesn't appear in * the cube. */ i = (int) (*w - 'a'); while (i < 26 && letter_map[i][0] == -1) i++; if (i == 26) break; previndex = prevch - 'a'; prevch = i + 'a'; /* * Fall through if the word's first letter appears in * the cube (i.e., if we can't skip ahead), otherwise * seek to the beginning of words in the dictionary * starting with the next letter (alphabetically) * appearing in the cube and then read the first word. */ if (i != previndex + 1) { if (dictseek(dictfp, dictindex[i].start, SEEK_SET) < 0) { cleanup(); errx(1, "seek error in checkdict()"); } continue; } } pi = wordpath; while (pi < qi && *pi != -1) *pi++ = -1; usedbits = 0; if (checkword(w, -1, wordpath) == -1) continue; st = 1; while (*pw != NULL && (st = strcmp(*pw, w)) < 0) pw++; if (st == 0) /* found it */ continue; if (nmwords == maxmwords - 1) { maxmwords += MAXMWORDS; mword = realloc(mword, maxmwords * sizeof(char *)); if (mword == NULL) { cleanup(); errx(1, strerror(ENOMEM)); } } if (mwordsp + wordlen + 1 >= &mwords[maxmspace]) { maxmspace += MAXMSPACE; mwords = realloc(mwords, maxmspace); if (mwords == NULL) { cleanup(); errx(1, strerror(ENOMEM)); } } mword[nmwords++] = mwordsp; memcpy(mwordsp, w, wordlen + 1); mwordsp += wordlen + 1; } }
/* * Check if the given word is present on the board, with the constraint * that the first letter of the word is adjacent to square 'prev' * Keep track of the current path of squares for the word * A 'q' must be followed by a 'u' * Words must end with a null * Return 1 on success, -1 on failure */ int checkword(char *word, int prev, int *path) { char *p, *q; int i, *lm; if (debug) { (void) printf("checkword(%s, %d, [", word, prev); for (i = 0; wordpath[i] != -1; i++) (void) printf(" %d", wordpath[i]); (void) printf(" ]\n"); } if (*word == '\0') return (1); lm = letter_map[*word - 'a']; if (prev == -1) { char subword[MAXWORDLEN + 1]; /* * Check for letters not appearing in the cube to eliminate some * recursive calls * Fold 'qu' into 'q' */ p = word; q = subword; while (*p != '\0') { if (*letter_map[*p - 'a'] == -1) return (-1); *q++ = *p; if (*p++ == 'q') { if (*p++ != 'u') return (-1); } } *q = '\0'; while (*lm != -1) { *path = *lm; usedbits |= (1 << *lm); if (checkword(subword + 1, *lm, path + 1) > 0) return (1); usedbits &= ~(1 << *lm); lm++; } return (-1); } /* * A cube is only adjacent to itself in the adjacency matrix if selfuse * was set, so a cube can't be used twice in succession if only the * reuse flag is set */ for (i = 0; lm[i] != -1; i++) { if (adjacency[prev][lm[i]]) { int used; used = 1 << lm[i]; /* * If necessary, check if the square has already * been used. */ if (!reuse && !selfuse && (usedbits & used)) continue; *path = lm[i]; usedbits |= used; if (checkword(word + 1, lm[i], path + 1) > 0) return (1); usedbits &= ~used; } } *path = -1; /* in case of a backtrack */ return (-1); }
/* * Play a single game * Reset the word lists from last game * Keep track of the running stats */ void playgame(void) { int i, *p, *q; time_t t; char buf[MAXWORDLEN + 1]; ngames++; npwords = 0; pwordsp = pwords; nmwords = 0; mwordsp = mwords; time(&start_t); q = &wordpath[MAXWORDLEN + 1]; p = wordpath; while (p < q) *p++ = -1; showboard(board); startwords(); if (setjmp(env)) { badword(); goto timesup; } while (1) { if (get_line(buf) == NULL) { if (feof(stdin)) clearerr(stdin); break; } time(&t); if (t - start_t >= tlimit) { badword(); break; } if (buf[0] == '\0') { int remaining; remaining = tlimit - (int) (t - start_t); (void)snprintf(buf, sizeof(buf), "%d:%02d", remaining / 60, remaining % 60); showstr(buf, 1); continue; } if (strlen(buf) < (size_t)minlength) { badword(); continue; } p = wordpath; while (p < q && *p != -1) *p++ = -1; usedbits = 0; if (checkword(buf, -1, wordpath) < 0) badword(); else { if (debug) { (void) printf("["); for (i = 0; wordpath[i] != -1; i++) (void) printf(" %d", wordpath[i]); (void) printf(" ]\n"); } for (i = 0; i < npwords; i++) { if (strcmp(pword[i], buf) == 0) break; } if (i != npwords) { /* already used the word */ badword(); showword(i); } else if (!validword(buf)) badword(); else { int len; if (npwords == maxpwords - 1) { maxpwords += MAXPWORDS; pword = realloc(pword, maxpwords * sizeof(char *)); if (pword == NULL) { cleanup(); errx(1, strerror(ENOMEM)); } } len = strlen(buf) + 1; if (pwordsp + len >= &pwords[maxpspace]) { maxpspace += MAXPSPACE; pwords = realloc(pwords, maxpspace); if (pwords == NULL) { cleanup(); errx(1, strerror(ENOMEM)); } } pword[npwords++] = pwordsp; memcpy(pwordsp, buf, len); pwordsp += len; addword(buf); } } } timesup: ; /* * Sort the player's words and terminate the list with a null * entry to help out checkdict() */ qsort(pword, npwords, sizeof(pword[0]), compar); pword[npwords] = NULL; /* * These words don't need to be sorted since the dictionary is sorted */ checkdict(); tnmwords += nmwords; tnpwords += npwords; results(); }
// Get a word from the user and check if it is in either of the two // word lists // If it's found, show the word on the board for a short time and then // erase the word // // Note: this function knows about the format of the board void findword(void) { int c, col, found, i, r, row; char buf[MAXWORDLEN + 1]; getyx(stdscr, r, c); getword(buf); found = 0; for (i = 0; i < npwords; i++) { if (strcmp(buf, pword[i]) == 0) { found = 1; break; } } if (!found) { for (i = 0; i < nmwords; i++) { if (strcmp(buf, mword[i]) == 0) { found = 1; break; } } } for (i = 0; i < MAXWORDLEN; i++) wordpath[i] = -1; usedbits = 0; if (!found || checkword(buf, -1, wordpath) == -1) { move(r, c); clrtoeol(); addstr("[???]"); refresh(); delay(10); move(r, c); clrtoeol(); refresh(); return; } standout(); for (i = 0; wordpath[i] != -1; i++) { row = BOARD_LINE + (wordpath[i] / 4) * 2 + 1; col = BOARD_COL + (wordpath[i] % 4) * 4 + 2; move(row, col); if (board[wordpath[i]] == 'q') printw("Qu"); else printw("%c", toupper((unsigned char) board[wordpath[i]])); move(r, c); refresh(); delay(5); } standend(); for (i = 0; wordpath[i] != -1; i++) { row = BOARD_LINE + (wordpath[i] / 4) * 2 + 1; col = BOARD_COL + (wordpath[i] % 4) * 4 + 2; move(row, col); if (board[wordpath[i]] == 'q') printw("Qu"); else printw("%c", toupper((unsigned char) board[wordpath[i]])); } move(r, c); clrtoeol(); refresh(); }
int main(void) { char s_mem[MAXWORD] = { 0 }; float memory[MEMSIZE] = { 0 }, accumulator = 0; FILE *fd; char infile[30] = { 'x' }; int operationCode = 0, instructionRegister = 0, operand = 0; int i, j, k, err = 0; float t_val = 0, f_tmp; while((*infile != 'y' && *infile != 'n') && strlen(infile) == 1) { printf("Enter in interactive mode (y/n): "); scanf("%c%*c", infile); } if(infile[0] == 'n') { printf("Input file: "); scanf("%s", infile); if( (fd = fopen(infile, "r")) == NULL) { printf("%s: cannot open the file\n", infile); exit(-1); } } else infile[0] = '\0'; printf("*** Welcome to the Simpletron! ***\n" "*** Please enter your program one instruction ***\n" "*** (or data word) at a time. I will type the ***\n" "*** location number and a question mark (?). ***\n" "*** You then type the word for that location. ***\n" "*** Use the sentinel -999999 to stop entering ***\n" "*** your program. ***\n"); for(i = 0; i < MEMSIZE; i++) { while(1) { /* Interactive mode */ if( infile[0] == '\0' ) { printf("%.2d ?? ", i); scanf("%s", s_mem); } else /* Non-interactive mode (read from a file) */ fscanf(fd, "%s", s_mem); memory[i] = r_htoi(s_mem); if(memory[i] == -999999) { memory[i] = 0; i = MEMSIZE; /* Terminate the for loop */ break; } if(s_mem[0] != '+') { printf("*** Invalid instruction: %s\n", s_mem); printf("*** Please use '+' or exit.\n"); /* If is in non-interactive mode, exit */ if( infile[0] != '\0' ) exit(-1); continue; } if( checkword((int)memory[i], MEMSIZE) ) { printf("*** Invalid instruction: +%.0f\n" "*** Please retype it or exit.\n", memory[i]); } else break; } /* end while */ } /* end for (i) */ printf("*** Program loading completed ***\n" "*** Program execution begins ***\n"); for(i = 0; i < MEMSIZE; i++) { instructionRegister = (int)memory[i]; operationCode = instructionRegister / (instructionRegister <= 9999 ? 100 : 1000); operand = instructionRegister % (instructionRegister <= 9999 ? 100 : 1000); /* this is required because after the switch() statement the 'i' counter is incremented of 1. */ if(operationCode >= BRANCH) --operand; switch(operationCode) { case READ: printf("\nInsert a word: "); scanf("%f", &memory[operand]); break; case WRITE: printf("\nMemory location: %.2d\nWord: %.2f\n", operand, memory[operand]); break; case NEWLINE: printf("\n"); break; case SREAD: /* If this instruction is used then HALT is required */ printf("\nInsert a string: "); scanf("%s", s_mem); if(strlen(s_mem) > 3) { err = 3; break; } for(j = 0; (unsigned)j < strlen(s_mem); j++) { if((int)s_mem[j] > 99) { err = 4; t_val = j; break; } } memory[operand] = 0; for(j = strlen(s_mem), k = 1; j >= 0; k *= 100, j--) memory[operand] += s_mem[j] * k; for(t_val = 0.1, k = 1; k < memory[operand]; t_val *= 0.10, k *= 10) ; t_val /= 0.10; memory[operand] *= t_val; memory[operand] += strlen(s_mem); break; case SWRITE: printf("\nMemory location: %.0f\nWord: ", memory[operand]); for(j = (int)memory[operand], t_val = 100; j ; t_val *= 100, j--) { f_tmp = memory[operand] * t_val; k = (int)f_tmp % 100; printf("%c", k); } printf("\n"); break; case LOAD: accumulator = memory[operand]; break; case STORE: memory[operand] = accumulator; break; case ADD: accumulator += memory[operand]; break; case SUBTRACT: accumulator -= memory[operand]; break; case DIVIDE: if( !memory[operand] ) err = 2; else accumulator /= memory[operand]; break; case MULTIPLY: accumulator *= memory[operand]; break; case REST: accumulator = (int)accumulator % (int)memory[operand]; break; case POWER: accumulator = pow(accumulator, memory[operand]); break; case BRANCH: i = operand; break; case BRANCHNEG: if(accumulator < 0) i = operand; break; case BRANCHZERO: if(!accumulator) i = operand; break; case HALT: i = MEMSIZE; /* terminate the for loop */ /* dump(accumulator, i, memory); */ break; case 0: break; default: printf("*** unknown error: %d\n", instructionRegister); dump(accumulator, i, memory); printf("\nAre'nt you using HALT (+4300)?\n"); exit(-1); } if(accumulator > MEMSIZE * MEMSIZE - 1 || accumulator < MEMSIZE * -MEMSIZE + 1) err = 1; if(err) { /* Error messages manager */ printf("\n*** "); switch(err) { case 1: printf("Out of the accumulator limit"); break; case 2: printf("Attempt to divide by zero"); break; case 3: printf("You can put max 3 numbers for memory location"); break; case 4: printf("This ASCII code is too long: %d (%c)", s_mem[(int)t_val], s_mem[(int)t_val]); } printf(" ***\n"); printf("*** Simpletron execution abnormally terminated ***\n"); dump(accumulator, i, memory); exit(-1); } } /* end for (i) */ dump(accumulator, i, memory); printf("\n*** Simpletron execution terminated ***\n"); return 0; } /* E0F main */