// Adds the string pos to the trie, and sets the length and from of the bottom node bool addT(Trie *root, char *pos, char *from, int length, int counter) { if ((*root) == NULL) { return false; } if (pos == NULL) { return false; } // Base case at the bottom of the trie if(pos[counter] == '\0') { (*root)->length = length; (*root)->from = from; return true; } else { int index = pos[counter] - NORM; // Index of the current char // If there is no child, add one if ((*root)->children[index] == NULL) { Trie temp; // The new child trie createT(&temp); (*root)->children[index] = temp; addT(&temp, pos, from, length, ++counter); } // Else go down the trie one child else { Trie temp; // The child trie temp = (*root)->children[index]; addT(&temp, pos, from, length, ++counter); } } return true; }
Shape::Shape() { transformIndex = 0; mainBlock = sf::Vector2i(5,1); int randomBelowSeven = rand() % 7; switch (randomBelowSeven) { case 0: createI(); break; case 1: createJ(); break; case 2: createS(); break; case 3: createO(); break; case 4: createZ(); break; case 5: createL(); break; case 6: createT(); break; } applyTransform(transformIndex); }
void encode () { codeCount = 1; Tree codeTrie; createT(&codeTrie); if (!Escaped){ initializeTrie(&codeTrie); } int firstChar = getchar(); while (firstChar != EOF) { firstChar = getLargestSequence(firstChar, &codeTrie); } freeTrie(&codeTrie); }
void decode () { int possition = 0; int code = 9; Tree codeTrie; createT(&codeTrie); int codeCount = 1; int *outputString = malloc(sizeof(int)); int *lastString = NULL; outputString[0] = -1; int * nextString = NULL; int bitsCount = 8; int getMaxBits = getBits(bitsCount); setMaxBits(getMaxBits); int Escaped = getBits(1); if (Escaped) { setEscaped(); } else { initializeTrie(&codeTrie); } int shouldPrune = getBits(1); if (shouldPrune) { setShouldPrune(); } while ((code = getBits(bitsCount)) != EOF) { if (code == 0 && Escaped) { int singleLetter = getBits(8); nextString = malloc(2 * sizeof(int)); nextString[0] = singleLetter; nextString[1] = -1; } else { nextString = checkForNextCode(&codeTrie, code); } if (!nextString) { nextString = addLetterToStringNoFree(lastString, lastString[0]); } printArray(nextString); int *output = combine(outputString, nextString, possition); free(outputString); outputString = output; possition = addStringToTrie(&codeTrie, outputString, 0, &codeCount); int stringLength = arrayLen(nextString); if (lastString) { free(lastString); lastString = NULL; } lastString = malloc((arrayLen(nextString) + 1) * sizeof(int)); for (int i = 0; nextString[i] != -1; i++) { lastString[i] = nextString[i]; } lastString[stringLength] = -1; bitsCount = getBitsCount(); free(nextString); nextString = NULL; } if (lastString) { free(lastString); } freeTrie(&codeTrie); free(outputString); }
int main(int argc, char *argv[]) { bool rFlag = false; // Flag to tell if -r is specified int height = 3; // HEIGHT of the Rubik's square int width = 3; // WIDTH of the Rubik's square int maxlength; // MAXLENGTH of a series of moves char *initial = NULL; // The INITIAL string char *goal = NULL; // The GOAL string /* INPUT ERROR CHECKING */ // Check for correct number of args if (argc < 4 || argc > 7) { DIE("RubikSq: RubikSq [-r] [HEIGHT WIDTH] MAXLENGTH INITIAL GOAL"); } if (argc == 5 || argc == 7) { // Check to make sure the first arg is "-r" if (strcmp(argv[1], "-r") != 0) { DIE("RubikSq: Invalid [-r] Flag"); } rFlag = true; } if (argc == 6 || argc == 7) { char *check = argv[argc-5]; // Used to check for non-numeric chars in the args for (int i = 0; i < strlen(check); i++) { if (!isdigit(check[i])) { DIE("RubikSq: Invalid HEIGHT"); } } char *end = NULL; // End pointer for strtol height = strtol(argv[argc-5], &end, 10); if (*end != '\0') { DIE("RubikSq: Invalid HEIGHT"); } char *check2 = argv[argc-4]; // Used to check for non-numeric chars in the args for (int i = 0; i < strlen(check2); i++) { if (!isdigit(check2[i])) { DIE("RubikSq: Invalid WIDTH"); } } char *end2 = NULL; // End pointer for strtol width = strtol(argv[argc-4], &end2, 10); if (*end2 != '\0') { DIE("RubikSq: Invalid WIDTH"); } } char *check3 = argv[argc-3]; // Used to check for non-numeric chars in the args for (int i = 0; i < strlen(check3); i++) { if (!isdigit(check3[i])) { DIE("RubikSq: Invalid MAXLENGTH"); } } char *end3 = NULL; // End pointer for strtol maxlength = strtol(argv[argc-3], &end3, 10); if (*end3 != '\0') { DIE("RubikSq: Invalid MAXLENGTH"); } // Check for non-alpha chars in the args initial = argv[argc-2]; for (int i = 0; i < strlen(initial); i++) { if (!isalpha(initial[i])) { DIE("RubikSq: Invalid INITIAL"); } } // Check for non-alpha chars in the args goal = argv[argc-1]; for (int i = 0; i < strlen(goal); i++) { if (!isalpha(goal[i])) { DIE("RubikSq: Invalid GOAL"); } } if (maxlength < 0) { DIE("RubikSq: MAXLENGTH < 0"); } if (height < 2 || height > 5 || width < 2 || width > 5) { DIE("RubikSq: HEIGHT/WIDTH must be between 2 and 5, inclusive"); } if (strlen(initial) != strlen(goal)){ DIE("RubikSq: Length of INITIAL does not equal length of GOAL"); } if ((height*width) != strlen(initial)) { DIE("RubikSq: HEIGHT*WIDTH does not match length of INITIAL/GOAL"); } // If GOAL and INITIAL are the same, print and exit if (strcmp(initial, goal) == 0) { printf("%s\n", initial); exit(0); } // Make an alphabetized copy of INITIAL char *initialSort = malloc(strlen(initial)+1); // An alphabetized version of INITIAL strcpy(initialSort, initial); sortAlphabetical(initialSort); // Make an alphabetized copy of GOAL char *goalSort = malloc(strlen(goal)+1); // An alphabetized version of GOAL strcpy(goalSort, goal); sortAlphabetical(goalSort); if (strcmp(initialSort, goalSort) != 0) { DIE("RubikSq: INITIAL and GOAL do not contain the same letters"); } // Make sure all letters are between A and L, inclusive if (initialSort[0] < 'A' || initialSort[strlen(initialSort)-1] > 'L' || goalSort[0] < 'A' || goalSort[strlen(goalSort)-1] > 'L') { DIE("RubikSq: INITIAL/GOAL contain invalid letters"); } /* ALGORITHM */ Trie dict; // The dictionary trie for storing past positions createT(&dict); addT(&dict, goal, NULL, 0, 0); Queue moves; // The queue of positions to analyze createQ(&moves); enQ(&moves, goal); // Main loop while (!isEmptyQ(&moves)) { char *pos = NULL; // The current position P deQ(&moves, &pos); int len = getLengthT(&dict, pos, 0); // The length of P in the dictionary if (len < maxlength) { int total; // The total number of possible moves // If -r is specified, there are more possible moves if (rFlag) { total = (width-1)*height + (height-1)*width; } else { total = width + height; } char *primes[total]; // The array of possible positions P' char *copy; // Used to find all P' to put in the array // If the -r flag is specified, we can move right or down multiple times if (rFlag) { for (int i = 1; i <= height; i++) { copy = pos; for (int j = 1; j < width; j++){ copy = moveRight(i, width, copy); primes[(i-1)*(width-1)+j-1] = copy; } } for (int i = 1; i <= width; i++) { copy = pos; for (int j = 1; j < height; j++){ copy = moveDown(i, width, height, copy); primes[height*(width-1)+(i-1)*(height-1)+j-1] = copy; } } } // Otherwise, we can only make one move else { for (int i = 1; i <= height; i++) { primes[i-1] = moveRight(i, width, pos); } for (int i = 1; i <= width; i++) { primes[i+height-1] = moveDown(i, width, height, pos); } } // P' checking for loop for (int i = 0; i < total; i++) { // If P' is INITIAL, print the moves and exit if (strcmp(primes[i], initial) == 0) { printf("%s\n", primes[i]); printf("%s\n", pos); while (getFromT(&dict, pos, 0) != NULL) { pos = getFromT(&dict, pos, 0); printf("%s\n", pos); } // Free the sorted INITIAL and GOAL free(initialSort); free(goalSort); exit(0); } // Else if P' is not in the dictionary, add it to the dict and queue else if (!isMemberT(&dict, primes[i], 0)) { addT(&dict, primes[i], pos, len+1, 0); enQ(&moves, primes[i]); } // Else free the storage else { free(primes[i]); } } } } // Free the sorted INITIAL and GOAL free(initialSort); free(goalSort); return 0; }
// 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; }
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; }
int main(int argc, char *argv[]) { std::cerr << "reading graph..."; Eigen::SparseMatrix<double> g = readGraph(std::string(argv[1])); std::cerr << "done." << std::endl; #if DEBUG std::cout << "Adjacency Matrix" << std::endl; std::cout << g << std::endl; #endif std::vector<C_tuple*> C; std::cerr << "getting C vector..."; getC(g, C); std::cerr << "sorting..."; __gnu_parallel::sort(C.begin(), C.end(), C_tuple_compare); //std::sort(C.begin(), C.end(), C_tuple_compare); std::cerr << "done." << std::endl; #if DEBUG for (uint64_t i = 0; i < C.size(); i++) { std::cout << C[i]->i << ", " << C[i]->j << ", " << C[i]->value<< std::endl; } #endif std::cerr << "creating T..."; node* root = createT(g, C); std::cerr << "done." << std::endl; #if DEBUG //postorder(printNode, root); levelorder(printNode, root); node* left = root->leftChild; while (left->leftChild) left = left->leftChild; node* right = root->rightChild; while (right->rightChild) right = right->rightChild; node* lca = LCA(left, right); std::cout << "lca for " << left->vertex << ", " << right->vertex << ": " << lca->vertex << std::endl; left = right->parent->leftChild; lca = LCA(left, right); std::cout << "lca for " << left->vertex << ", " << right->vertex << ": " << lca->vertex << std::endl; #endif std::cerr << "counting vertices and edges..."; countVerticesAndEdges(g, root); std::cerr << "done." << std::endl; std::cerr << "computing density..."; computeDensity(root); std::cerr << "done." << std::endl; #if DEBUG std::cout << "\nPrinting after the countVerticesAndEdges\n" << std::endl; postorder(printNode, root); #endif std::cerr << "extracting subgraphs..."; extractSubgraphs(root, 0.75); std::cerr << "done." << std::endl; }
// encodes the input stream by taking advantage of lzw algorithm // also implements logic to prune the trie structure used to store the string // table, and escapes single character codes void encode(int e, int m, int p) { Trie st; createT(&st, e); int c = EMPTY; // same as (EMPTY, K), index of the prefix // int value of char k we are testing to see if c,k exists in the table int k; // number of codes you have inserted, 256 without escape flag... int codeCount = (e) ? 3 : 259; int bitCount = (e) ? 2 : 9; int maxbits = (m<=8 || m>20) ? 12 : m; int maxcodes = (1 << maxbits); int firstRead = false; // if first read of k when e flag is present int pruneCount = 0; printf("%02d:%d:%d:", maxbits, p, e); while((k = getchar())!= EOF) { st[c].appearances++; int ck = searchT(&st, c, k, e); // will increment c's appearance once // if ck is not in the table if(ck<0) { // if prune flag & reached maxcodes, do a prune before next insert // into the table, putBits 0 to indicate a prune has occurred // a prune should likewise happen in decode if(c!=EMPTY) { putBits(bitCount, c); } // add ck to the table as long as (e && c == EMPTY) is false // we will add (empty, k) to the table after this condition // !e and c==EMPTY will never happen, bc all chars will have been // added as children to empty // prune right before we reach maxcodes, we would have lost the next // code we insert anyways, now we won't lose k if(p&&(codeCount+1==maxcodes)) { putBits(bitCount, 0); pruneCount++; Trie newst; createT(&newst, e); int oldCodeCount = codeCount; codeCount=pruneT(&st, &newst, e, oldCodeCount); destroyT(&st, oldCodeCount); st = newst; bitCount=codeLength(codeCount); c=EMPTY; ungetc(k, stdin); continue; } // if(!e || c!=EMPTY) { if(codeCount<maxcodes) { if(tableFilled(codeCount+1)) { int newSize = (codeCount+1)*2; expandT(&st, newSize); bitCount++; } addT(&st, c, k, codeCount); codeCount++; } } // if escape flag is on and k is not yet added to the table if(e && searchT(&st, EMPTY, k, e) < 0) { putBits(bitCount, ESC); // 1 is the index of escape character putBits(8, k); if(codeCount<maxcodes) { if(codeLength(codeCount+1)-codeLength(codeCount)) { int newSize = (codeCount+1)*2; expandT(&st, newSize); bitCount++; } addT(&st, EMPTY, k, codeCount); codeCount++; } firstRead=true; // encode escaped something, don't unget(k) // if this happens } c = EMPTY; // make c empty again if(!firstRead) { ungetc(k, stdin); // put k back to start reading } // a new character else { firstRead = false; } } else { c=ck; // set c to index of next code } } if(c!=EMPTY) { putBits(bitCount, c); } putBits(bitCount, EOFILE); // puts EOF flushBits(); destroyT(&st, codeCount); }
// decodes using lzw algorithm void decode() { int code, newcode; int maxbits = getFlags(2); int maxcodes = (1 << maxbits); int p = getFlags(1); int e = getFlags(1); Trie st; createT(&st, e); int bitCount = (e) ? 2 : 9; int codeCount = (e) ? 3 : 259; int oldc = EMPTY; bool kwk = false; char baseK; int pruneCount=0, kwkcount=0; while((newcode=code=getBits(bitCount))!=EOFILE) { // under these conditions, a valid prune can occur if(p && code==EMPTY) { pruneCount++; Trie newst; createT(&newst, e); int oldCodeCount=codeCount; codeCount=pruneT(&st, &newst, e, oldCodeCount); destroyT(&st, oldCodeCount); st=newst; bitCount=codeLength(codeCount); oldc=EMPTY; continue; } if(newcode>=codeCount+1) { ERROR("code impossible to decode\n"); } // read an escaped character else if(e && code==ESC) { if(tableFilled(codeCount+1)&&bitCount!=codeLength(codeCount+1)) { if(bitCount<maxbits) { bitCount++; } } code=getBits(8); baseK=(char)code; putchar(baseK); if(codeCount<maxcodes) { if(tableFilled(codeCount+1)) { expandT(&st, (codeCount)*2); } addT(&st, oldc, code, codeCount); codeCount++; // then we need to add the char k as it's own code if(oldc!=EMPTY) { if(tableFilled(codeCount+1)) { expandT(&st, (codeCount)*2); } addT(&st, EMPTY, code, codeCount); codeCount++; if(tableFilled(codeCount)&&bitCount!=codeLength(codeCount)) { if(bitCount<maxbits) { bitCount++; } } } } oldc=EMPTY; } else { // no escape character called, would read c and k normally if(newcode==codeCount) { kwk=true; code=oldc; // omega, need to print k after } baseK=outputCode(&st, code, true); if(kwk) { putchar(baseK); kwkcount++; } // oldc is empty on the first read, and when the e-flag is present // oldc is zero when the last character read was escaped if(oldc!=EMPTY) { if(codeCount<maxcodes) { if(tableFilled(codeCount+1)) { expandT(&st, (codeCount)*2); } addT(&st, oldc, (int)baseK, codeCount); codeCount++; if(kwk) { // we added kwk after seeing it once already in the prev // scan through so we should increase its number of apps st[newcode].appearances++; // this scenario means we have kkk, without w in between // so if(st[st[oldc].prefix].prefix==EMPTY&&kwkcount==1) { st[oldc].appearances--; } kwk=false; } if(tableFilled(codeCount+1)) { if(bitCount<maxbits&&bitCount!=codeLength(codeCount+1)) { bitCount++; } } } } else if(e) { // if e-flag & last char was excaped, increase bit count if // table is filled now if(tableFilled(codeCount+1)) { if(bitCount<maxbits) { bitCount++; } } } oldc = newcode; } } destroyT(&st, codeCount); }
/* 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; }