00001
00002
00003
00004
00005
00006
00007
00008
00009 #ifndef SG_SORTEDMOVES_H
00010 #define SG_SORTEDMOVES_H
00011
00012 #include <iostream>
00013 #include "SgRandom.h"
00014 #include "SgVector.h"
00015
00016
00017
00018
00019 template<typename MOVE, typename VALUE, int SIZE>
00020 class SgSortedMoves
00021 {
00022 public:
00023
00024 static const bool CHECKMOVES = SG_CHECK;
00025
00026 explicit SgSortedMoves(int maxNuMoves);
00027
00028
00029 void CheckOverflow() {m_checkOverflow = true;}
00030
00031
00032 void Clear();
00033
00034
00035 void DeleteEqual();
00036
00037
00038
00039 void Delete(int index);
00040
00041
00042
00043 void Insert(const MOVE& move, VALUE value);
00044
00045
00046 bool GetMove(const MOVE& move, VALUE &value, int &index) const;
00047
00048
00049 void GetMoves(SgVector<MOVE>* moves) const;
00050
00051
00052 void SetMinValue(const MOVE& move, VALUE value);
00053
00054
00055 void SetMove(int i, const MOVE& move)
00056 {
00057 AssertIndexRange(i);
00058 m_move[i] = move;
00059 }
00060
00061
00062 void SetValue(int i, VALUE value)
00063 {
00064 AssertIndexRange(i);
00065 m_value[i] = value;
00066 }
00067
00068
00069
00070 void SetMaxMoves(int nu);
00071
00072
00073 void SetMaxNuMoves(int max);
00074
00075
00076 void SetLowerBound(VALUE bound) {m_lowerBound = bound;};
00077
00078
00079 void SetInitLowerBound(VALUE bound) {m_initLowerBound = bound;};
00080
00081
00082 int LowerBound() const {return m_lowerBound;}
00083
00084
00085 int NuMoves() const {return m_nuMoves;}
00086
00087
00088 int MaxNuMoves() const {return m_maxNuMoves;}
00089
00090
00091 const MOVE& Move(int i) const {AssertIndexRange(i); return m_move[i];}
00092
00093
00094 const MOVE& BestMove() const {return Move(0);}
00095
00096
00097 VALUE Value(int i) const {AssertIndexRange(i); return m_value[i];}
00098
00099
00100 VALUE BestValue() const
00101 {
00102 SG_ASSERT(m_nuMoves > 0);
00103 return m_value[0];
00104 }
00105
00106
00107 void DecNuMoves()
00108 {
00109 SG_ASSERT(m_nuMoves > 0);
00110 --m_nuMoves;
00111 }
00112
00113
00114 void AssertIndexRange(int i) const
00115 {
00116 SG_DEBUG_ONLY(i);
00117 SG_ASSERTRANGE(i, 0, m_nuMoves - 1);
00118 }
00119
00120
00121 void Shuffle();
00122
00123 private:
00124
00125 int m_maxNuMoves;
00126
00127
00128 int m_nuMoves;
00129
00130
00131 VALUE m_lowerBound;
00132
00133
00134 VALUE m_initLowerBound;
00135
00136
00137 bool m_checkOverflow;
00138
00139
00140 bool m_considerEqual;
00141
00142
00143 MOVE m_move[SIZE];
00144
00145
00146 VALUE m_value[SIZE];
00147
00148
00149 void CheckMoves() const;
00150
00151
00152 void ShuffleInterval(int from, int to);
00153 };
00154
00155 template<typename MOVE, typename VALUE, int SIZE>
00156 SgSortedMoves<MOVE, VALUE, SIZE>::SgSortedMoves(int maxNuMoves)
00157 : m_maxNuMoves(maxNuMoves),
00158 m_checkOverflow(false),
00159 m_considerEqual(true)
00160 {
00161 SG_ASSERT(maxNuMoves <= SIZE);
00162 Clear();
00163 }
00164
00165 template<typename MOVE, typename VALUE, int SIZE>
00166 void SgSortedMoves<MOVE, VALUE, SIZE>::Clear()
00167 {
00168 m_initLowerBound = INT_MIN;
00169 SG_ASSERT(m_maxNuMoves >= 1);
00170 m_lowerBound = m_initLowerBound;
00171 m_nuMoves = 0;
00172 }
00173
00174 template<typename MOVE, typename VALUE, int SIZE>
00175 void SgSortedMoves<MOVE, VALUE, SIZE>::Delete(int index)
00176 {
00177 if (CHECKMOVES)
00178 CheckMoves();
00179 SG_ASSERT(index < m_nuMoves);
00180
00181 --m_nuMoves;
00182 for (int k = index; k <= m_nuMoves - 1; ++k)
00183 {
00184 m_move[k] = m_move[k + 1];
00185 m_value[k] = m_value[k + 1];
00186 }
00187
00188 if (m_nuMoves >= m_maxNuMoves)
00189 m_lowerBound = m_value[m_maxNuMoves - 1];
00190 else
00191 m_lowerBound = m_initLowerBound;
00192
00193 if (CHECKMOVES)
00194 CheckMoves();
00195 }
00196
00197 template<typename MOVE, typename VALUE, int SIZE>
00198 void SgSortedMoves<MOVE, VALUE, SIZE>::DeleteEqual()
00199 {
00200 for (int j = m_nuMoves - 2; j >= 0; --j)
00201 {
00202 for (int i = m_nuMoves - 1; i >= j + 1; --i)
00203 {
00204 if (m_value[i] == m_value[j])
00205 {
00206 Delete(SgRandom::Global().Int(2) ? j : i);
00207 return;
00208 }
00209 }
00210 }
00211
00212 SG_ASSERT(false);
00213 }
00214
00215 template<typename MOVE, typename VALUE, int SIZE>
00216 void SgSortedMoves<MOVE, VALUE, SIZE>::CheckMoves() const
00217 {
00218 SG_ASSERT(m_maxNuMoves <= SIZE);
00219 SG_ASSERT(m_nuMoves <= SIZE);
00220
00221 for (int i = 0; i < m_nuMoves - 1; ++i)
00222 SG_ASSERT(m_value[i] >= m_value[i + 1]);
00223 for (int i = m_maxNuMoves; i < m_nuMoves; ++i)
00224 SG_ASSERT(m_value[i] == m_value[m_maxNuMoves - 1]);
00225
00226 SG_ASSERT((m_nuMoves == 0) || (m_value[m_nuMoves - 1] >= m_lowerBound));
00227 }
00228
00229 template<typename MOVE, typename VALUE, int SIZE>
00230 void SgSortedMoves<MOVE, VALUE, SIZE>::Insert(const MOVE& m, VALUE val)
00231 {
00232 if (CHECKMOVES)
00233 CheckMoves();
00234
00235 if (val < m_lowerBound)
00236 return;
00237
00238 int i = 0;
00239 while (i < m_nuMoves && m_value[i] > val)
00240 ++i;
00241 int maxMoves = m_nuMoves;
00242 if (maxMoves >= SIZE)
00243 {
00244 if (m_checkOverflow)
00245 {
00246 SG_ASSERT(false);
00247 }
00248 maxMoves = SIZE - 1;
00249 }
00250 else
00251 ++m_nuMoves;
00252
00253 for (int j = maxMoves; j >= i + 1; --j)
00254 {
00255 m_move[j] = m_move[j - 1];
00256 m_value[j] = m_value[j - 1];
00257 }
00258
00259 m_move[i] = m;
00260 m_value[i] = val;
00261
00262
00263
00264 if (m_nuMoves >= m_maxNuMoves)
00265 m_lowerBound = std::max(m_lowerBound, m_value[m_maxNuMoves - 1]);
00266
00267 if (m_nuMoves > m_maxNuMoves)
00268
00269 while ( m_value[m_nuMoves - 1] < m_lowerBound
00270 || ( m_nuMoves > m_maxNuMoves
00271 && ! m_considerEqual
00272 && m_value[m_nuMoves - 1] == m_lowerBound
00273 )
00274 )
00275 --m_nuMoves;
00276
00277 if (CHECKMOVES)
00278 CheckMoves();
00279 }
00280
00281 template<typename MOVE, typename VALUE, int SIZE>
00282 bool SgSortedMoves<MOVE, VALUE, SIZE>::GetMove(const MOVE& move,
00283 VALUE &value, int &index) const
00284 {
00285 for (int i = 0; i <= m_nuMoves - 1 ; ++i)
00286 if (m_move[i] == move)
00287 {
00288 value = m_value[i];
00289 index = i;
00290 return true;
00291 }
00292 return false;
00293 }
00294
00295 template<typename MOVE, typename VALUE, int SIZE>
00296 void SgSortedMoves<MOVE, VALUE, SIZE>::ShuffleInterval(int from, int to)
00297 {
00298 AssertIndexRange(from);
00299 AssertIndexRange(to);
00300 SG_ASSERT(m_value[from] == m_value[to]);
00301
00302 for (; to > from; --to)
00303 {
00304 int i = from + SgRandom::Global().Int(to - from + 1);
00305 SG_ASSERT(m_value[i] == m_value[to]);
00306 MOVE t = m_move[i];
00307 m_move[i] = m_move[to];
00308 m_move[to] = t;
00309 }
00310 }
00311
00312 template<typename MOVE, typename VALUE, int SIZE>
00313 void SgSortedMoves<MOVE, VALUE, SIZE>::Shuffle()
00314 {
00315 for (int i = 0; i < m_nuMoves; ++i)
00316 {
00317 int val = m_value[i];
00318 int j;
00319 for (j = i + 1; j < m_nuMoves && (val == m_value[j]); ++j)
00320 { }
00321 if (j > i + 1)
00322 ShuffleInterval(i, j - 1);
00323 }
00324 }
00325
00326 template<typename MOVE, typename VALUE, int SIZE>
00327 void SgSortedMoves<MOVE, VALUE, SIZE>::GetMoves(SgVector<MOVE>* moves) const
00328 {
00329 for (int i = 0; i < m_nuMoves; ++i)
00330 moves->PushBack(m_move[i]);
00331 }
00332
00333 template<typename MOVE, typename VALUE, int SIZE>
00334 void SgSortedMoves<MOVE, VALUE, SIZE>::SetMinValue(const MOVE& move,
00335 VALUE val)
00336 {
00337 VALUE oldValue;
00338 int index;
00339 bool insert = true;
00340
00341 if (GetMove(move, oldValue, index))
00342 {
00343 if (val > oldValue)
00344 Delete(index);
00345 else
00346 insert = false;
00347 }
00348 if (insert)
00349 Insert(move, val);
00350 }
00351
00352 template<typename MOVE, typename VALUE, int SIZE>
00353 void SgSortedMoves<MOVE, VALUE, SIZE>::SetMaxNuMoves(int max)
00354 {
00355 SG_ASSERT(max >= 1);
00356 SG_ASSERT(max <= SIZE);
00357 m_maxNuMoves = max;
00358 }
00359
00360 template<typename MOVE, typename VALUE, int SIZE>
00361 void SgSortedMoves<MOVE, VALUE, SIZE>::SetMaxMoves(int nu)
00362 {
00363 SetMaxNuMoves(nu);
00364
00365 if ( m_nuMoves >= m_maxNuMoves
00366 && m_value[m_maxNuMoves - 1] > m_lowerBound
00367 )
00368 m_lowerBound = m_value[m_maxNuMoves - 1];
00369 if (m_nuMoves > m_maxNuMoves)
00370 {
00371
00372 while ( m_value[m_nuMoves - 1] < m_lowerBound
00373 || ( m_nuMoves > m_maxNuMoves
00374 && ! m_considerEqual
00375 && m_value[m_nuMoves - 1] == m_lowerBound
00376 )
00377 )
00378 --m_nuMoves;
00379 }
00380 }
00381
00382
00383
00384
00385 template<typename MOVE, typename VALUE, int SIZE>
00386 std::ostream& operator<<(std::ostream& str,
00387 const SgSortedMoves<MOVE, VALUE, SIZE>& m)
00388 {
00389 if (m.NuMoves() == 0)
00390 str << "none\n";
00391 else
00392 {
00393 str << m.NuMoves() << " (Moves, Values): ";
00394 for (int i = 0; i < m.NuMoves(); ++i)
00395 {
00396 str << '('
00397 << m.Move(i) << ", "
00398 << m.Value(i)
00399 << ')';
00400 }
00401 str << '\n';
00402 }
00403 return str;
00404 }
00405
00406
00407
00408 #endif // SG_SORTEDMOVES_H