int ListWords(const map<char,string> &keypads,string prex,string digitSequence,string alber,Lexicon &lex){ int count=0; if(digitSequence.empty()&&lex.containsPrefix(prex)){ if(lex.containsWord(prex)){ count++; cout<<prex<<endl; } for(unsigned int i=0;i<alber.size();i++){ string p=prex; p.push_back(alber[i]); count+=ListWords(keypads,p,digitSequence,alber,lex); } return count; } if(!digitSequence.empty()&&lex.containsPrefix(prex)){ string nextchar=(keypads.find(digitSequence[0]))->second; digitSequence.erase(digitSequence.begin()); for(unsigned int i=0;i<nextchar.size();i++){ string p=prex; p.push_back(nextchar[i]); count+=ListWords(keypads,p,digitSequence,alber,lex); } } return count; }
void checkLexicon(string indexLetters, Lexicon & lex) { string lowerCase = UpToLow(indexLetters); foreach (string word in lex) { Lexicon newLex; newLex.add(word); if(newLex.containsPrefix(indexLetters) || newLex.containsPrefix(lowerCase)) { cout << word << endl; } }
TIMED_TEST(LexiconTests, basicTest_Lexicon, TEST_TIMEOUT_DEFAULT) { std::initializer_list<std::string> words = { "a", "ab", "aab", "aaab", "aardvark", "b", "banana" }; std::initializer_list<std::string> badWords = { "abb", "ad", "and", "aaardvark", "aardvarks", }; std::initializer_list<std::string> badPrefixes = { "aaaa", "abb", "aardvarz", "bb", "bananas", "c", "r", "z" }; Lexicon lex; for (std::string word : words) { lex.add(word); } assertEquals("Lexicon size", words.size(), lex.size()); for (std::string word : words) { assertTrue("Lexicon contains " + word, lex.contains(word)); } for (std::string word : badWords) { assertFalse("Lexicon contains " + word, lex.contains(word)); } for (std::string word : words) { for (int i = 0; i < (int) word.length(); i++) { std::string prefix = word.substr(0, i); assertTrue("Lexicon containsPrefix " + word, lex.containsPrefix(word)); } } for (std::string word : badPrefixes) { assertFalse("Lexicon containsPrefix " + word, lex.containsPrefix(word)); } }
/* * Recursive Computer Search * * Recursively searches the Boggle board to find all the * words that can be made on the board and haven't * been guessed correctly by the human player */ void recursiveComputer(int row, int col, string word, Grid<string>& board, Lexicon& dictionary, Set<string>& results, Grid<bool>& visitedCubes, int& computerScore, Set<string>& usedWords){ if(!board.inBounds(row, col)) return; if(dictionary.contains(word) && word.length() >= 4) { if (!results.contains(word) && !usedWords.contains(word)) { computerScore += word.length() - 3; results.add(word); } } if(!dictionary.containsPrefix(word)){ return; } word = word + board[row][col]; visitedCubes[row][col] = true; for(int i = -1; i <= 1; i++){ for(int j = -1; j <= 1; j++){ if(visitedCubes.inBounds(row + i, col + j) && !visitedCubes[row + i][col + j]){ recursiveComputer(row + i, col + j, word, board, dictionary, results, visitedCubes, computerScore, usedWords); } if(visitedCubes.inBounds(row + i, col + j) && dictionary.contains(word) && !results.contains(word) && word.length() >=4) { computerScore += word.length() - 3; results.add(word); } } } visitedCubes[row][col] = false; }
/* ListCompletions(string, Lexicon): * Prints all words from the lexicon that can be formed by extending * the given digit sequence. */ void ListCompletions(string digits, Lexicon & lex) { int index=0; /*find the first digit*/ while(index<(int)digits.length() && !isdigit(digits[index])) index++; /*Don't start checking until the digits have been entirely converted to letters*/ if(index == digits.length() ){ string word = digits; //redundant, but helps me understand /*Lexicon doesn't containPrefix=>these aren't the droids I'm looking for*/ if(!lex.containsPrefix(word)) return; /*Otherwise check if the current word is in the lexicon and print it if it is*/ if( lex.contains(word)){ cout << "\t" << word << endl; } /*...and then try recursively checking after adding each letter*/ for( char ch='a'; ch<='z'; ++ch){ string newWord = digits + ch; ListCompletions(newWord, lex); } return; } /*make a prefix out of the current letters, check what could come next, and recursively check each*/ string prefix = digits.substr(0, index); string digitLetters = letterSets[digits[index] - '0']; //subtracting '0' converts digits[index] a char to an int int i=0; //not intuitive at all while(i<digitLetters.length()){ ListCompletions(prefix + digitLetters[i] + digits.substr(index + 1), lex ); i++; } }
Vector<string> sloveBoggle(Grid<char> &grid, Point start, int depth, Vector<Point> &path, string &word, Lexicon &lex) { Vector<string> result; if (depth > MAX_LENGTH) { // greater than maxium length, return // return lex.containsWord(word); } else { //recursion to the element around the current element. int i = start.x; int j = start.y; if(lex.containsWord(word) && depth >= MIN_LENGTH) { result.add(word); } for(Direction dir = TOPLEFT; dir <= LEFT; dir++) { if(isBound(grid, i, j, dir)) { Point new_start = adjustPoint(start, dir); if(isContainPoint(path, new_start)) continue; string new_word = word + grid.getAt(new_start.x, new_start.y); if(!lex.containsPrefix(new_word)) continue; path.add(new_start); depth++; Vector<string> res = sloveBoggle(grid, new_start, depth, path, new_word, lex); result = concateVec(result, res); path.removeAt(path.size() - 1); depth--; } } } return result; }
static void generateAllPossibleWords(const Grid<char> & boggleBoard, Set<string> & wordsSpottedSoFar, const Lexicon & english, int rowIndex, int colIndex, string buildingWord, Set<coord> wordPath){ buildingWord += boggleBoard[rowIndex][colIndex]; if (buildingWord.size() >= kMinGuessLength && english.contains(buildingWord) && !wordsSpottedSoFar.contains(buildingWord)) { wordsSpottedSoFar.add(buildingWord); recordWordForPlayer(buildingWord, COMPUTER); } if (!english.containsPrefix(buildingWord)) return; for (int i = -1; i <= 1; i++) { for (int j = -1; j <=1; j++){ if(isShiftValid(boggleBoard, rowIndex, colIndex, i, j)){ coord nextPos; nextPos.row = rowIndex + i; nextPos.col = colIndex + j; if (!wordPath.contains(nextPos)){ wordPath.add(nextPos); generateAllPossibleWords(boggleBoard, wordsSpottedSoFar, english, rowIndex + i, colIndex + j, buildingWord, wordPath); wordPath.remove(nextPos); } } } } }
//credit to erickwill, his code guided me to the answer void recursiveFindWord(int row, int col,std::string soFar, Grid<char> &grid, Lexicon words, Vector<std::string> &foundWords) { char orig = grid.get(row,col); soFar = soFar + grid.get(row,col); drawCubes(grid); cout << "row = " << row << " col = " << col << endl; cout << "sofar = " << soFar << endl; if(words.contains(soFar) && !containsWord(foundWords,soFar)){ cout << "contains word: " << soFar << endl; foundWords.push_back(soFar); return; } if(!words.containsPrefix(soFar)){ cout << "does not contain prefix: " << soFar << endl; return; } for(int i = -1; i < 2; i++){ for(int j = -1; j < 2; j++){ if(row+i>=0 && col+j >=0 && row+i < grid.numRows() && col+j < grid.numCols() && (row+i < grid.numRows() && col+j < grid.numCols()) && !(i==0 && j==0) && grid.get(row+i,col+j) != '~') { grid.set(row,col,'~'); recursiveFindWord(row+i,col+j,soFar,grid,words,foundWords); grid.set(row,col,orig); } } } return; }
// checks lexicon and prints all words that begin with the given prefix void printValidWords(string prefix, Lexicon &lex){ string alpha = "abcdefghijklmnopqrstuvwxyz"; if(lex.containsWord(prefix)) cout << prefix << " "; if(lex.containsPrefix(prefix)){ for(int i = 0; i < alpha.length(); i++){ printValidWords(prefix + alpha.at(i), lex); } } }
void ListCompletionsRec(Vector<string>prefixes, Lexicon & lex) { for (int i = 0; i < prefixes.size(); i ++) { string current = prefixes[i]; if (lex.contains(current) || lex.containsPrefix(current)) { for (int i = 0; i < alphabet.length(); i ++) { current += alphabet[i]; ListCompletionsRec(prefixes, lex); } } } }
/** * @brief Gets possible completions for a given word * @param word The word to check for completions * @param lex The lexicon to check completions against * @param words A set that will be filled with possible completions * * This function recursively checks for possible completions of a given * word, using the provided lexicon. */ void getCompletions(string word, Lexicon &lex, Set<string> &words) { if (lex.containsWord(word)) { words.add(word); } for (int i = 0; i < ALPHABET.size(); i++) { string newWord = word + ALPHABET[i]; if (lex.containsPrefix(newWord)) { getCompletions(newWord, lex, words); } } }
void SearchAll(string &word, string &occupy, int row, int col) { int pos = row * size + col; occupy[pos] = OCCUPY; path.push_back(SPoint(row, col)); word += tolower(board[pos]); if(!english.containsPrefix(word)) { word = word.substr(0, word.size() - 1); occupy[pos] = EMPTY; path.pop_back(); return; } if(word.size() >= 4 && InEnglish(word) && !InHumanWord(word)) { recordWordForPlayer(word, COMPUTER); humanword.push_back(word); showpath(); } //cout << word << ' ' << row << ' ' << col << endl; //Up if(row != 0 && occupy[pos - size] == EMPTY) SearchAll(word, occupy, row - 1, col); //Down if(row != size - 1 && occupy[pos + size] == EMPTY) SearchAll(word, occupy, row + 1, col); //Right if(col != size - 1 && occupy[pos + 1] == EMPTY) SearchAll(word, occupy, row, col + 1); //Left if(col != 0 && occupy[pos - 1] == EMPTY) SearchAll(word, occupy, row, col - 1); //UpRight if(row != 0 && col != size - 1 && occupy[pos - size + 1] == EMPTY) SearchAll(word, occupy, row - 1, col + 1); //UpLeft if(row != 0 && col != 0 && occupy[pos - size - 1] == EMPTY) SearchAll(word, occupy, row - 1, col - 1); //DownLeft if(row != size - 1 && col != 0 && occupy[pos + size - 1] == EMPTY) SearchAll(word, occupy, row + 1, col - 1); //DownRight if(row != size - 1 && col != size - 1 && occupy[pos + size + 1] == EMPTY) SearchAll(word, occupy, row + 1, col + 1); word = word.substr(0, word.size() - 1); path.pop_back(); occupy[pos] = EMPTY; }
/** Recursive function used to populate a vector of words found from an initial position on the board and used to search words for the computer. This function returns a Vector of string elements. **/ Vector<string> ComputerWordSearch(Grid<char> &Board,string Candidate,Location Cursor,Lexicon &English) { //Board copy to make recursive call Grid<char> NewBoard=Grid<char>(); Location Pos; //Vector to store results Vector<string> Aux=Vector<string>(); //vector to indicate failure, empty vector Vector<string> EmptyVec=Vector<string>(); //if the search is heading to failure finish it if((!English.containsPrefix(Candidate))||Candidate.length()>8) return EmptyVec; //if you found a valid word, add it to your vector if(Candidate.length()>3&&English.contains(Candidate)) { Aux.add(Candidate); } //search the adjacent cubes in search of a valid word path for(int dx=-1;dx<=1;dx++) { for(int dy=-1;dy<=1;dy++) { //if I point to the same cube or I am out of the board or I already used the cube do not search that way if(!(dx==0&&dy==0)&&Board.inBounds(Cursor.row+dx,Cursor.col+dy)&&(Board[Cursor.row+dx][Cursor.col+dy]!=USED)) { //add char to candidate Candidate+=Board[Cursor.row+dx][Cursor.col+dy]; //create board copy and mark used the char taken NewBoard=Board; NewBoard[Cursor.row+dx][Cursor.col+dy]=USED; Pos.row=Cursor.row+dx; Pos.col=Cursor.col+dy; //if you can find a word using the path chosen, add the word to aux if(!ComputerWordSearch(NewBoard,Candidate,Pos,English).isEmpty()) { Aux+=ComputerWordSearch(NewBoard,Candidate,Pos,English); } //backtracking, if I could not find a word this way I need to remove the last char from my candidate Candidate=Candidate.substr(0,Candidate.length()-1); } } } //return your vector full of valid words return Aux; }
/* * Function: FindWordsonBoard * ------------------------------ * Recursively searchs for all possible words that can be created from dice configuration of boggleBoard starting from * the specified location. * *@return bool true if the char arrangement found is an actual word. * false if all possibilities have been exhausted and no word is created. */ bool FindWordsOnBoard(Grid<char> boggleBoard, int row, int col, string partialWord, Grid<bool> usedDice, Lexicon wordList, Lexicon &usedWords) { int newRow, newCol; if (OffBoard(boggleBoard, row, col) || usedDice.getAt(row, col) == true) return false; partialWord += boggleBoard.getAt(row, col); //keeps track of current char arrangement if (!wordList.containsPrefix(partialWord)) return false; //checks if partialWord is a prefix of any word in wordList usedDice.setAt(row, col, true); //marks the dice as used if (wordList.containsWord(partialWord) && partialWord.length() >= minWordLength && !usedWords.containsWord(partialWord)) { //checks if partialWord is an actual word meeting the minimum length and has not been used by either the player or computer RecordWordForPlayer(partialWord, Computer); usedWords.add(partialWord); //adds the word found to list of used words } for(int i = 0; i < 8; i++) { //there are 8 possible paths the char arrangement can take FindPossiblePath(newRow, newCol, row, col, i); if (FindWordsOnBoard(boggleBoard, newRow, newCol, partialWord, usedDice, wordList, usedWords)) return true; } usedDice.setAt(row, col, false); //unmarks the dice as unused when current char configuration turns out fruitless return false; }
bool findWord(string sofar, pointT position, Grid<char> &board, Lexicon &lex, Vector<pointT> deltas, Set<string> &acc) { if( validBoggle(sofar, lex) ) { acc.add(sofar); return true; } Vector<pointT> next = successors(position, board, deltas); for (int i = 0; i < next.size(); i++) { pointT nextPt = next[i]; char ch = board.getAt(nextPt.row, nextPt.col); string prefix = sofar + ch; if ( lex.containsPrefix( prefix ) ) { Grid<char> copy = board; copy.setAt(nextPt.row, nextPt.col, 'f'); if ( findWord(prefix, nextPt, copy, lex, deltas, acc) ) return true; } } return false; }
void FindAllWords(int row, int col, Grid<string> & board, Lexicon & lex, Set<string> & wordsSeen, string soFar, Vector<locationT> visited) { locationT here; here.numRow = row; here.numCol = col; visited.add(here); soFar += board(row,col); if (!lex.containsPrefix(soFar)) { //return if this is a dead end return; } if (lex.containsWord(soFar) && (!wordsSeen.contains(soFar)) && soFar.size() > 3) { RecordWordForPlayer(soFar, Computer); //found a word, so record it wordsSeen.add(soFar); } for (int i = 0; i < board.numRows(); i++) { for (int j = 0; j < board.numCols(); j++) { if (AreNeighbors(row, col, i, j) && NotDuplicated(i, j, visited)) { //recur on the rest of the puzzle for all FindAllWords(i, j, board, lex, wordsSeen, soFar, visited); //neighbors that haven't already been seen } } } }