00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include <cstdlib>
00027 #include <cstring>
00028 #include <iostream>
00029 #include <mpcl/test.h>
00030 #include <vector>
00031
00032
00033 #define MAX_QUEENS (8)
00034 #define MAX_ROWS (8)
00035 #define MAX_COLUMNS (8)
00036
00037
00038 class TQueen
00039 {
00040
00041 public:
00042
00043 int iX;
00044 int iY;
00045
00046
00047 public:
00048
00049 TQueen (void) :
00050 iX (0) ,
00051 iY (0) {}
00052
00053 bool isKillingTo (const TQueen& rktSOURCE_QUEEN) const;
00054 bool operator == (const TQueen& rktSOURCE_QUEEN) const;
00055
00056
00057
00058
00059 friend std::basic_ostream<char>& operator << (std::basic_ostream<char>& rtOUTPUT_OSTREAM, const TQueen& rktSOURCE_QUEEN);
00060
00061 };
00062
00063 typedef std::vector<TQueen> TArrayQueen;
00064 typedef std::vector<TArrayQueen> TArrayArrayQueen;
00065
00066
00067 class TRecursiveApproachAlgorithm
00068 {
00069
00070 public:
00071
00072 TArrayArrayQueen* ptSolutionsArray;
00073
00074
00075 public:
00076
00077 void execute (TArrayArrayQueen& rtSOLUTIONS_ARRAY);
00078
00079
00080 private:
00081
00082 bool areKillingEachOther ( const TQueen& rktQUEEN ,
00083 const TArrayQueen& rktSOURCE_QUEEN_ARRAY ) const;
00084 bool tryFor (int iROW, TArrayQueen& rtQUEEN_ARRAY);
00085
00086 };
00087
00088
00089 bool TQueen::isKillingTo (const TQueen& rktSOURCE_QUEEN) const
00090 {
00091
00092 return ( ( abs (iX - rktSOURCE_QUEEN.iX) == abs (iY - rktSOURCE_QUEEN.iY) ) ||
00093 ( iX == rktSOURCE_QUEEN.iX ) ||
00094 ( iY == rktSOURCE_QUEEN.iY ) );
00095
00096 }
00097
00098
00099 bool TQueen::operator == (const TQueen& rktSOURCE_QUEEN) const
00100 {
00101
00102 return ( ( iX == rktSOURCE_QUEEN.iX ) && ( iY == rktSOURCE_QUEEN.iY ) );
00103
00104 }
00105
00106
00107 std::basic_ostream<char>& operator << (std::basic_ostream<char>& rtOUTPUT_OSTREAM, const TQueen& rktSOURCE_QUEEN)
00108 {
00109
00110 rtOUTPUT_OSTREAM << rktSOURCE_QUEEN.iX;
00111 rtOUTPUT_OSTREAM << ",";
00112 rtOUTPUT_OSTREAM << rktSOURCE_QUEEN.iY;
00113 return rtOUTPUT_OSTREAM;
00114
00115 }
00116
00117
00118 void TRecursiveApproachAlgorithm::execute (TArrayArrayQueen& rtSOLUTIONS_ARRAY)
00119 {
00120
00121 TArrayQueen tTemporalQueenArray;
00122
00123
00124
00125
00126
00127
00128 ptSolutionsArray = &rtSOLUTIONS_ARRAY;
00129
00130 tryFor (0, tTemporalQueenArray);
00131
00132 }
00133
00134
00135 bool TRecursiveApproachAlgorithm::areKillingEachOther ( const TQueen& rktQUEEN ,
00136 const TArrayQueen& rktQUEEN_ARRAY ) const
00137 {
00138
00139 bool gKills = false;
00140
00141 for (size_t J = 0; ( J < rktQUEEN_ARRAY.size() ) ;++J)
00142 {
00143 if ( rktQUEEN_ARRAY [J].isKillingTo (rktQUEEN) )
00144 {
00145 gKills = true;
00146 break;
00147 }
00148 }
00149 return gKills;
00150
00151 }
00152
00153
00154 bool TRecursiveApproachAlgorithm::tryFor (int iROW, TArrayQueen& rtQUEEN_ARRAY)
00155 {
00156
00157 bool gSuccess = true;
00158
00159 if ( ( rtQUEEN_ARRAY.size() < MAX_QUEENS ) && ( iROW < MAX_ROWS ) )
00160 {
00161
00162 TQueen tNewQueen;
00163
00164 gSuccess = false;
00165 tNewQueen.iY = iROW;
00166 for (size_t J = 0; ( J < MAX_COLUMNS ) ;++J)
00167 {
00168 tNewQueen.iX = J;
00169 if ( !areKillingEachOther (tNewQueen, rtQUEEN_ARRAY) )
00170 {
00171 rtQUEEN_ARRAY.push_back (tNewQueen);
00172 if ( tryFor (iROW + 1, rtQUEEN_ARRAY) )
00173 {
00174 gSuccess |= true;
00175 if ( rtQUEEN_ARRAY.size() == MAX_QUEENS )
00176 {
00177 ptSolutionsArray->push_back (rtQUEEN_ARRAY);
00178 }
00179 }
00180
00181
00182
00183 rtQUEEN_ARRAY.erase (rtQUEEN_ARRAY.end() - 1);
00184 }
00185 }
00186 }
00187 return gSuccess;
00188
00189 }
00190
00191
00192
00193
00194
00195
00196 static void _DisplaySolutionsGraphicly (const TArrayArrayQueen& rktSOLUTIONS_ARRAY)
00197 {
00198
00199 using std::cout;
00200 using std::endl;
00201
00202
00203
00204
00205
00206 for (size_t J = 0; ( J < rktSOLUTIONS_ARRAY.size() ) ;++J)
00207 {
00208 cout << "Queens Solution [" << J << "]" << endl;
00209 cout << "+---+---+---+---+---+---+---+---+" << endl;
00210 for (long int K = rktSOLUTIONS_ARRAY[J].size() - 1; ( K >= 0 ) ;K--)
00211 {
00212 for (int L = 0; ( L < rktSOLUTIONS_ARRAY [J][K].iX ) ;++L)
00213 {
00214 cout << "| ";
00215 }
00216 cout << "| Q ";
00217 for (size_t M = rktSOLUTIONS_ARRAY [J][K].iX + 1; ( M < MAX_COLUMNS ) ;++M)
00218 {
00219 cout << "| ";
00220 }
00221 cout << "|" << endl;
00222 cout << "+---+---+---+---+---+---+---+---+" << endl;
00223 }
00224 }
00225
00226 }
00227
00228
00230 int main (int argc, char** argv)
00231 {
00232
00233 using std::strcmp;
00234
00235 TEST_INIT ("tests for TBaseAlgorithm (implements eight queens solution)");
00236
00237 TArrayArrayQueen tSolutionsArray;
00238 TRecursiveApproachAlgorithm tRecursiveApproachAlgorithm;
00239
00240 if ( argc > 1 )
00241 {
00242 if ( !strcmp (argv[1], "-g") || !strcmp (argv[1], "--graphic") )
00243 {
00244 _DisplaySolutionsGraphicly (tSolutionsArray);
00245 }
00246 else
00247 {
00248 TEST_WRITE_INFO ("%s", "eight_queens: unrecognized option(s)");
00249 TEST_WRITE_INFO ("%s", "Usage: eight_queens [{-g|--graphic}]");
00250 TEST_FAIL;
00251 }
00252 }
00253 else
00254 {
00255 tRecursiveApproachAlgorithm.execute (tSolutionsArray);
00256 TEST_NUMBERS (92, tSolutionsArray.size());
00257 if ( !TEST_IN_SILENT_MODE )
00258 {
00259 for (size_t J = 0; ( J < tSolutionsArray.size() ) ;++J)
00260 {
00261 for (size_t K = 0; ( K < tSolutionsArray[J].size() ) ;++K)
00262 {
00263 fprintf ( hptTestTargetFile ,
00264 "#Queen [%d][%d]: %d, %d\n" ,
00265 J ,
00266 K ,
00267 tSolutionsArray [J][K].iX ,
00268 tSolutionsArray [J][K].iY );
00269 }
00270 }
00271 }
00272 }
00273
00274 TEST_MEMORY_STATUS;
00275 TEST_RETURN_CODE;
00276
00277 }