diff --git a/RandomWriter/RandomWriter.pro b/RandomWriter/RandomWriter.pro index 85bdbce..b25432f 100644 --- a/RandomWriter/RandomWriter.pro +++ b/RandomWriter/RandomWriter.pro @@ -110,7 +110,6 @@ win32 { QMAKE_LFLAGS += -Wl,--stack,536870912 LIBS += -lDbghelp LIBS += -lbfd - LIBS += -liberty LIBS += -limagehlp } macx { diff --git a/RandomWriter/src/RandomWriter.cpp b/RandomWriter/src/RandomWriter.cpp index e591dac..67a30e7 100644 --- a/RandomWriter/src/RandomWriter.cpp +++ b/RandomWriter/src/RandomWriter.cpp @@ -6,9 +6,252 @@ #include "random.h" #include "strlib.h" #include "vector.h" + using namespace std; +struct Statistic{ + char letter; + int quantity; + double procent; +}; + +// global variables section + +// main map of seeds and their letter statistics +Map > seedsMap; + +// map of seed's frequency +Map seedFrequency; + +// model level +int modelLevel=0; + +// length of output text +const int numLettersToGenerate=2000; +// + +/** + * @brief getValidFileFromUser ask user for a file name and validate it + * @return validated file name as string + */ +string getValidFileFromUser(){ + string fName=""; + while(true){ + cout << "Enter file name: "; + cin >> fName; + ifstream ifs (fName); + if (ifs.is_open()){ + break; + } else { + cout << "That file could not be opened. Try again. \n"; + } + } + return fName; +} + +/** + * @brief getValidModelLevelFromUser ask user for a valid model level + * @return model level in range 1-10 + */ +int getValidModelLevelFromUser(){ + int res=0; + while(true){ + cout << "Enter model level (1-10): "; + cin >> res; + if ((res>0)&(res<=10)){ + break; + } else { + cout << "That level is incorrect. Try again. \n"; + } + } + return res; +} + +/** + * @brief incrementCounterSeeds increment counter of frequecy for current seed + * @param seed, frequency of which must be increased. + */ +void incrementCounterSeeds(string lastSeed){ + int counter=0; + if(seedFrequency.containsKey(lastSeed)) + counter=seedFrequency.get(lastSeed); + counter++; + seedFrequency.put(lastSeed,counter); +} + +/** + * @brief incrementCounterSeedsLetters increment counter of letter frequency for current seed. + * @param seed - working seed + * @param c - letter, frequency of which must be increased. + */ +void incrementCounterSeedsLetters(string seed, char c){ + Vector statVector; + + if(seedsMap.containsKey(seed)) + statVector=seedsMap.get(seed); + + bool isNewLetter=true; + + for(int i=0;i tmp; + tmp=seedsMap.get(elem); + cout << elem << " -> "; + for(auto elv:tmp){ + cout << " letter "<< elv.letter << "-" << elv.quantity<< "%" << elv.procent << " "; + } + cout << endl; + } +} + +/** + * @brief countStatProcents - count percent of frequency for each letter of each seed. + */ +void countStatProcents(){ + for(auto elem:seedsMap){ + Vector statVector=seedsMap.get(elem); + int totalLettersInSeedVector=0; + for(auto letterStat:statVector){ + totalLettersInSeedVector+=letterStat.quantity; + } + for(int i=0;imaxSN){ + maxSN=timesUsed; + maxSeed=el; + } + } + return maxSeed; +} + +/** + * @brief findLetterForSeed - randomly choose next letter for current seed, depending to letter's frequency statistic. + * @param seed - base seed + * @return founded char + */ +char findLetterForSeed(string seed){ + char res='o'; + Vector lettersStat=seedsMap.get(seed); + double rnddbl=randomReal(0, 1); + double currentSum=0; + for(auto letterStat:lettersStat){ + currentSum+=letterStat.procent; + if(currentSum>rnddbl){ + res=letterStat.letter; + break; + } + } + return res; +} + +/** + * @brief generateRandomText - generate and show on screen randomized text + * @param startSeed - start seed, which begin from. + */ +void generateRandomText(string startSeed){ + cout << startSeed; + string seed=startSeed; + + for(int i=0;i dic; + +// declare source and final words +string source_word; +string final_word; + +/** + * @brief fillDic select words from lexicon depending to required word length + * @param wordLength - int length of words to select + */ +void fillDic(int wordLength){ + dic.clear(); + for(string word:lex){ + if((word.length()==wordLength) && (word!=source_word)) + dic.add(word); + } +} + +/** + * @brief wordAlreadyInOldChain check if word already present in current chain + * @param wordToCheck - word to check + * @param Chain - vector of words to check in + * @return true - if present + */ +bool wordAlreadyInOldChain(string wordToCheck, Vector & Chain){ + bool res=false; + for(string usedWord:Chain){ + if(usedWord==wordToCheck){ + res=true; + break; + } + } + return res; +} + +/** + * @brief numberDifferentLetters count number of different letters between words + * @param wordToCheck - word to check:) + * @param lastWord - word to compare with + * @return int number of differences + */ +int numberDifferentLetters(string wordToCheck,string lastWord){ + int res=0; + for(int i=0; i findNewWordsInDic(string lastWord, Vector & oldChain){ + Vector res; + // look for words, that not equ lastWord & has 1 difference in letters from it & is'nt in oldChain Vector. + int i=0; + for(string word:dic){ + i++; + if((word==lastWord)||(word=="")||(wordAlreadyInOldChain(word,oldChain))||(numberDifferentLetters(word,lastWord)>1)) + continue; + res.add(word); + dic[i-1]=""; + } + return res; +} + +/** + * @brief showChain show chain of words to screen + * @param currentChain - chain to show + */ +void showChain(Vector & currentChain){ + for(auto word:currentChain){ + cout << word << " "; + } + cout << endl; +} + +/** + * @brief takeWord ask user to enter word + * @param msg - prompt message + * @return string, entered by user. + */ +string takeWord(string msg){ + string res; + cout << msg; + cin >> res; + return res; +} + +/** + * @brief check if destination word not present in local dictionary. + * @return false - if present. + */ +bool finalWordNotInDictionary(){ + bool res=true; + for(string word:dic){ + if(word==final_word){ + res=false; + break; + } + } + return res; +} + +/** + * @brief removeChainWordsFromDic - remove deadlock words from local dictionary + * @param chain - vector of words to be removed + */ +void removeChainWordsFromDic(Vector & chain){ + int i=0; + for(string dicElem:dic){ + if(dicElem=="") // already removed + continue; + for(string chainElem:chain) + if(chainElem==dicElem){ + dic.set(i,""); + break; + } + i++; + } +} + + +int main() +{ + while(true){ + source_word=takeWord("Source word ('q' to exit): "); + + if(source_word.length()==1) + break; + + final_word=takeWord("Destination word: "); + + cout << "I'm thinking..." << endl; + + if(final_word.length()!=source_word.length()){ + cout << "Detination word has incorrect length" << endl; + continue; + } + + // fill local dictionary + fillDic(source_word.length()); + cout << "Local dictionary: " << dic.size() << "words.\n"; + + // check for corrent length source and final words + if(finalWordNotInDictionary()){ + cout << "Detination word is absent in dictionary" << endl; + continue; + } + + // init first chain + Vector chain; + chain.add(source_word); + + // init chainsQueue + Queue> chainsQueue; + chainsQueue.enqueue(chain); + + bool chainFound=false; + + // main search loop + while(chainsQueue.size()>0){ + Vector currentChain=chainsQueue.dequeue(); + string lastWordOfCurrentChain=currentChain[currentChain.size()-1]; + + Vector expandingWords=findNewWordsInDic(lastWordOfCurrentChain,currentChain); + + if(expandingWords.size()==0){ // deadlock words chain found + removeChainWordsFromDic(currentChain); + } else { // expand the chainwith new words + for(auto word:expandingWords){ + Vector newChain(currentChain); + newChain.add(word); + //check, if final_word found?! + if(word==final_word){ + showChain(newChain); + chainFound=true; + break; + } + chainsQueue.enqueue(newChain); + } + } + if(chainFound) + break; + } + // message if not found chain... + if(chainsQueue.size()==0) + cout << "No chain between words:(" << endl; + } + return(0); }