Automate::~Automate(){ deleteTableTranstion(); deleteQ(); deleteI(); deleteT(); }
bool Automate::ouvrir(const string& nomFichier){ deleteTableTranstion(); deleteA(); deleteQ(); deleteI(); deleteT(); ifstream fichier(nomFichier.c_str(), ios::in); if (fichier.is_open()){ string charA; string charQ; string charI; string charT; string charTDT; string temp; getline(fichier,charA); for(unsigned int i = 0; i < charA.size(); i++) { temp.clear(); while ((i < charA.size())&&(charA[i] == ' ')) i++; while((i < charA.size())&&(charA[i] != ' ')){ temp += charA.substr(i,1); i++; } _A.push_back(temp); } getline(fichier,charQ); for(unsigned int i = 0; i < charQ.size(); i++) { temp.clear(); while ((i < charQ.size())&&(charQ[i] == ' ')) i++; while((i < charQ.size())&&(charQ[i] != ' ')){ temp += charQ.substr(i,1); i++; } _Q.push_back(new list<string>); (*--_Q.end())->push_back(temp); } getline(fichier,charI); for(unsigned int i = 0; i < charI.size(); i++) { temp.clear(); while ((i < charI.size())&&(charI[i] == ' ')) i++; while((i < charI.size())&&(charI[i] != ' ')){ temp += charI.substr(i,1); i++; } _I.push_back(new list<string>); (*--_I.end())->push_back(temp); } getline(fichier,charT); for(unsigned int i = 0; i < charT.size(); i++) { temp.clear(); while ((i < charT.size())&&(charT[i] == ' ')) i++; while((i < charT.size())&&(charT[i] != ' ')){ temp += charT.substr(i,1); i++; } _T.push_back(new list<string>); (*--_T.end())->push_back(temp); } list<list<string>*>::iterator iQ; for(iQ=_Q.begin(); iQ!=_Q.end(); iQ++){ _tab[*iQ]=new list<list<string>*>[_A.size()]; } getline(fichier,charTDT); iQ = _Q.begin(); unsigned int col; unsigned int start; while ((!fichier.eof())&&(iQ != _Q.end())){ getline(fichier,charTDT); col = 0; start = 0; while ((start < charTDT.size())&&(charTDT[start] == ' ')) start++; while(charTDT[start] != ' ') start++; for(unsigned int i=start; i < charTDT.size(); i++){ temp.clear(); while ((i < charTDT.size())&&(charTDT[i] == ' ')) i++; while((i < charTDT.size())&&(charTDT[i] != ',')&&(charTDT[i] != ' ')){ temp += charTDT.substr(i,1); i++; } if (temp != "-"){ _tab[*iQ][col].push_back(new list<string>); (*--_tab[*iQ][col].end())->push_back(temp); } if (charTDT[i] == ','){ i++; } else{ col++; } } iQ++; } return true; } return false; }
void Automate::determinisation(){ /* Determinise l'automate * */ list<list<string>*> Qdet; list<list<string>*> Tdet; // Creation de l'etat initial (= premier etat de la liste des etats) Qdet.push_back(new list<string>); list<list<string>*>::iterator iQdet = Qdet.begin(); _tab[*iQdet] = new list<list<string>*>[_A.size()]; for(list<list<string>*>::iterator iI=_I.begin(); iI!=_I.end(); iI++) (*iQdet)->insert((*iQdet)->begin(),(*iI)->begin(),(*iI)->end()); (*iQdet)->sort(); (*iQdet)->unique(); // Remplace les etats initiaux pour le nouvel etat initial _I.clear(); _I.push_back(new list<string>); (*_I.begin())->assign((*iQdet)->begin(),(*iQdet)->end()); // Creer la nouvelle table de transition et la nouvelle liste des etats list<list<string>*>::iterator iQ; list<string>::iterator iiQdet; unsigned int cpt; // Tant qu'il y a des etats dans la nouvelle liste des etats while(iQdet != Qdet.end()){ for(cpt=0; cpt<_A.size(); cpt++){ _tab[*iQdet][cpt].push_back(new list<string>); } // Creation des nouvelles transitions pour l'etat concerne for(iQ=_Q.begin(); iQ!=_Q.end(); iQ++){ for(iiQdet=(*iQdet)->begin(); iiQdet!=(*iQdet)->end(); iiQdet++){ if (find((*iQ)->begin(),(*iQ)->end(),*iiQdet) != (*iQ)->end()){ for(cpt=0; cpt<_A.size(); cpt++){ list<list<string>*>::iterator iiTab; iiTab = _tab[*iQdet][cpt].begin(); for(list<list<string>*>::iterator iTab=_tab[*iQ][cpt].begin(); iTab!=_tab[*iQ][cpt].end(); iTab++) (*iiTab)->insert(--(*iiTab)->end(),(*iTab)->begin(),(*iTab)->end()); } } } } int temp; list<list<string>*>::iterator iTab; // Tri des nouvelles transitions pour l'etat concerne, et creation d'un nouvel etat a partir des nouvelles transition (s'il n'existait pas deja) for(cpt=0; cpt<_A.size(); cpt++){ iTab=_tab[*iQdet][cpt].begin(); while((!_tab[*iQdet][cpt].empty())&&(iTab!=_tab[*iQdet][cpt].end())){ if((*iTab)->empty()){ _tab[*iQdet][cpt].erase(iTab); iTab--; } else{ (*iTab)->sort(); (*iTab)->unique(); } iTab++; } temp = 0; iTab = _tab[*iQdet][cpt].begin(); // Creation d'un nouvel etat (s'il n'existait pas deja) for(iQ=Qdet.begin(); iQ!=Qdet.end(); iQ++){ if((_tab[*iQdet][cpt].empty())||(((*iTab)->size() == (*iQ)->size())&&(equal((*iTab)->begin(),(*iTab)->end(),(*iQ)->begin())))) temp = 1; } if (temp == 0){ Qdet.push_back(new list<string>); _tab[*(--Qdet.end())] = new list<list<string>*>[_A.size()]; (*(--Qdet.end()))->assign((*iTab)->begin(),(*iTab)->end()); } } iQdet++; } // Suppression de l'ancienne table de transition deleteTableTranstion(); // Remplace l'ancienne liste des etats par la nouvelle deleteQ(); _Q = Qdet; // Creation de la nouvelle liste des etats teminaux (tout etat contenant un ancien etat terminal est terminal) for(list<list<string>*>::iterator iT=_T.begin(); iT!=_T.end(); iT++){ for(iQ=_Q.begin(); iQ!=_Q.end(); iQ++){ if(search((*iQ)->begin(),(*iQ)->end(),(*iT)->begin(),(*iT)->end()) != (*iQ)->end()){ int temp = 0; list<list<string>*>::iterator iTdet; iTdet = Tdet.begin(); while ((iTdet != Tdet.end())&&(temp == 0)){ if (((*iQ)->size() == (*iTdet)->size())&&(equal((*iQ)->begin(),(*iQ)->end(),(*iTdet)->begin()))) temp = 1; iTdet++; } if (temp == 0){ Tdet.push_back(new list<string>); (*(--Tdet.end()))->assign((*iQ)->begin(),(*iQ)->end()); } } } } // Remplace l'ancienne liste des etats terminaux par la nouvelle deleteT(); _T = Tdet; }
bool Automate::minimiser(){ /* Minimise l'automate * Retourne true si l'automate etait deja minimal <=> Le nombre de groupe cree lors de la minimisation est egal au nombre d'etat de l'automate * Retourne false si l'automate n'etait pas minimal * */ list<string> groupes; // La liste des groupes Ex : {NT, T} list<string> tempgroupes; // Une liste des groupes temporaires string groupeString; // Le groupe auquel appartient un etat map<string, list<list<string>*>*> tabG; // Un tableau indexe par les groupes contenant la liste des etats dans un groupe //Initialisation de tempGroupes et de tabG tempgroupes.push_back("NT"); tempgroupes.push_back("T"); tabG["NT"] = new list<list<string>*>; tabG["T"] = new list<list<string>*>; for(list<list<string>*>::iterator iQ=_T.begin(); iQ!=_T.end(); iQ++) tabG["T"]->push_back(*iQ); for(list<list<string>*>::iterator iQ=_Q.begin(); iQ!=_Q.end(); iQ++){ int temp = 0; for(list<list<string>*>::iterator iT=_T.begin(); iT!=_T.end(); iT++){ if( ((*iT)->size() == (*iQ)->size()) && (equal( (*iQ)->begin(), (*iQ)->end(), (*iT)->begin()) )){ temp = 1; } } if(temp == 0) tabG["NT"]->push_back(*iQ); } list<string>::iterator iG; QStringList liste; QString tempS; int cptG; // Tant que le nombre de groupe n'est pas egal a celui de la derniere iteration while (groupes.size() != tempgroupes.size()) { // Initialisation de groupes et reinitialisation de tempgroupes groupes = tempgroupes; tempgroupes.clear(); cptG = 1; for(list<string>::iterator i = groupes.begin(); i != groupes.end(); i++){ tempS.clear(); tempS += "Group " + QString::number(cptG) + " : "; for(list<list<string>*>::iterator ii = tabG[*i]->begin(); ii != tabG[*i]->end(); ii++){ if (ii != tabG[*i]->begin()) tempS += ", "; tempS += "{"; for(list<string>::iterator iii = (*ii)->begin(); iii != (*ii)->end(); iii++){ if(iii != (*ii)->begin()) tempS += ", "; tempS += QString::fromStdString(*iii); } tempS += "}"; } liste << tempS; cptG++; } liste << ""; // Pour chaque etat for(list<list<string>*>::iterator iQ=_Q.begin(); iQ!=_Q.end(); iQ++){ // Reinitialisation de groupeString groupeString.clear(); iG = groupes.begin(); int temp; // Faire tant que nous ne trouvons pas dans quel groupe est cet etat temp = 1; do { for(list<list<string>*>::iterator iiG = tabG[*iG]->begin(); iiG != tabG[*iG]->end(); iiG++){ // Si les etats sont egaux if (((*iiG)->size() == (*iQ)->size())&&(equal((*iiG)->begin(), (*iiG)->end(), (*iQ)->begin()))) temp = 0; } iG++; }while(temp == 1); iG--; // Insertion de ce groupe dans groupeString groupeString = groupeString + *iG; for (unsigned int cpt = 0; cpt != _A.size(); cpt++){ int temp; iG = groupes.begin(); temp = 1; do{ list<list<string>*>::iterator iTab = _tab[*iQ][cpt].begin(); for(list<list<string>*>::iterator iiG = tabG[*iG]->begin(); iiG != tabG[*iG]->end(); iiG++){ if (((*iiG)->size() == (*iTab)->size())&&(equal((*iiG)->begin(), (*iiG)->end(), (*iTab)->begin()))) // Si les etats ne sont pas egaux temp = 0; } iG++; }while(temp == 1); iG--; // Insertion de ce groupe dans groupeString groupeString = groupeString + *iG; } if(tabG[groupeString] == NULL){ tabG[groupeString] = new list<list<string>*>; } // Insertion de cet etat dans son groupe tabG[groupeString]->push_back(*iQ); tempgroupes.push_back(groupeString); tempgroupes.sort(); tempgroupes.unique(); } // Suppression des anciens groupes for (list<string>::iterator it=groupes.begin(); it != groupes.end(); it++) tabG[*it]->clear(); } Interface::messageMinimiser(&liste); groupes = tempgroupes; tempgroupes.clear(); if(groupes.size() == _Q.size()) return true; list<list<string>*> Qmin, Tmin, Imin; list<string>::iterator iGG; list<list<string>*>::iterator iTabG; list<list<string>*>::iterator iTab; int temp; list<list<string>*>::iterator iI; list<list<string>*>::iterator iIm; iI = _I.begin(); iG=groupes.begin(); temp = 1; do { for(list<list<string>*>::iterator iiG = tabG[*iG]->begin(); iiG != tabG[*iG]->end(); iiG++){ if (((*iiG)->size() == (*iI)->size())&&(equal((*iiG)->begin(), (*iiG)->end(), (*iI)->begin()))) // Si les etats ne sont pas egaux temp = 0; } iG++; }while(temp == 1); iG--; Imin.push_back(new list<string>); iIm =-- Imin.end(); for(list<list<string>*>::iterator iTabGG = tabG[*iG]->begin(); iTabGG != tabG[*iG]->end(); iTabGG++) (*iIm)->insert(--(*iIm)->end(), (*iTabGG)->begin(), (*iTabGG)->end()); deleteI(); _I = Imin; list<list<string>*>::iterator iTmin; for(list<string>::iterator iG = groupes.begin(); iG != groupes.end(); iG++){ if ((*iG).at(0) == 'T'){ Tmin.push_back(new list<string>); iTmin =-- Tmin.end(); for(list<list<string>*>::iterator iTabG = tabG[*iG]->begin(); iTabG != tabG[*iG]->end(); iTabG++){ (*iTmin)->insert(--(*iTmin)->end(), (*iTabG)->begin(), (*iTabG)->end()); } } } deleteT(); _T = Tmin; list<list<string>*>::iterator iQmin; list<list<string>*>::iterator iTabmin; for(list<string>::iterator iG=groupes.begin(); iG != groupes.end(); iG++){ // Creation des états Qmin.push_back(new list<string>); iQmin = --Qmin.end(); for(iTabG = tabG[*iG]->begin(); iTabG != tabG[*iG]->end(); iTabG++){ (*iQmin)->insert(--(*iQmin)->end(), (*iTabG)->begin(), (*iTabG)->end()); } // Creation des transitions associes a chaque etat _tab[*(--Qmin.end())] = new list<list<string>*>[_A.size()]; // Pour chaque transition for(unsigned int cpt = 0; cpt < _A.size(); cpt++){ // Pour un etat dans le groupe iTabG = tabG[*iG]->begin(); // Pour une transition de de cet etat dans le groupe iTab = _tab[*iTabG][cpt].begin(); int temp; iGG = groupes.begin(); temp = 1; // Faire tant que nous ne trouvons pas dans quel groupe est cet etat do { for(list<list<string>*>::iterator iiG = tabG[*iGG]->begin(); iiG != tabG[*iGG]->end(); iiG++){ if (((*iiG)->size() == (*iTab)->size())&&(equal((*iiG)->begin(), (*iiG)->end(), (*iTab)->begin()))) temp = 0; } iGG++; }while(temp == 1); iGG--; _tab[*(--Qmin.end())][cpt].push_back(new list<string>); iTabmin =-- _tab[*(--Qmin.end())][cpt].end(); for(list<list<string>*>::iterator iTabGG = tabG[*iGG]->begin(); iTabGG != tabG[*iGG]->end(); iTabGG++) (*iTabmin)->insert(--(*iTabmin)->end(), (*iTabGG)->begin(), (*iTabGG)->end()); } } deleteQ(); _Q = Qmin; return false; }
/* 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; }