// Gets user input numbers to populate binary tree NodeT *getNumbers(NodeT *pRoot) { char szBuffer[200]; // Initial input buffer, will be converted to integers int i; int d; int n; int iPos; int iSize = 0; // Number of entries in binary tree bool bIsNumber = FALSE; printf("\nEnter numbers for the binary tree (seperated by spaces):\n"); // Get user input and store in buffer fgets(szBuffer, 200, stdin); // Find spaces to determin number of integers for (i = 0; i < strlen(szBuffer); i++) { if (szBuffer[i] == ' ') bIsNumber = FALSE; else { if (bIsNumber == FALSE) iSize++; bIsNumber = TRUE; } } char *p = szBuffer; // Make it a pointer so we can move through it // Cycle through input to pull out integers and put them in a binary tree for (i = 1; i <= iSize; i++) { sscanf(p, "%d%n", &n, &iPos); pRoot = insertT(pRoot, n); p += iPos; } return pRoot; }
// Compress STDIN into stream of codes // First byte sent in the form [MAXBITS (6 bits)][E_FLAG][P_FLAG] // // The only special code sent is ESCAPE for -e; // everything else is derived in decode. // // Pruning performed as soon as the table is full int encode(int MAXBITS, int E_FLAG, int P_FLAG) { // Send option args encoded as: // MAXBITS: 6 bits (since max value is 20) // E_FLAG: 1 bit // P_FLAG: 1 bit putBits(6, MAXBITS); putBits(1, E_FLAG); putBits(1, P_FLAG); int next_code = 0; // == number of codes assigned == # elts in ARRAY int nBits = 1; // #bits required to send NEXT code if (E_FLAG) next_code = 2; // already assigned 0 to QUIT // 1 to ESCAPE // ============== INITIALIZE TRIE ================ Trie t = createT(); if (!E_FLAG) { // initialize all one-char strings for (int K = 0; K < 256; K++) insertT(t, K, next_code++, 0); nBits = 8; } // ================ ENCODE INPUT ================= Trie C = t; // last node visited int K; while ((K = getchar()) != EOF) { Trie child = getT(C, K); if (child != NULL) { // increment NAP and go down trie sawT(child); C = child; } else { // ============ PUTBITS ========================== if (C == t) { // new 1-char string if (!E_FLAG) DIE_FORMAT("E_FLAG false, yet (EMPTY, K=%d) not in table\n", K); putBits(nBits, ESCAPE); putBits(CHAR_BIT, K); } else { // Output code C putBits(nBits, getCodeT(C)); } // =========== INSERT ============================== // insert new code if table not full if (next_code < (1 << MAXBITS)) { insertT(C, K, next_code++, 1); } // =========== UPDATE NBITS ======================= // Prune as soon as last slot taken if (next_code == (1 << MAXBITS)) { if (P_FLAG) { next_code = prune(&t, E_FLAG); nBits = get_nbits(next_code); } else ; } // Increase NBITS only when #codes assigned // exceeds it else if (next_code > (1 << nBits)) nBits++; // ============ RESET C ===== if (C == t) // new single-char, so skip continue; else { C = getT(t, K); if (C == NULL) { // (EMPTY, K) not in table if (!E_FLAG) DIE_FORMAT("E_FLAG false, yet (EMPTY, K=%d) not in table\n", K); ungetc(K, stdin); // single-char on next insert C = t; } else sawT(C); // increment NAP } } } // Put leftover known prefix if (C != t) { putBits(nBits, getCodeT(C)); } flushBits(); destroyT(t); return 0; }
void STinsert(Item item) { head = insertT(head, item); }
int decode() { // Decode first byte as options int MAXBITS = getBits(6); int E_FLAG = getBits(1); int P_FLAG = getBits(1); if (MAXBITS <= CHAR_BIT || MAXBITS > 20 || E_FLAG == EOF || P_FLAG == EOF) DIE("decode: bit stream not encoded by encode"); int next_code = 0; // == number of codes assigned == # elts in ARRAY int nBits = 1; // #bits required to send NEXT code if (E_FLAG) next_code = 2; // already assigned 0 to QUIT // 1 to ESCAPE // =============== INITIALIZE TRIE ===================== Trie t = createT(); if (!E_FLAG) { // initialize all one-char strings for (int K = 0; K < 256; K++) insertT(t, K, next_code++, 0); nBits = 8; } // =============== DECODE BIT STREAM ==================== int C; int last_insert = EMPTY; // code assigned to last inserted node while ((C = getBits(nBits)) != EOF) { // -e: Break on C = QUIT (flushBits() junk) if (E_FLAG && C == QUIT) break; // ========== PRINT STRING WITH NEW CODE ======= int finalK; // first char in C string // -e: check for ESCAPE if (E_FLAG && C == ESCAPE) { finalK = getBits(CHAR_BIT); if (finalK == EOF) DIE("decode: bit stream not encoded by encode"); putchar(finalK); } else { int KwK = 0; finalK = putstring(C, &KwK); // DIEs if C not in table // If C was just inserted w/ STANDBY (KwK), // print oldC==Kw then K if (KwK) putchar(finalK); } // =========== PATCH LAST-INSERTED STRING ========= // K now known for word inserted with prefix OLDC if (last_insert != EMPTY) updateK(last_insert, finalK); // =========== INSERT NEW CODE ==================== // insert new code if table not full if (next_code < (1 << MAXBITS)) { if (E_FLAG && (C == ESCAPE)) { insertT(t, finalK, next_code++, 1); last_insert = EMPTY; } else { // Insert node with C as prefix and K=STANDBY insertT( C_to_T(C), STANDBY, next_code, 1); last_insert = next_code++; } } else last_insert = EMPTY; // no insert to update next time // =========== UPDATE NBITS ======================= // Prune as soon as last slot taken if (next_code == (1 << MAXBITS)) { if (P_FLAG) { next_code = prune(&t, E_FLAG); nBits = get_nbits(next_code); // no need to update K in insertion // since it'll be pruned last_insert = EMPTY; } else ; } // Increase NBITS only when #codes assigned // exceeds it else if (next_code > (1 << nBits)) nBits++; } destroyT(t); return 0; }
/* RubikSq.c | Stephen Krewson | CPSC 223b. USAGE: RubikSq [-r] [HEIGHT WIDTH] MAXLENGTH INITIAL GOAL. RubikSq solves a Rubik's square puzzle using a trie data structure and breadth-first search to find the fewest number of moves necessary to transform INITIAL into GOAL. */ int main (int argc, char *argv[]) { // 1. PARSING COMMAND-LINE ARGS bool rFlag = false; int maxLength = 0; int pos = 0; // pos is counter for moving through argv[] int height = 3, width = 3; // default values char *initial = NULL; char *goal = NULL; if (argc % 2 != 0) // "-r" specified { if (argc > 3) { if (strcmp(argv[1], "-r") != 0) KILL("ERROR: '-r' flag improperly specified."); else rFlag = true; } else KILL("ERROR: Insufficient number of arguments."); } if (argc == 6 || argc == 7) // HEIGHT and WIDTH specified { // Indexes depend on -r flag pos = (rFlag == true) ? 2 : 1; initial = strdup(argv[pos+3]); // use malloc bc we will call free() goal = strdup(argv[pos+4]); // on all the dict nodes if (!(height = atoi(argv[pos])) || !(width = atoi(argv[pos+1])) || (height < 2 || height > 5) || (width < 2 || width > 5)) KILL("ERROR: Invalid HEIGHT and WIDTH values."); char *endPtr; maxLength = (int) strtol(argv[pos+2], &endPtr, 10); if (endPtr < argv[pos+2] + strlen(argv[pos+2])) KILL("ERROR: MAXLENGTH contains nun-numeric characters."); else if (maxLength < 0) KILL ("ERROR: MAXLENGTH is negative."); if (!checkTray(height, width, initial, goal)) KILL("ERROR: Invalid tray sequences."); } // HEIGHT, WIDTH NOT specified else if (argc == 4 || argc == 5) { pos = (rFlag == true) ? 2 : 1; initial = strdup(argv[pos+1]); goal = strdup(argv[pos+2]); char *endPtr; maxLength = (int) strtol(argv[pos], &endPtr, 10); if (endPtr < argv[pos] + strlen(argv[pos])) KILL("ERROR: MAXLENGTH contains nun-numeric characters."); else if (maxLength < 0) KILL ("ERROR: MAXLENGTH is negative."); if (!checkTray(height, width, initial, goal)) KILL("ERROR: Invalid tray sequences."); } else { KILL("ERROR: Invalid number of arguments."); } Trie dict; // Initialize trie data structure createT(&dict); Stack stk1, stk2; // Initialize the "queue" createS(&stk1); createS(&stk2); char *currentPos = NULL; // pointer for position being processed char *prevPos = NULL; // pointer to "from" attr in the dict long lengthPos = 0; // address to hold "length" attr in the dict int permutations = 0; // hold # of permutations getPerms returns insertT(&dict, goal, NULL, 0); // Add GOAL to dictionary enqueue(&stk1, &stk2, goal); // push GOAL onto the queue while (!isEmptyQ(&stk1, &stk2)) // While the queue is not empty { dequeue(&stk1, &stk2, ¤tPos); // Remove P from head of queue searchT(&dict, currentPos, &prevPos, &lengthPos); // lengPos holds length of P if (lengthPos + 2 < maxLength) // +2 because currentPos is 1 { // more than the previous distance and each // permutation is another distance of 1 char **perms; // array of pointers to permutations of P perms = getPerms(currentPos, height, width, rFlag, &permutations); for (int j = 0; j < permutations; j++) // for each position . . . { if (strcmp(initial, perms[j]) == 0) // if P' is the INITIAL { // add it so we can trace insertT(&dict, perms[j], currentPos, lengthPos+1); printf("%s\n", initial); // print INITIAL printf("%s\n", currentPos); // reached INITIAL from... char *holder2; // follow path of search holder2 = currentPos; // start at currentPos while (strcmp(holder2, goal) != 0) { if(!searchT(&dict, currentPos, &holder2, &lengthPos)) { KILL("ERROR: searchT() failed."); } printf("%s\n", holder2); currentPos = holder2; } destroyS(&stk1); // get rid of the queue destroyS(&stk2); deleteT(dict, dict); free(dict); // Remember root node free(perms[j]); free(perms); // free the pointer array exit(0); // Successful exit! } else if (!searchT(&dict, perms[j], &prevPos, &lengthPos)) { // Put p' in dict, on queue if (!insertT(&dict, perms[j], currentPos, lengthPos+1)) { KILL("ERROR: insertT() failed."); } enqueue(&stk1, &stk2, perms[j]); } else // else P' is already in the dictionary { free(perms[j]); // don't need it anymore! } } free(perms); // Free the pointer array } } destroyS(&stk1); // Cleanup in case of no valid sequence destroyS(&stk2); deleteT(dict, dict); free(dict); // Remember to clean root node of dict return EXIT_SUCCESS; }