diff --git a/RandomWriter/RandomWriter.pro b/RandomWriter/RandomWriter.pro index 85bdbce..35adfaf 100644 --- a/RandomWriter/RandomWriter.pro +++ b/RandomWriter/RandomWriter.pro @@ -110,7 +110,7 @@ win32 { QMAKE_LFLAGS += -Wl,--stack,536870912 LIBS += -lDbghelp LIBS += -lbfd - LIBS += -liberty + #LIBS += -liberty LIBS += -limagehlp } macx { diff --git a/RandomWriter/src/RandomWriter.cpp b/RandomWriter/src/RandomWriter.cpp index e591dac..44e070a 100644 --- a/RandomWriter/src/RandomWriter.cpp +++ b/RandomWriter/src/RandomWriter.cpp @@ -6,9 +6,91 @@ #include "random.h" #include "strlib.h" #include "vector.h" + +#include "filelib.h" +#include "simpio.h" + using namespace std; +/* Function Prototypes */ +string getSourceText(); +Map> analyzeText(string str, int k); +string findSeed(Map> &map); +string generateText(Map< string,Vector> &map, string str); + +/* Constants */ +const int NUMBER_OF_CHARACTERS = 2000; + int main() { - // TODO: fill in the code + + string text = getSourceText(); // get the original text file into a string + cout << endl; + int k = getInteger("Choose order of analysis (1 to 10):"); // get the number of the order to build the model + Map> map = analyzeText(text,k); // read a source text, build an order-k Markov model for it + string seed = findSeed(map); // get initial seed + string randomText = generateText(map, seed); // generating random text + cout << endl; + cout << randomText; + return 0; } + +/* This implementation prompts user for a filename and + * returns that file as a string. + */ +string getSourceText() { + cout << "Select one of the three source files: Hamlet.txt, Middlemarch.txt, and TomSawyer.txt." << endl; + ifstream stream; + cout << endl; + string filename = promptUserForFile(stream, "Please enter filename containing source text:"); + string text = readEntireFile(filename); + return text; +} + +/* This implementation takes in a string of text and an integer k. It returns + * a Map where each key is a k-character sequence found in the string. + * The associated value is a vector of all the characters that follow that + * seed in the string. This vector will likely contain multiple entries and + * duplicate values. These duplicates represent higher probability transitions + * from the Markov state. + */ +Map> analyzeText(string text, int k) { + Map> map; + for(int i = 0; i < text.length()-k; i++) { + map[text.substr(i,k)].add(text[i+k]); + } + return map; +} + +/* Chooses the sequence that appears most frequently in the source. + * Sequences are stored in the map that is passed in. If there are + * several sequences tied for most frequent this implementation + * returns the last occurence of those sequences. + */ +string findSeed(Map> &map) { + string seed; + int n = 0; + for(string seq : map) { + if(map.get(seq).size() > n) { + n = map.get(seq).size(); + seed = seq; + } + } + return seed; +} + +/* Implementation of generating random text. + */ +string generateText(Map> &map, string str) { + cout << "Processing..."; + cout << endl; + string seed = str; + string randomText = str; + for (int i = 0; i < NUMBER_OF_CHARACTERS; i++) { + int vectorLength = map[seed].size(); + int indexDraw = randomInteger(0, vectorLength-1); + seed = seed.substr(1,seed.length()-1) + map[seed][indexDraw]; + randomText += seed[seed.size()-1]; + } + return randomText; +} diff --git a/WordLadder/WordLadder.pro b/WordLadder/WordLadder.pro index 85bdbce..35adfaf 100644 --- a/WordLadder/WordLadder.pro +++ b/WordLadder/WordLadder.pro @@ -110,7 +110,7 @@ win32 { QMAKE_LFLAGS += -Wl,--stack,536870912 LIBS += -lDbghelp LIBS += -lbfd - LIBS += -liberty + #LIBS += -liberty LIBS += -limagehlp } macx { diff --git a/WordLadder/src/WordLadder.cpp b/WordLadder/src/WordLadder.cpp index 01d35d7..8307b81 100644 --- a/WordLadder/src/WordLadder.cpp +++ b/WordLadder/src/WordLadder.cpp @@ -4,9 +4,133 @@ #include "queue.h" #include "simpio.h" #include "vector.h" + using namespace std; +/* Function prototypes */ +string getStartWord(Lexicon &dictionary); +string getDestinationWord(Lexicon &dictionary, int length); +Vector findMetagrams(string word, Lexicon &dictionary); +Vector findWordLadder(string startWord, string destinationWord, Lexicon &dictionary); +void printWordLadder(Vector &ladder); + int main() { - // TODO: fill in the code - return 0; + /* Lexicon of English words. */ + const string WORD_LIST = "EnglishWords.dat"; + Lexicon dictionary(WORD_LIST); + + Vector wordLadder; + + while(true){ + /* Get the initial and final words */ + string startWord = getStartWord(dictionary); + string destinationWord = getDestinationWord(dictionary, startWord.length()); + /* Find and print word ladder */ + wordLadder = findWordLadder(startWord, destinationWord, dictionary); + printWordLadder(wordLadder); + } + return 0; +} +/* Function prompts the user for the initial word, checks its presence in the dictionary. + * If the user enters a blank line terminates the program. + */ +string getStartWord(Lexicon &dictionary){ + string startWord = ""; + while (true) { + startWord = toLowerCase(getLine("Enter start word (RETURN to quit): ")); + if (startWord == ""){ + exit(0); + } else if (!dictionary.contains(startWord)){ + cout << "Please enter a valid word!" << endl; + } else break; + } + return startWord; +} +/* The function prompts the user for the final word, + * check for it in the dictionary and matching the length of the first word. + */ +string getDestinationWord(Lexicon &dictionary, int length){ + string destinationWord = ""; + while (true) { + destinationWord = toLowerCase(getLine("Enter destination word: ")); + if (dictionary.contains(destinationWord) && destinationWord.length() == length){ + break; + } else if (!dictionary.contains(destinationWord) && !(destinationWord.length() == length)){ + cout << "Please enter a valid word of " << length << " letters!" << endl; + } else if (!dictionary.contains(destinationWord)){ + cout << "Please enter a valid word!" << endl; + } else if (!(destinationWord.length() == length)){ + cout << "Destination word must be " << length << " letters!" << endl; + } + } + return destinationWord; +} +/* The function takes an original word and finds it Metagrams in the dictionary. + * Returns vector Metagrams. + */ +Vector findMetagrams(string parentalWord, Lexicon &dictionary){ + Vector metagrams; + string tmp = ""; + + for (int i = 0; i < parentalWord.length(); i++){ + for (char ch = 'a'; ch <= 'z'; ch++){ + tmp = parentalWord; + tmp[i] = ch; // generation word + if (tmp != parentalWord && dictionary.contains(tmp)){ // check in dictionary and unique + metagrams.add(tmp); // add to vector + } + } + } + return metagrams; +} +/* Function finds the word ledder between two words + * using Breadth-first search algorithm. + */ +Vector findWordLadder(string startWord, string destinationWord, Lexicon &dictionary){ + + Vector wordLadder; + Vector emptyWordLadder; + Lexicon usedWords; + Queue> ladders; + + wordLadder.add(startWord); + usedWords.add(startWord); + ladders.enqueue(wordLadder); + + while (!ladders.isEmpty()){ + wordLadder = ladders.dequeue(); // Removes and returns the first item in the queue. + // short ladder found if last element of word ladder == destination word + if (wordLadder[wordLadder.size() - 1] == destinationWord){ + return wordLadder; // + } + // Looking Metagrams for the word standing at the end of the current ladder. + Vector metagrams = findMetagrams(wordLadder[wordLadder.size() - 1], dictionary); + // Looking at Metagrams words have not been used before and are adding to the ladders + for(string word : metagrams){ + if(!usedWords.contains(word)){ + usedWords.add(word); + Vector tmp = wordLadder; + tmp.add(word); + ladders.enqueue(tmp); + } + } + } + return emptyWordLadder; +} +/* The function displays the ladder of words or a message about her absence. */ +void printWordLadder(Vector &ladder){ + if(ladder.size() > 0){ + for (int i = 0; i < ladder.size(); i++){ + if (i < ladder.size() - 1){ + cout << ladder[i] << " -> "; + } + else { + cout << ladder[i] << endl; + } + } + } + else { + cout << "Word ladder not found." << endl; + + } }