SEclone  URs ULs  main process

UR’s main process

 

Having the common process to URs L’s, there is not that much to show on UR’s.

 

The process start in the main table of cells and continue in the class CRIN.

 

Only sets of 4 cells having 2 and only 2 common digits are considered.

I am not quite sure this meet SE specifications, but it works with the test file.

 

In that aprt of the code, only rating 4.5 is active. Other potential URs are stored;

All the code is located in the file "c\_05b_  RI_2N.cpp"

 

 

int TP81::RIN(int aig)       // look for unique rectangle

{int ir=0; y$t.Init();

 for(int i0=0;i0<3;i0++) // band/stack 1 to 3

 for(int i1=0;i1<2;i1++)for(int i2=i1+1;i2<3;i2++) // 2 rows 

 for(int j1=0;j1<2;j1++)for(int j2=j1+1;j2<3;j2++) // boxes   12 13 23

  for(int j3=0;j3<3;j3++)for(int j4=0;j4<3;j4++)  // 2 cols 

   //analysing band and stack, main diagonal symmetry

   {int l1=3*i0+i1,l2=3* i0+i2,c1=3*j1+j3,c2=3*j2+j4;

    if (y$.RID(l1,l2,c1,c2)||y$.RID(c1,c2,l1,l2)) ir++;  }

return ir;}

 

// one possible location for a UR;

// no assigned position, 2 and only 2 common digits

 

int CRIN::RID(int i1,int i2,int c1,int c2)

{ia=i$.Pos(i1,c1);ib=i$.Pos(i1,c2);ic=i$.Pos(i2,c1);id=i$.Pos(i2,c2);

 char * gr=jdk.gg.pg;

 if( (gr[ia]-'0') ||(gr[ib]-'0') ||(gr[ic]-'0') ||(gr[id]-'0') ) return 0;

 if(Setw()-2) return 0;   CalcDeux();  

 if(ndeux==3)  {ta[pp1].Change(wc);   ImageRI("1");  return 1;}// type 1

 if((ndeux-2)|| IsDiag()) return 0; // not processed

 

 Setwou();  GenCh();

 // if one digit active, do it now 4.5

 if(nautres==1)  // un chiffre en lig/col  ou diagonal

     if(jdk.Keep (ch1,pp1,pp2))  {ImageRI(" one digit active"); return 1; }

   // if one of the common digit is a bivalue, do it as well it is 4.5

 while((tr[ia].v.ncand>2) ||  (tr[ic].v.ncand>2 ))

    {USHORT pw=ia; ia=ib; ib=id;id=ic;ic=pw;}// sort cells

 int ir= T2(1) ; // we  want only rating 4.5 as "good" so far

 if(ir==1) {ImageRI(" action from object");return 1;} // it was ok

 if(ir)  y$t.Store(this);

 return 0; //store if something else seen 

  }

 

UL’s main process

 

The process for UL’s start in the table of dual cells .

A recursive search is then launched using a specific class UL_SEARCH.

At the end, either an immediate result comes or the UL dat are stored for later processing;

 

Specific classes  are located in "h\_04d_  paires.h"

The process is in the file  "c\_04d_  paires.cpp"

 

 

class UL_SEARCH

{public:

 TPAIRES * tpa;          // calling TPAIRES

 PAIRES * pa;            // subtable in TPAIRES::zpt for processed bivalue

 USHORT npa;             // size of pa for that bivalue

 BIT32 el_used,parity;   // to chexk Used sets

 ZINFL cells;            // to check used cells

 CB9CH chd,cht;          // starting pair ; total digits included

 USHORT nadds,adds[8],   // cells with more digits

           tcount[40],      // storing the list or cells forming the loop

           c1,c2,           // the 2 digits

        elcpt[27],       // count per elem

              last,            // last cell number

        line_count;      // must end with more than 4 to have a valid UL (not a UR)

 P81F  p;            // last cell row col box

 UL_SEARCH (){}      // empty constructor for the storing table below

 UL_SEARCH (UL_SEARCH * old) {(*this) = (*old);}

 UL_SEARCH ( CB9CH c,TPAIRES * tpae,PAIRES * pae,USHORT npae )

        // initial for a new start

     {tpa=tpae;pa=pae;npa=npae;

         chd=cht=c; nadds=line_count=0;

         char * st=c.String(); c1=st[0]-'1';c2=st[1]-'1';

      cells.Init();el_used.f=parity.f=0;

      for(int i=0;i<27;i++) elcpt[i]=0;

     }

 void Copie (UL_SEARCH *x) {(*this)=(*x);}

 void Set(int i8);  //a new cell is added to the search

 int Add_Chain (int i8);

 int Loop_OK(int action=0);

 int Valid_Set(P81F f,char c)

    {int el=f.el;if(c=='c') el=f.pl+9; else if(c=='b')el=f.eb+18;

     if(el_used.Off(el)) return el;

     return -1;}

 int Is_OK_Suite(USHORT i8) ;

 int El_Suite(USHORT el);

 void UL_Mess(char * lib,int pr);

};

 

 

// ULT is a table storing possible UL rating more than 4.6 for further processing

class ULT 

{public:

UL_SEARCH ult[20]; 

int n;

void Init() {n=0;}

void Store(UL_SEARCH *x) {if(n<20) ult[n++].Copie(x);}

 // the processing is lenght dependant

int Traite(int rat)

       {// up to 6 cells basis=4.6 (+0.1)  7_8 cells 4.7 (+0.2)  10_.. 4.8 (+0.3)

        //E$.E("recherche UL rating =");E$.E(rat);E$.E(" n=");E$.Enl(n);

      for(int i=0;i<n;i++)

         {    int len=ult[i].line_count,irat,rbase=46;        

           if(len>7) rbase++; if(len>9) rbase++;

           if(len>7) rbase++; if(len>9) rbase++;// seems to be doubled ??

              // now the relative difficulty for loop_ok nand UR common processing

              irat=rat-rbase+1;if(irat <1 || irat>4 )continue;        

              if(ult[i].Loop_OK(irat))return 1;

         }

        return 0;}

}tult;

 

 

 

//====================================

int TPAIRES::UL()

{int ir=0;tult.Init();

 for(int i=0;i<np;i++)

   {USHORT id=izpd[i],ie=izpd[i+1];

  // E$.Enl("un depart paire");

       UL_SEARCH uls(tp[i],this,&zpt[id],ie-id); //build search

    for(int j=id;j<ie-1;j++) for(int k=j+1;k<ie;k++)

         {USHORT i1=zpt[j].i8,i2=zpt[k].i8;

          P81F p1=t81f[i1],p2=t81f[i2];

          if(!(p1.el==p2.el || p1.pl==p2.pl) )continue; // start row or col

   //  E$.E(p1.pt); E$.E(p2.pt);E$.Enl("un depart lig/col");

       UL_SEARCH ulsn(&uls); ulsn.Set(i1);

          if(p1.el==p2.el) ulsn.el_used.Set(p1.el); 

          else ulsn.el_used.Set(p1.pl+9);

       ir+=ulsn.Add_Chain(i2);  // looking for all equivalent moves

       }// end jk

    }// end i

return ir;}

 

//========================= insert a new cell after el_used correct

void UL_SEARCH::Set(int i8) // el_used already ok if necessary

{cells.Set(i8); 

 P81F p=t81f[i8];last=i8;

 UNP pv=T81tc[i8].v;

 parity.Inv(p.el);parity.Inv(p.pl+9);parity.Inv(p.eb+18);                  

 elcpt[p.el]++;elcpt[p.pl+9]++;elcpt[p.eb+18]++;

 cht|=pv.cand; int nc=pv.cand.QC();

 if(nc>2) adds[nadds++]=i8;

// E$.E("UL lc=");E$.E(line_count);E$.Esp();E$.Enl(p.pt);

 tcount[line_count++]=i8;

}

 

//============================= recurrent process to add next point

int UL_SEARCH::Add_Chain(int i8)

{if(line_count>20) return 0; // securite

 if(cells.On(i8)) // terminé on élimine URs et fausses boucles

   {//E$.E("UL end ");E$.E(t81f[i8].pt);E$.Esp();cells.ImagePoints();E$.Enl();

       if (line_count<5 || (i8-tcount[0])) return 0; 

    tcount[line_count++]=i8;return Loop_OK();}

Set(i8);              // On met le point en place

P81F f=t81f[i8];

 

// a défaut une case avec additifs  ligne, puis col, puis bloc en paire

// uniquement dans éléments non traités et si pas de double paire

// not more than 3 adds except one digit

if(nadds>7 ||(cht.QC()>3 && nadds>2)) return 0;

if(El_Suite(f.el) ) return 1;

if(El_Suite(f.pl+9) ) return 1;

if(El_Suite(f.eb+18) ) return 1;

return 0;}

 

 

//====================================

int UL_SEARCH::El_Suite(USHORT ele)

{if(el_used.On(ele)) return 0;

 //E$.E("suite el=");E$.Enl(ele+1);

 CB9CH wc=aztob.tchbit.el[ele].eld[c1].b

        & aztob.tchbit.el[ele].eld[c2].b ;

 for(int i=0;i<9;i++) if (wc.On(i))// cells with both digits

       {int i8r=divf.el81[ele][i];

     //E$.E("essai i8=");E$.Enl(t81f[i8r].pt);

     if(ele>17) // in a box, only not row col

            {P81F f=t81f[i8r],f2=t81f[last];

             if(f.el==f2.el || f.pl==f2.pl) continue;

            }

     if(! Is_OK_Suite(i8r)) continue;

        UL_SEARCH ulsn(this); ulsn.el_used.Set(ele);

     if(ulsn.Add_Chain(i8r)) return 1;

       }// end for

 return 0; }

 

//=================================================

int UL_SEARCH::Is_OK_Suite(USHORT i8)

{if(i8==last)return 0; if(i8==tcount[0]) return 1;

 if(cells.On(i8)) return 0; // false loop 

 P81F f=t81f[i8];

 if(elcpt[f.el]>1 ||  elcpt[f.pl+9]>1 ||  elcpt[f.eb+18]>1) return 0;

 // for the time being, I see no more exclusion

 return 1;}

//  entry action 0 is the start 4.6.  store after

//       one digit in excess and

 

//==================================================

int UL_SEARCH::Loop_OK(int action)

{//UL_Mess("potential loop",1);

if (parity.f)return 0; // must be even number everywhere

if(!action) // split processing depending on size of the loop

       if(line_count>7) {  tult.Store(this); return 0;}

       else action++;

 // les deux ci-dessous sortent en 4.6 et 4.7; voir l'origine de l'écart (nb de pas???)

if(action==1 && nadds<2) //one cell with adds rating 4.6 revérifié, c'est bien 4.6

    {USHORT iu=adds[0];      if(T81t[iu].Change(chd))

         {UL_Mess("one cell with extra digits ",1);

          return 1;}

     } // nothing if redundancy with another loop

 

 // now one digit in excess ++++++++++++

 if(action==1 && (cht.QC()==3))  // rating 4.6 en tous cas si 2 en objet

   { ZINFL zi; zi.InitUn(); for(int i=0;i<nadds;i++) zi&=t81f[adds[i]].z;

     if(T81->Clear(zi,(cht-chd).First() ))

             {UL_Mess(" one digit in excess",1); return 1; }        

    }

 

 

// action 1, launching the process common to UR/UL

if(nadds==2) // type 2;3;4 must be same object

    { if(!(t81f[adds[0]].ObjCommun(&t81f[adds[1]]) )) return 0;  

      int ir=y$.StartECbi(adds[0],adds[1],chd,action);

         if(ir==1)

         {UL_Mess("action UL / 2 cells)",1); return 1;}  

 

    }

         // store it if action 0

if(action<2)   { tult.Store(this); return 0;}

 

//UL_Mess("nothing",1);

 return 0;}

//----- 

void UL_SEARCH::UL_Mess(char * lib,int pr)  // et flag des "faits"

{ E$.Enl();

 E$.E("UL loop nadds=");E$.E(nadds); E$.E(" count=");E$.E(line_count);

 E$.E(" rating=");E$.E(o$.difficulty);

 for(int i=0;i<line_count;i++) {E$.Esp(); E$.E(t81f[tcount[i]].pt);}

 E$.Enl();

 if(pr) {E$.E("active due to " );E$.Enl(lib);   }

}