Created
December 4, 2020 22:11
-
-
Save pingpoli/5741b95426088c0b714ea29aaea32de7 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <iostream> | |
#include "../../SRC/lstd/filesystemutil.hpp" | |
#include "../../SRC/lstd/Timer.hpp" | |
class Node | |
{ | |
public: | |
Node* parent; | |
std::string value; | |
std::vector< Node* > children; | |
Node( Node* parent , const std::string& value ) : parent(parent) , value(value) {} | |
~Node() | |
{ | |
for ( uint i = 0 ; i < this->children.size() ; ++i ) delete this->children[i]; | |
} | |
}; | |
void expand( const std::vector< std::string >& words , Node* node , int depth ) | |
{ | |
if ( depth == 0 ) return; | |
std::string startingWord = node->value; | |
// find all words that only differ in one letter | |
for ( uint i = 0 ; i < words.size() ; ++i ) | |
{ | |
int dif = 0; | |
for ( uint j = 0 ; j < startingWord.length() ; ++j ) | |
{ | |
if ( words[i][j] != startingWord[j] ) | |
{ | |
++dif; | |
if ( dif >= 2 ) break; | |
} | |
} | |
if ( dif == 1 ) | |
{ | |
// only add if not in list already | |
bool inList = false; | |
for ( uint j = 0 ; j < node->children.size() ; ++j ) | |
{ | |
if ( words[i] == node->children[j]->value ) | |
{ | |
inList = true; | |
break; | |
} | |
} | |
if ( !inList ) node->children.push_back( new Node( node , words[i] ) ); | |
} | |
} | |
// expand children | |
for ( uint i = 0 ; i < node->children.size() ; ++i ) | |
{ | |
expand( words , node->children[i] , depth-1 ); | |
} | |
} | |
void search( std::vector< std::vector< std::string > >& solutions , Node* node , const std::string& str ) | |
{ | |
if ( str == node->value ) | |
{ | |
Node* counter = node; | |
std::vector< std::string > solution; | |
while ( counter->parent != nullptr ) | |
{ | |
solution.push_back( counter->value ); | |
counter = counter->parent; | |
} | |
solution.push_back( counter->value ); | |
solutions.push_back( solution ); | |
return; | |
} | |
for ( uint i = 0 ; i < node->children.size() ; ++i ) | |
{ | |
search( solutions , node->children[i] , str ); | |
} | |
} | |
int main() | |
{ | |
std::string filename = "PATH/TO/DICTIONARY_FILENAME"; | |
std::string startingWord = "Kerzen"; | |
std::string endingWord = "Vetter"; | |
int depth = 6; | |
bool removeNames = false; | |
std::vector< std::string > lines; | |
if ( readFile( lines , filename ) ) | |
{ | |
// find all six letter words | |
std::vector< std::string > sixLetterWords; | |
for ( uint i = 1 ; i < lines.size() ; ++i ) | |
{ | |
if ( !startsWith( lines[i] , "#" ) ) | |
{ | |
std::vector< std::string > parts; | |
split( parts , lines[i] , '/' ); | |
if ( parts.size() == 2 ) | |
{ | |
if ( parts[0].length() == startingWord.length() ) | |
{ | |
if ( removeNames ) | |
{ | |
// names have only an S in the second part, so don't add them | |
if ( parts[1] != "S" ) | |
{ | |
sixLetterWords.push_back( parts[0] ); | |
} | |
} | |
else sixLetterWords.push_back( parts[0] ); | |
} | |
} | |
} | |
} | |
std::cout << sixLetterWords.size() << " six letter words found" << std::endl; | |
// yeet the umlauts | |
std::vector< std::string > cleanWords; | |
for ( uint i = 0 ; i < sixLetterWords.size() ; ++i ) | |
{ | |
bool clean = true; | |
for ( uint j = 0 ; j < startingWord.length() ; ++j ) | |
{ | |
if ( sixLetterWords[i][j] < 65 || sixLetterWords[i][j] > 122 ) | |
{ | |
clean = false; | |
break; | |
} | |
} | |
if ( clean ) cleanWords.push_back( sixLetterWords[i] ); | |
} | |
std::cout << cleanWords.size() << " clean words found" << std::endl << std::endl; | |
Node* root = new Node( nullptr , startingWord ); | |
Timer timer; | |
timer.start(); | |
expand( cleanWords , root , depth ); | |
std::vector< std::vector< std::string > > solutions; | |
search( solutions , root , endingWord ); | |
timer.stop(); | |
std::cout << "There are " << solutions.size() << " solutions:" << std::endl << std::endl; | |
for ( uint i = 0 ; i < solutions.size() ; ++i ) | |
{ | |
std::cout << i << ": "; | |
for ( int j = (int)solutions[i].size()-1 ; j >= 0 ; --j ) | |
{ | |
std::cout << solutions[i][j]; | |
if ( j != 0 ) std::cout << " > "; | |
} | |
std::cout << std::endl << std::endl; | |
} | |
std::cout << "Time: " << timer.getTime() << "ms" << std::endl; | |
delete root; | |
} | |
else std::cout << "failed to open file" << std::endl; | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment