// 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; }
int pruneT(Trie* st, Trie *newst, int e, int oldstCodes) { // if escape flag, start from 3 without checking if reserved. int newCount = (e) ? 3 : 259; // codeCount of new string table // index of old trie we are iterating thru to copy int oldindex = (e) ? 3 : 259; // copy the appearances of the first 256 non-reserved codes for(int i=3; i<newCount; i++){ (*newst)[i].appearances = (*st)[i].appearances/2; } while(oldindex < oldstCodes) { if(((*st)[oldindex].appearances/2)) { if(filledTable(newCount+1)){ expandT(newst, (newCount+1)*2); } addT(newst, (*st)[oldindex].prefix, (*st)[oldindex].suffix, newCount); (*newst)[newCount].appearances = (*st)[oldindex].appearances/2; for(int i=0; i<(*st)[oldindex].childCount; i++){ ((*st)[(*st)[oldindex].children[i]]).prefix = newCount; } newCount++; } oldindex++; } return newCount; }
boost::shared_ptr<Continent> TeamDatabase::getOrCreateContinent(const char* n) { boost::shared_ptr<Soccer::Continent> cont = getT(n); if(!cont) { cont = boost::shared_ptr<Soccer::Continent>(new Soccer::Continent(n)); addT(cont); } return cont; }
boost::shared_ptr<League> TeamDatabase::getOrCreateLeague(const char* continentName, const char* countryName, const char* leagueName, unsigned int level) { auto lsys = getOrCreateLeagueSystem(continentName, countryName); auto leag = lsys->getT(leagueName); if(!leag) { leag = boost::shared_ptr<Soccer::League>(new Soccer::League(leagueName, level)); lsys->addT(leag); } return leag; }
boost::shared_ptr<LeagueSystem> TeamDatabase::getOrCreateLeagueSystem(const char* continentName, const char* countryName) { auto cont = getOrCreateContinent(continentName); auto lsys = cont->getT(countryName); if(!lsys) { lsys = boost::shared_ptr<Soccer::LeagueSystem>(new Soccer::LeagueSystem(countryName)); cont->addT(lsys); } return lsys; }
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; }
// 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); }