/* Checks is either of the stacks used to simulate the queue are empty. Returns TRUE is both are empty, FALSE if at least one stack contains values. */ bool isEmptyQ (Stack *stk1, Stack *stk2) { if (!isEmptyS(stk1) || !isEmptyS(stk2)) return false; else return true; }
// Checks to see if the queue is empty bool isEmptyQ(Queue *q) { if (q == NULL) { return true; } if (isEmptyS(&(q->stack1)) && isEmptyS(&(q->stack2))) { return true; } return false; }
void popQ(Stack *s1, Stack *s2, char **c){ char *t; if(isEmptyS(s2)){ while(!(isEmptyS(s1))){ popS(s1, &t); pushS(s2, t); } } popS(s2, c); }
// Removes the string from the front of the queue and sets it to s void deQ(Queue *q, char **s) { if (isEmptyQ(q)) { DIE("Queue is empty"); } if (!isEmptyS(&(q->stack2))) { popS(&(q->stack2), s); } else { while (!isEmptyS(&(q->stack1))) { popS(&(q->stack1), s); pushS(&(q->stack2), *s); } popS(&(q->stack2), s); } }
/* Pops off string pointer in FIFO order by taking from Stack 2 if it has values and otherwise pouring all the values from Stack 1 into Stack 2 before popping off the top of Stack 2, which will be the first element pushed onto Stack 1. Returns TRUE if successful and puts popped value into *pos. */ bool dequeue (Stack *stk1, Stack *stk2, char **pos) { if (!isEmptyQ(stk1, stk2)) // The queue is NOT empty { if (!isEmptyS(stk2)) // stk2 has vals, pop off top one { popS(stk2, pos); return true; } else // No vals in stk2 { while (!isEmptyS(stk1)) // pour all of stk1 into stk2 { popS(stk1, pos); pushS(stk2, *pos); } popS(stk2, pos); // Now pop off top of stk2 return true; } } else return false; // Queue was empty }
/* Function: quicksort Arguments: A = the stack we want to be sorted B = the stack where we put the bigger values C = the stack where we put the smaller values flipped = for keeping the sort stable location = where the sorted stack is, from 1 to 3 counter = how many values have been pushed on this level pos = the value of POS len = the value of LEN Return Value: This function returns void Outside Effect: This function sorts the values in the A stack, which persists outside the function Description: This function performs quicksort using three stacks */ void quicksort(Stack *A, Stack *B, Stack *C, bool flipped, int location, int counter, int pos, int len) { // Base case if (counter == 0) { return; } char *splitter; // The splitter string // Pop off the splitter if (!isEmptyS(A)) { if (!popS(A, &splitter)) { DIE("Pop failed"); } counter--; } char *next = NULL; // The next string to be sorted int bigger = 0; // The number of pushes to B int smaller = 0; // The number of pushes to C // Split the stack into bigger and smaller while (counter > 0) { if (!popS(A, &next)) { DIE("Pop failed1"); } int comp; // The value of the comparsion comp = strcompare(splitter, next, pos, len); // Push the string to the bigger stack if (comp < 0) { if(!pushS(B, next)) { DIE("Push failed"); } bigger++; } // Push the string to the smaller stack else if (comp > 0) { if(!pushS(C, next)) { DIE("Push failed"); } smaller++; } // If strings are equal, perform stability check else { // If flipped, push the splitter if (flipped) { if(!pushS(B, splitter)) { DIE("Push failed"); } splitter = next; bigger++; } // Otherwise push the string else { if(!pushS(B, next)) { DIE("Push failed"); } bigger++; } } counter--; } // Swap the value of flipped each iteration flipped = !flipped; // Recursive step if (bigger == 0) { // Push to A, swap location 1 and 2, sort smallers if (location == 1) { if(!pushS(A, splitter)) { DIE("Push failed"); } if (smaller == 0) { return; } quicksort(C, A, B, flipped, 2, smaller, pos, len); } // Push to B, keep location the same, sort smallers else if (location == 2) { if(!pushS(B, splitter)) { DIE("Push failed"); } if (smaller == 0) { return; } quicksort(C, B, A, flipped, 2, smaller, pos, len); } } else { // Swap location 1 and 2, sort biggers, push to A, sort smallers if (location == 1) { quicksort(B, A, C, flipped, 2, bigger, pos, len); if(!pushS(A, splitter)) { DIE("Push failed"); } if (smaller == 0) { return; } quicksort(C, A, B, flipped, 2, smaller, pos, len); } // Keep location the same, sort biggers, push to B, sort smallers else if (location == 2) { quicksort(B, A, C, flipped, 1, bigger, pos, len); if(!pushS(B, splitter)) { DIE("Push failed"); } if (smaller == 0) { return; } quicksort(C, B, A, flipped, 2, smaller, pos, len); } } return; }
int main(int numargs, char *args[]){ //should have either 4, 5, 6, or 7 arguments //if 7, [1] must be -r, [2,3,4] must be ints, initial and goal are letters //if 6, must not include -r, include all else //if 5 must include -r and not height OR width //if 4, must have int for maxlength and letters for other, and nothing else //height and width are ints between 2 and 5 (Default is 3) //maxlength is non-negative int (can be 0) //INITIAL and GOAL have the necessary number of letters for the size of the tray //letters between only A and L (duplicates ok) int width = 3; //width of the tray, default is 3 int height = 3; //height of the tray, default is 3 int maxlength = -1; //maxlength of the pattern int tilelen; //number of tiles char *temp; bool flag; //true is -r is specified bool used; char *initial; //initial position char *goal; //goal position //if all the command-line args follow the rules for 4 args if((numargs == 4) && checkNum(args[1]) && checkTiles(args[2], args[3])){ maxlength = (int)strtol(args[1], &temp, 10); tilelen = strlen(args[2]); flag = false; //no flag present initial = args[2]; goal = args[3]; } //if all the command-line args follow the rules for 5 args else if((numargs == 5) && checkFlag(args[1]) && checkNum(args[2]) && checkTiles(args[3], args[4])){ maxlength = (int)strtol(args[2], &temp, 10); tilelen = strlen(args[3]); flag = true; //flag present initial = args[3]; goal = args[4]; } //if all the command-line args follow the rules for 6 args else if((numargs == 6) && checkNum(args[1]) && checkNum(args[2]) && checkNum(args[3]) && checkTiles(args[4], args[5])){ height = (int)strtol(args[1], &temp, 10); width = (int)strtol(args[2], &temp, 10); maxlength = (int)strtol(args[3], &temp, 10); tilelen = strlen(args[4]); flag = false; //no flag present initial = args[4]; goal = args[5]; } //if all the command-line args follow the rules for 7 args else if((numargs == 7) && checkFlag(args[1]) && checkNum(args[2]) && checkNum(args[3]) && checkNum(args[4]) && checkTiles(args[5], args[6])){ height = (int)strtol(args[2], &temp, 10); width = (int)strtol(args[3], &temp, 10); maxlength = (int)strtol(args[4], &temp, 10); tilelen = strlen(args[5]); flag = true; //flag present initial = args[5]; goal = args[6]; } else{//invalid command line args fprintf(stderr, "Invalid command line arguments\n"); exit(1); } if((height >= 2) && (height <= 5) && (width >= 2) && (width <= 5) && (tilelen == height*width)){} else{//if the height and width aren't right, then quit fprintf(stderr, "Invalid command line arguments\n"); exit(1); } Stack q1; //create the two stacks for the queue Stack q2; createS(&q1); createS(&q2); char *nextStr; //holds what is popped off queue 'P' int nextLen; //holds the length of P Trie root; //root of the trie dictionary root.len = -1; root.from = NULL; for(int k = 0; k < 12; k++) root.children[k] = NULL; insert(&root, goal, NULL, 0); //insert root in queue & dictionary pushS(&q1, goal); if(!(strcmp(goal, initial))){ //if goal is initial printf("%s\n", initial); destroyS(&q1); destroyS(&q2); return 0; } while(!(isEmptyS(&q1) && isEmptyS(&q2))){ //while queue not empty popQ(&q1, &q2, &nextStr); nextLen = lenInTrie(&root, nextStr); used = false; if(nextLen < maxlength){ //generate all the possible tiles for(int c = 0; c < width; c++){ //for all column shifts if(flag){//-r, then do it for all possible shifts for(int sh = 1; sh < width; sh++){ char *nextTiles = shiftC(nextStr, height, width, c, height - sh); //next tile pattern generated by a shift if(!strcmp(nextTiles, initial)){ insert(&root, nextTiles, nextStr, nextLen + 1); printSteps(root, nextTiles); destroyS(&q1); destroyS(&q2); return 0; } if(insert(&root, nextTiles, nextStr, nextLen + 1)){ pushS(&q1, nextTiles); //add it to the queue and dictionary used = true; } else free(nextTiles); } } else{//else do it for shift is one step only char *nextTiles = shiftC(nextStr, height, width, c, height - 1); //next tile pattern generated by a shift if(!strcmp(nextTiles, initial)){ insert(&root, nextTiles, nextStr, nextLen + 1); printSteps(root, nextTiles); destroyS(&q1); destroyS(&q2); return 0; } if(insert(&root, nextTiles, nextStr, nextLen + 1)){ pushS(&q1, nextTiles); //add it to the queue and dictionary used = true; } else free(nextTiles); } } for(int r = 0; r < height; r++){//for all possible row shifts if(flag){//-r, then do it for all possible shifts for(int sh = 1; sh < height; sh++){ char *nextTiles = shiftR(nextStr, height, width, r, width - sh); //next tile pattern generated by a shift if(!strcmp(nextTiles, initial)){ insert(&root, nextTiles, nextStr, nextLen + 1); printSteps(root, nextTiles); destroyS(&q1); destroyS(&q2); return 0; } if(insert(&root, nextTiles, nextStr, nextLen + 1)){ pushS(&q1, nextTiles); //add it to the queue and dictionary used = true; } else free(nextTiles); } } else{//else do it for shift is one step only char *nextTiles = shiftR(nextStr, height, width, r, width - 1); //next tile pattern generated by a shift if(!strcmp(nextTiles, initial)){ insert(&root, nextTiles, nextStr, nextLen + 1); printSteps(root, nextTiles); destroyS(&q1); destroyS(&q2); return 0; } if(insert(&root, nextTiles, nextStr, nextLen + 1)){ pushS(&q1, nextTiles); //add it to the queue and dictionary used = true; } else free(nextTiles); } } } if(!used) free(nextStr); }//end of while queue is not empty destroyS(&q1); destroyS(&q2); return 0; }
int main(int argc, char * argv[]){ Stack stack1; Stack stack2; Stack stack3; createS(&stack1); createS(&stack2); createS(&stack3); int flipped = 1; //equals 1 if lines are in same relative order as in files, -1 if flipped int pos = 0; int len = INT_MAX; int filestart = 1; //variable is incremented if there is a len/pos key int nlines = 0; //Number of lines beeing sorted char * end; if( argc == 1 ){ exit(1); } if(argv[1][0] == '-'){ filestart +=1; pos = strtol(&argv[1][1],&end,10); if(end[0] != ',' && strlen(end) != 0){ DIE("Invalid input"); } else if (strlen(end) != 0 ){ len = strtol(&end[1],&end,10); printf("%d", len); } if (strlen(end) != 0){ DIE("Invalid input"); } } char * line; FILE * fp; for(int m=filestart; m < argc; m++) { if(argv[m][0] == '-'){ fp = stdin; } else if ((fp = fopen(argv[m],"r")) == NULL){ DIE("Cannot read file"); } while((line = getLine(fp)) != NULL){ remove_break(&line); if(!pushS(&stack1, line)){ DIE("pushS failed to execute"); } nlines += 1; } fclose(fp); } split(&stack2, &stack1, &stack3, nlines, pos, len, -1, flipped * -1); while(!isEmptyS(&stack2)){ popS(&stack2, &line); printf("%s", line); free(line); printf("\n"); } while(!isEmptyS(&stack1)){ popS(&stack1, &line); printf("%s", line); free(line); printf("\n"); } destroyS(&stack1); destroyS(&stack2); destroyS(&stack3); return 1; }