1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160
|
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <map>
#include <queue>
#include <algorithm>
#include <ctime>
using namespace std;
vector<string> readWords( istream & in )
{
string oneLine;
vector<string> v;
while( in >> oneLine )
v.push_back( oneLine );
return v;
}
// Returns true if word1 and word2 are the same length
// and differ in only one character.
bool oneCharOff( const string & word1, const string & word2 )
{
if( word1.length( ) != word2.length( ) )
return false;
int diffs = 0;
for( int i = 0; i < word1.length( ); ++i )
if( word1[ i ] != word2[ i ] )
if( ++diffs > 1 )
return false;
return diffs == 1;
}
// Computes a map in which the keys are words and values are vectors of words
// that differ in only one character from the corresponding key.
// Uses a quadratic algorithm, but speeds things up a little by
// maintaining an additional map that groups words by their length.
map<string,vector<string>>
computeAdjacentWords( const vector<string> & words )
{
map<string,vector<string>> adjWords;
map<int,vector<string>> wordsByLength;
// Group the words by their length
for( auto & thisWord : words )
wordsByLength[ thisWord.length( ) ].push_back( thisWord );
// Work on eaach group separately
for( auto & entry : wordsByLength )
{
const vector<string> & groupsWords = entry.second;
for( int i = 0; i < groupsWords.size( ); ++i )
for( int j = i + 1; j < groupsWords.size( ); ++j )
if( oneCharOff( groupsWords[ i ], groupsWords[ j ] ) )
{
adjWords[ groupsWords[ i ] ].push_back( groupsWords[ j ] );
adjWords[ groupsWords[ j ] ].push_back( groupsWords[ i ] );
}
}
return adjWords;
}
// Find most changeable word: the word that differs in only one
// character with the most words. Return a list of these words, in case of a tie.
vector<string>
findMostChangeable( const map<string,vector<string>> & adjacentWords )
{
vector<string> mostChangeableWords;
int maxNumberOfAdjacentWords = 0;
for( auto & entry : adjacentWords )
{
const vector<string> & wordList = entry.second;
if( wordList.size( ) > maxNumberOfAdjacentWords )
{
maxNumberOfAdjacentWords = wordList.size( );
mostChangeableWords.clear( );
}
if( wordList.size( ) == maxNumberOfAdjacentWords )
mostChangeableWords.push_back( entry.first );
}
return mostChangeableWords;
}
void printMostChangeables( const vector<string> & mostChangeable,
const map<string,vector<string>> & adjWords )
{
auto & adjacentWords = const_cast<map<string,vector<string>> &>( adjWords );
for( auto & thisWord : mostChangeable )
{
cout << thisWord << ":";
vector<string> & adjacents = adjacentWords[ thisWord ];
for( string & str : adjacents )
cout << " " << str;
cout << " (" << adjacents.size( ) << " words)" << endl;
}
}
void printHighChangeables( const map<string,vector<string>> & adjacentWords,
int minWords = 15 )
{
for( auto & entry : adjacentWords )
{
const vector<string> & words = entry.second;
if( words.size( ) >= minWords )
{
cout << entry.first << " (" << words.size( ) << "):";
for( auto & str : words )
cout << " " << str;
cout << endl;
}
}
}
int main( )
{
clock_t start, end;
ifstream fin( "words.txt" );
vector<string> words = readWords( fin );
cout << "Read the words..." << words.size( ) << endl;
map<string,vector<string> > adjacentWords;
start = clock( );
adjacentWords = computeAdjacentWords( words );
end = clock( );
cout << "Elapsed time FAST: " << double(end-start)/CLOCKS_PER_SEC << endl;
cout << "Adjacents computed.." << endl;
vector<string> mostChangeable = findMostChangeable( adjacentWords );
cout << "Most changeable computed..." << endl;
printMostChangeables( mostChangeable, adjacentWords );
return 0;
}
|