SEclone  cell and table of cell


We continue with the main table at the start of the game, the table of cells.

From now on, most of the classes have a separate file for the code.


As I re use the code of my solver, I did not clean some routines supposed to be used later, which does not help to decipher the code.


To limit the trouble, I split the routines in several files and I show here in a first step only what has been used in the first part (basic rules rating 1.0 to 6.2)


Consequently, some functions are defined in the .h files with no code associated.


The first class is a cell P81. We have already defined smaller classes,


One for the permanent date P81F

One for the “variable data” UNP.


No surprise, the class P81  has the variable part and a pointer to the fix part.

Just are missing 2 string dedicated to prints.



// class describing and managing a cell.

// as a matter of fact, data have been split in 2 classes,

//   P81F permanant data

//   UNP  non permanant data

// data remaining are related to tagging printing

// the main table is the basic entry to eliminate candidates

class P81


   char scand[10],colcand[10];  // printing data

   P81F * f; UNP v;

   void Init(){v.Init();}     // at the start

   int Change (int ch) ;      // clear one candate

   int Change (CB9CH cb9)     // clear candidates

                 { int ir=0;for(int i=0;i<9;i++)

                          if(cb9.On(i))ir+= Change (i);   return ir;}

   int Keep (CB9CH cb9)       // clear candidates others than

               {int ir=0;      for(int i=0;i<9;i++)

                if(v.cand.On(i) && cb9.Off(i)) { Change (i);ir=1;}       return ir;}

   int Keep(int ch1,int ch2)  // clear candidates others than

               {int ir=0;     for(int i=0;i<9;i++)

                if(v.cand.On(i) && (i-ch1)&&(i-ch2)) { Change (i);ir=1;}    return ir;}

   int ObjCommun(P81* p8) {return f->ObjCommun(p8->f);}   // same row, column or box


   void Fixer(UCHAR type,UCHAR ch) // force digit as valid in the solution




   char * strcol(int cas){if(o$.ot)return strcol_(cas);return " "; }   // printing purpose


   char * strcol_(int cas);    // printing purpose




Having a look at the routines, one can see that the main ones are dedicated to assignments and eliminations.


Objcommun() is an old one that should be replaced by a direct call of P81F


The second class is the table of cells. TP81 Several copies of that table exist, but the primary one holds the last updated situation of candidates;


A copy of that table is used during UR/UL processing to be sure to restart from the situation at the beginning of a cycle.


Other copies will come later when processing of nested chains will be covered.

That class is not yet fully cleaned. Some routines have still to be cancelled.


Basically, the following functions are made using that table :


Assignments and eliminations of candidates

Generation of specific weak links or sets of tags (to be seen later)

Printing of various table of PM


And 2 specific tasks


Updating of the list of cells not yet assigned ( Actifs() )

Search for UR patterns ( RIN() ) .

Looking at the code, one can see that I made a reservation to process UR including already eliminated candidates, but I never did ir (this refers to an ongoing discussion in the forum)




// class collecting all datas for the cells and managing a cell oriented process


class TP81

{ public:

   P81 t81[81];      


   void init();  


   void Fixer(int ch,int i8,UCHAR typ);

   int Clear(ZINFL &z,int ch  );

   int Clear(ZINFL &z,CB9CH ch  );

   int CheckClear(ZINFL &z,CB9CH ch  );


   void GenzCand(ZINFL & z1,ZINFL & z2,int ic);

   void GenereChoixCases();

   CB9CH   GenCand(ZINFL & z);   

   CB9CH   GenCandTyp01(ZINFL & z);


   void Actifs(ZINFL & z);


   int RIN(int aig=0);


   void imgnappesT(); // will see lat(er, to print tagged PM

   void Candidats(){ if(o$.ot)CandidatsT(10,0);}

   void Candidatsz() {if(!o$.ot)return;

                       E$.Enl("justificatif a posteriori");


   void CandidatsColores(){if(o$.ot) CandidatsT(20,0);}//1-opUS); }


private:    void CandidatsT(int ic,int sansfixe=1);



TP81 * T81,*T81C;             //standard names for main objects of the class

P81 * T81t,*T81tc;            //and corresponding tables of cells 

                      // the corresponding tables are located in class JDK


And  here after the associated functions found in the .cpp file


void TP81::init()

{for(int i=0;i<81;i++)


       t81[i].f=&t81f[i]; }      


void TP81::Fixer(int ch,int i8,UCHAR typ)



int TP81::Clear(ZINFL &z,int ch  )

{//E$.E("clear tp81 ");E$.E(ch+1);z.ImagePoints();  E$.Enl();

int ir=0; for(int i=0;i<81;i++)if( z.On(i))  ir+= t81[i].Change(ch);

return ir;}


int TP81::Clear(ZINFL &z,CB9CH x  )

{ int ir = 0; for(int j=0;j<9;j++)   if( x.On(j)) ir+=Clear(z,j);

return ir;}

//<<<<<<<<<<<<<<<<<<<<    specific ot UR/UL filter to find the lowest length

int TP81::CheckClear(ZINFL &z,CB9CH x  )

{ for(int i=0;i<81;i++)  if(z.On(i))    if((t81[i].v.cand&x).f )  return 1;

return 0;}// positive as soon as one effect found



void TP81::Actifs(ZINFL & z)

{ z.Init(); for(int i=0;i<81;i++) if(!t81[i].v.typ)z.Set(i);}


CB9CH   TP81::GenCand(ZINFL & z)

{CB9CH w;w.f=0; for(int i=0;i<81;i++) if( z.On(i)&&(!t81[i].v.typ)) w=w|t81[i].v.cand;

return w;}

//<<<<<<<<<<<<<<<<<     y compris assigned pour RIs

CB9CH   TP81::GenCandTyp01(ZINFL & z)

{CB9CH w;w.f=0; for(int i=0;i<81;i++) if( z.On(i)&&t81[i].v.typ<2) w=w|t81[i].v.cand;

return w;}


void    TP81::GenzCand(ZINFL & z1,ZINFL & z2,int ic)

{z2.Init();  for(int i=0;i<81;i++)

if(z1.On(i)&&(!t81[i].v.typ)&&t81[i].v.cand.On(ic)) z2.Set(i);  }


void  TP81::GenereChoixCases()

{for(USHORT i=0;i<81;i++)

  {USHORT n= t81[i].v.ncand; if(n<3 || n>chx_max) continue;


       CB9CH ch8=t81[i].v.cand; 

   USHORT nm=0,tm[18];    for(int j=0;j<9;j++) if(ch8.On(j))

     {int ix=zpln.GetPoint(i,j); tm[nm+n]=ix; tm[nm++]=zpln.zp[ix].m;}


    }  }




void TP81::CandidatsT(int ic,int sansfixe)

{if(!o$.ot) return;

 int i,j,l,lcol[9],tcol=0; char * pw;       //lcol  largeur maxi colonne

 E$.E("table des candidats cas "); E$.Enl(ic);

 for(i=0;i<9;i++)  // attention ici i indice colonne

  {if(ic==10)lcol[i]=2; else lcol[i]=1;    // 1  mini tous chiffres imposés

       for(j=0;j<9;j++)   {l=strlen( t81[9*j+i].strcol(ic));




 for(i=0;i<9;i++) {if((i==3) ||(i==6)) E$.E("|");

                       E$.E((char)('A'+i));E$.E(Blancs(lcol[i],1));  }


 for(i=0;i<9;i++)  // maintenant indice ligne

  { if((i==3) ||(i==6))

     {for(int ix=0;ix<(tcol+10);ix++) E$.E((char)'-');   E$.Enl(); }


           { if((j==3) ||(j==6)) E$.E("|");

                P81* pp8= &t81[9*i+j]; pw=pp8->strcol(ic);



                  if(sansfixe) pw[0]='_'else pw[0][i][j];     


             E$.E(pw);   E$.E(Blancs(lcol[j]+1- strlen(pw),1));

                    } // end for j

     E$.Enl();  } // end for i

  E$.Enl("\n\n"); }



void TP81::imgnappesT()


 for(int i=0;i<81;i++) {strcpy_s (t81[i].colcand,10,t81[i].scand);  }

 for (int il=0;il<zpln.ip;il++)

 {ZPTLN pw=zpln.zp[il];  short int c=pw.m;

  if(! ztm.xm.Isch(c)) continue; // marque  dans la liste

  char cf=mms.val(c); if (pw.ig>80) continue; // pas case

  if(c>82) continue; // pas marque une position

  P81 * p8=&t81[pw.ig]; int ili=strlen(p8->scand );

  for(int i=0;i<ili;i++) {if(p8->scand [i]'1') {p8->colcand[i]=cf; break;} }