combination.h

Go to the documentation of this file.
00001 // This source code is licensed under The Code Project Open License (CPOL)
00002 // see http://www.codeproject.com/KB/recipes/CombC.aspx
00003 //=======================================================
00004 // combination.h
00005 // Description : Template class to find combinations
00006 //=======================================================
00007 // Copyright 2003 - 2006 Wong Shao Voon
00008 // No warranty, implied or expressed, is included.
00009 // Author is not liable for any type of loss through
00010 // the use of this source code. Use it at your own risk!
00011 //=======================================================
00012 
00013 
00014 #ifndef __COMBINATION_H__
00015 #define __COMBINATION_H__
00016 
00017 
00018 namespace oversim
00019 {
00020 
00021 // Non recursive template function
00022 template <class BidIt>
00023 
00024 inline bool next_combination(BidIt n_begin, BidIt n_end,
00025 BidIt r_begin, BidIt r_end)
00026 {
00027 
00028   bool boolmarked=false;
00029   BidIt r_marked;
00030 
00031   BidIt n_it1=n_end;
00032   --n_it1;
00033 
00034 
00035   BidIt tmp_r_end=r_end;
00036   --tmp_r_end;
00037 
00038   for(BidIt r_it1=tmp_r_end; r_it1!=r_begin || r_it1==r_begin; --r_it1,--n_it1)
00039   {
00040     if(*r_it1==*n_it1 )
00041     {
00042       if(r_it1!=r_begin) //to ensure not at the start of r sequence
00043       {
00044         boolmarked=true;
00045         r_marked=(--r_it1);
00046         ++r_it1;//add it back again
00047         continue;
00048       }
00049       else // it means it is at the start the sequence, so return false
00050         return false;
00051     }
00052     else //if(*r_it1!=*n_it1 )
00053     {
00054       //marked code
00055       if(boolmarked==true)
00056       {
00057         //for loop to find which marked is in the first sequence
00058         BidIt n_marked;//mark in first sequence
00059         for (BidIt n_it2=n_begin;n_it2!=n_end;++n_it2)
00060           if(*r_marked==*n_it2) {n_marked=n_it2;break;}
00061 
00062 
00063         BidIt n_it3=++n_marked;
00064         for  (BidIt r_it2=r_marked;r_it2!=r_end;++r_it2,++n_it3)
00065         {
00066           *r_it2=*n_it3;
00067         }
00068         return true;
00069       }
00070       for(BidIt n_it4=n_begin; n_it4!=n_end; ++n_it4)
00071         if(*r_it1==*n_it4)
00072         {
00073           *r_it1=*(++n_it4);
00074           return true;
00075         }
00076     }
00077   }
00078 
00079   return true;//will never reach here
00080 }
00081 
00082 // Non recursive template function with Pred
00083 template <class BidIt, class Prediate>
00084 
00085 inline bool next_combination(
00086         BidIt n_begin,
00087         BidIt n_end,
00088         BidIt r_begin,
00089         BidIt r_end,
00090         Prediate Equal)
00091 {
00092 
00093   bool boolmarked=false;
00094   BidIt r_marked;
00095 
00096   BidIt n_it1=n_end;
00097   --n_it1;
00098 
00099 
00100   BidIt tmp_r_end=r_end;
00101   --tmp_r_end;
00102 
00103   for(BidIt r_it1=tmp_r_end; r_it1!=r_begin || r_it1==r_begin; --r_it1,--n_it1)
00104   {
00105     if( Equal( *r_it1, *n_it1) )
00106     {
00107       if(r_it1!=r_begin) //to ensure not at the start of r sequence
00108       {
00109         boolmarked=true;
00110         r_marked=(--r_it1);
00111         ++r_it1;//add it back again
00112         continue;
00113       }
00114       else // it means it is at the start the sequence, so return false
00115         return false;
00116     }
00117     else //if(*r_it1!=*n_it1 )
00118     {
00119       //marked code
00120       if(boolmarked==true)
00121       {
00122         //for loop to find which marked is in the first sequence
00123         BidIt n_marked;//mark in first sequence
00124         for (BidIt n_it2=n_begin;n_it2!=n_end;++n_it2)
00125           if( Equal( *r_marked, *n_it2) ) {n_marked=n_it2;break;}
00126 
00127 
00128         BidIt n_it3=++n_marked;
00129         for  (BidIt r_it2=r_marked;r_it2!=r_end;++r_it2,++n_it3)
00130         {
00131           *r_it2=*n_it3;
00132         }
00133         return true;
00134       }
00135       for(BidIt n_it4=n_begin; n_it4!=n_end; ++n_it4)
00136         if( Equal(*r_it1, *n_it4) )
00137         {
00138           *r_it1=*(++n_it4);
00139           return true;
00140         }
00141     }
00142   }
00143 
00144   return true;//will never reach here
00145 }
00146 
00147 
00148 // Non recursive template function
00149 template <class BidIt>
00150 
00151 inline bool prev_combination(BidIt n_begin, BidIt n_end,
00152 BidIt r_begin, BidIt r_end)
00153 {
00154 
00155   bool boolsame=false;
00156   BidIt marked;//for r
00157   BidIt r_marked;
00158   BidIt n_marked;
00159 
00160 
00161   BidIt tmp_n_end=n_end;
00162   --tmp_n_end;
00163 
00164   BidIt r_it1=r_end;
00165   --r_it1;
00166 
00167   for(BidIt n_it1=tmp_n_end; n_it1!=n_begin || n_it1==n_begin ; --n_it1)
00168   {
00169     if(*r_it1==*n_it1)
00170     {
00171       r_marked=r_it1;
00172       n_marked=n_it1;
00173       break;
00174     }
00175   }
00176 
00177   BidIt n_it2=n_marked;
00178 
00179 
00180   BidIt tmp_r_end=r_end;
00181   --tmp_r_end;
00182 
00183   for(BidIt r_it2=r_marked; r_it2!=r_begin || r_it2==r_begin; --r_it2,--n_it2)
00184   {
00185     if(*r_it2==*n_it2 )
00186     {
00187       if(r_it2==r_begin&& !(*r_it2==*n_begin) )
00188       {
00189         for(BidIt n_it3=n_begin;n_it3!=n_end;++n_it3)
00190         {
00191           if(*r_it2==*n_it3)
00192           {
00193             marked=r_it2;
00194             *r_it2=*(--n_it3);
00195 
00196             BidIt n_it4=n_end;
00197             --n_it4;
00198             for(BidIt r_it3=tmp_r_end; (r_it3!=r_begin || r_it3==r_begin) &&r_it3!=marked; --r_it3,--n_it4)
00199             {
00200               *r_it3=*n_it4;
00201             }
00202             return true;
00203           }
00204         }
00205       }
00206       else if(r_it2==r_begin&&*r_it2==*n_begin)
00207       {
00208         return false;//no more previous combination;
00209       }
00210     }
00211     else //if(*r_it2!=*n_it2 )
00212     {
00213       ++r_it2;
00214       marked=r_it2;
00215       for(BidIt n_it5=n_begin;n_it5!=n_end;++n_it5)
00216       {
00217         if(*r_it2==*n_it5)
00218         {
00219           *r_it2=*(--n_it5);
00220 
00221           BidIt n_it6=n_end;
00222           --n_it6;
00223           for(BidIt r_it4=tmp_r_end; (r_it4!=r_begin || r_it4==r_begin) &&r_it4!=marked; --r_it4,--n_it6)
00224           {
00225             *r_it4=*n_it6;
00226           }
00227           return true;
00228         }
00229       }
00230     }
00231   }
00232   return false;//Will never reach here, unless error
00233 }
00234 
00235 
00236 // Non recursive template function with Pred
00237 template <class BidIt, class Prediate>
00238 
00239 inline bool prev_combination(
00240         BidIt n_begin,
00241         BidIt n_end,
00242         BidIt r_begin,
00243         BidIt r_end,
00244         Prediate Equal)
00245 {
00246 
00247   bool boolsame=false;
00248   BidIt marked;//for r
00249   BidIt r_marked;
00250   BidIt n_marked;
00251 
00252 
00253   BidIt tmp_n_end=n_end;
00254   --tmp_n_end;
00255 
00256   BidIt r_it1=r_end;
00257   --r_it1;
00258 
00259   for(BidIt n_it1=tmp_n_end; n_it1!=n_begin || n_it1==n_begin ; --n_it1)
00260   {
00261     if( Equal(*r_it1, *n_it1) )
00262     {
00263       r_marked=r_it1;
00264       n_marked=n_it1;
00265       break;
00266     }
00267   }
00268 
00269   BidIt n_it2=n_marked;
00270 
00271 
00272   BidIt tmp_r_end=r_end;
00273   --tmp_r_end;
00274 
00275   for(BidIt r_it2=r_marked; r_it2!=r_begin || r_it2==r_begin; --r_it2,--n_it2)
00276   {
00277     if( Equal(*r_it2, *n_it2) )
00278     {
00279       if(r_it2==r_begin&& !Equal(*r_it2, *n_begin) )
00280       {
00281         for(BidIt n_it3=n_begin;n_it3!=n_end;++n_it3)
00282         {
00283           if(Equal(*r_it2, *n_it3))
00284           {
00285             marked=r_it2;
00286             *r_it2=*(--n_it3);
00287 
00288             BidIt n_it4=n_end;
00289             --n_it4;
00290             for(BidIt r_it3=tmp_r_end; (r_it3!=r_begin || r_it3==r_begin) &&r_it3!=marked; --r_it3,--n_it4)
00291             {
00292               *r_it3=*n_it4;
00293             }
00294             return true;
00295           }
00296         }
00297       }
00298       else if(r_it2==r_begin&&Equal(*r_it2, *n_begin))
00299       {
00300         return false;//no more previous combination;
00301       }
00302     }
00303     else //if(*r_it2!=*n_it2 )
00304     {
00305       ++r_it2;
00306       marked=r_it2;
00307       for(BidIt n_it5=n_begin;n_it5!=n_end;++n_it5)
00308       {
00309         if(Equal(*r_it2, *n_it5))
00310         {
00311           *r_it2=*(--n_it5);
00312 
00313           BidIt n_it6=n_end;
00314           --n_it6;
00315           for(BidIt r_it4=tmp_r_end; (r_it4!=r_begin || r_it4==r_begin) &&r_it4!=marked; --r_it4,--n_it6)
00316           {
00317             *r_it4=*n_it6;
00318           }
00319           return true;
00320         }
00321       }
00322     }
00323   }
00324   return false;//Will never reach here, unless error
00325 }
00326 
00327 
00328 // Recursive template function
00329 template <class RanIt, class Func>
00330 
00331 void recursive_combination(RanIt nbegin, RanIt nend, int n_column,
00332                       RanIt rbegin, RanIt rend, int r_column,int loop, Func func)
00333 {
00334 
00335         int r_size=rend-rbegin;
00336 
00337 
00338         int localloop=loop;
00339         int local_n_column=n_column;
00340 
00341         //A different combination is out
00342         if(r_column>(r_size-1))
00343         {
00344     func(rbegin,rend);
00345     return;
00346         }
00348 
00349         for(int i=0;i<=loop;++i)
00350         {
00351 
00352                 RanIt it1=rbegin;
00353                 for(int cnt=0;cnt<r_column;++cnt)
00354                 {
00355                   ++it1;
00356                 }
00357 
00358                 RanIt it2=nbegin;
00359                 for(int cnt2=0;cnt2<n_column+i;++cnt2)
00360                 {
00361                   ++it2;
00362                 }
00363 
00364                 *it1=*it2;
00365 
00366                 ++local_n_column;
00367 
00368                 recursive_combination(nbegin,nend,local_n_column,
00369                         rbegin,rend,r_column+1,localloop,func);
00370                 --localloop;
00371         }
00372 
00373 }
00374 
00375 }
00376 
00377 #endif
Generated on Wed May 26 16:21:14 2010 for OverSim by  doxygen 1.6.3