Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- function sudoku_cell() {
- return {
- p: [1,2,3,4,5,6,7,8,9],
- v: 0,
- rand: function(){
- let max = this.p.length-1;
- let min = 0;
- let i = Math.floor( Math.random()*(max-min+1)+min );
- this.v = this.p.splice(i,1)[0];
- return this.v;
- },
- remove: function(el){ // remove elem if contains return true, else false
- for(let i=0;i<this.p.length;i++){
- if( this.p[i]==el ){
- this.p.splice(i,1);
- return true;
- }
- }
- return false;
- },
- isEmpty: function(){
- if( this.v==0 && this.p.length==0 )
- return true;
- return false;
- }
- }
- }
- function sudoku_cell_copy(v, p) {
- return {
- p: p,
- v: v,
- rand: function(){
- let max = this.p.length-1;
- let min = 0;
- let i = Math.floor( Math.random()*(max-min+1)+min );
- this.v = this.p.splice(i,1)[0];
- return this.v;
- },
- remove: function(el){ // remove elem if contains
- for(let i=0;i<this.p.length;i++){
- if( this.p[i]==el ){
- this.p.splice(i,1);
- break;
- }
- }
- },
- isEmpty: function(){
- if( this.v==0 && this.p.length==0 )
- return true;
- return false;
- }
- }
- }
- let steps=0;
- let sudoku = { // 9*9 sudoku
- t: null,
- init: function(){
- this.t = [];
- for(let i=0;i<9;i++){
- let mt = [];
- for(let j=0;j<9;j++){
- mt.push( sudoku_cell() );
- }
- this.t.push(mt);
- }
- },
- eliminate: function(t, n, ki, kj){
- // row elimination
- for(let i=0;i<9;i++){
- if( t[ki][i].v==0 ){
- t[ki][i].remove(n);
- }
- if( t[ki][i].isEmpty() ){
- return false;
- }
- }
- // column elimination
- for(let i=0;i<9;i++){
- if( t[i][kj].v==0 ){
- t[i][kj].remove(n);
- }
- if( t[i][kj].isEmpty() ){
- return false;
- }
- }
- // mini-grid elimination
- let ci=Math.floor(ki/3)*3, cj=Math.floor(kj/3)*3;
- for(let i=0;i<3;i++){
- for(let j=0;j<3;j++){
- if( t[ci+i][cj+j].v==0 ){
- t[ci+i][cj+j].remove(n);
- }
- if( t[ci+i][cj+j].isEmpty() ){
- return false;
- }
- }
- }
- return true;
- },
- copy: function(t){
- let r = [];
- for(let i=0;i<9;i++){
- let mt = [];
- for(let j=0;j<9;j++){
- let obj = sudoku_cell_copy(t[i][j].v, t[i][j].p.slice());
- mt.push( obj );
- }
- r.push(mt);
- }
- return r;
- },
- gen: function(t, ki, kj, n, lki, lkj){
- // steps++;
- // if( steps>100 )
- // return null;
- // eleminate possibilities
- if( !(ki==0 && kj==0) && !this.eliminate(t, n, lki, lkj) ){
- return null;
- }
- // this.print(t);
- // next
- let nki, nkj;
- if( kj==8 ){
- nki = ki+1;
- nkj = 0;
- }else{
- nki = ki;
- nkj = kj+1;
- }
- while( t[ki][kj].p.length!=0 ){
- let nv = t[ki][kj].rand();
- if( nki==9 ){
- // job done
- return t;
- }
- let r = this.gen(this.copy(t), nki, nkj, nv, ki, kj);
- if( r!=null ){
- // this.print(r);
- return r;
- }
- }
- return null;
- },
- rand: function(){
- console.log(" init.. ");
- this.init();
- console.log(" randering.. ");
- let r = this.gen(this.t, 0, 0, 0, 0, 0);
- // console.log(r);
- console.log(" printing.. ");
- this.print(r);
- console.log(" digging.. ");
- this.dig(r, 30);
- this.print(r);
- console.log(" solving.. ");
- let s;
- // console.log(s);
- while( (s=this.solve(r)).length>1 ){
- // for(let i=0;i<s.length;i++){
- // console.log(" -------------- ");
- // this.print(s[i]);
- // }
- let objs = [];
- // mn:
- for(let i=0;i<9;i++){
- for(let j=0;j<9;j++){
- if( s[0][i][j].v!=s[1][i][j].v ){
- objs.push({
- i: i, j: j,
- v: s[0][i][j].v
- });
- }
- }
- }
- // let str="";
- // for(let i=0;i<objs.length;i++){
- // str+="["+objs[i].i+","+objs[i].j+","+objs[i].v+"]; ";
- // }
- // console.log(str);
- // console.log(" ------bgrid-------- ");
- // this.print(r);
- let obj = objs[Math.floor(Math.random()*objs.length)];
- // console.log(obj.i, obj.j, obj.v);
- r[obj.i][obj.j].v = obj.v;
- this.eliminate(r, obj.v, obj.i, obj.j);
- // console.log(" ------grid-------- ");
- // this.print(r);
- }
- console.log(" final randering.. ");
- // this.print(r);
- // console.log(s);
- return [r, s[0]];
- },
- print: function(t){
- // let obj =null;
- let str = "";
- for(let i=0;i<9;i++){
- for(let j=0;j<9;j++){
- // if( obj==null && t[i][j].v==0 ){
- // obj = t[i][j];
- // // console.log(obj.v, obj.p.join(", "));
- // }
- str += t[i][j].v;
- if( j%3==2 )
- str += " ";
- }
- str +="\n";
- }
- console.log(str);
- },
- dig: function(t, N){
- let pz = [];
- for(let i=0;i<9;i++){
- let tpz = [];
- for(let j=0;j<9;j++){
- tpz.push( {i: i, j: j} );
- }
- pz.push( tpz );
- }
- let n=9*9;
- while(n>N){
- let ti = Math.floor( Math.random()*pz.length );
- let tj = Math.floor( Math.random()*pz[ti].length );
- let obj = pz[ti][tj];
- t[obj.i][obj.j].v = 0;
- pz[ti].splice(tj, 1);
- if( pz[ti].length==0 ){
- pz.splice(ti, 1);
- }
- n--;
- }
- return t;
- },
- solve: function(t){
- for(let i=0;i<9;i++){
- for(let j=0;j<9;j++){
- if( t[i][j].v==0 ){
- t[i][j].p = [1,2,3,4,5,6,7,8,9];
- }
- }
- }
- for(let i=0;i<9;i++){
- for(let j=0;j<9;j++){
- if( t[i][j].v!=0 ){
- this.eliminate(t, t[i][j].v, i, j);
- }
- }
- }
- let sols = [];
- this._solve(sols, this.copy(t), 0, 0, 0);
- return sols;
- },
- _solve: function(sols, t, si ,sj, n){
- // steps++;
- // if( steps>10000 )
- // return null;
- if( sols.length>1 )
- return null;
- if( !(si==0 && sj==0) && !this.eliminate(t, n, si, sj) ){
- return null;
- }
- // console.log("t")
- // this.print(t);
- let i=si, j=sj;
- while( i<9 && t[i][j].v!=0 ){
- if( j==8 ){
- j=0;
- i++;
- }else{
- j++;
- }
- }
- if( i==9 ){
- // console.log("i==9")
- // this.print(t);
- sols.push( t );
- return null;
- }
- while( t[i][j].p.length>0 ){
- let nv = t[i][j].rand();
- this._solve(sols, this.copy(t), i, j, nv);
- if( sols.length>1 )
- return null;
- }
- }
- };
- let sts=0;
- let sudoku_Eval = {
- byInclusion: function(t){
- let b = 0;
- for(let i=0;i<t.length;i++){
- for(let j=0;j<t[i].length;j++){
- if( t[i][j].v==0 && t[i][j].p.length==1 ){
- t[i][j].v=t[i][j].p[0];
- // console.log('inclusion: row '+(i+1)+', col '+(j+1)+' val='+t[i][j].v)
- if( !sudoku.eliminate(t, t[i][j].v, i, j) ) // mean that the grid is unsolvable
- return -1;
- b++;
- }
- }
- }
- return b;
- },
- byExclusionRegion: function(t){
- let b=0;
- for(let ki=0;ki<3;ki++){
- for(let kj=0;kj<3;kj++){
- let oc = [];
- for(let i=0;i<9;i++){
- oc.push({
- o: 0,
- i: 0, j: 0
- });
- }
- for(let i=0;i<3;i++){
- for(let j=0;j<3;j++){
- if( t[3*ki+i][3*kj+j].v==0 ){
- for(let k=0;k<t[3*ki+i][3*kj+j].p.length;k++){
- if( ++oc[t[3*ki+i][3*kj+j].p[k]-1].o==1 ){
- oc[t[3*ki+i][3*kj+j].p[k]-1].i = 3*ki+i;
- oc[t[3*ki+i][3*kj+j].p[k]-1].j = 3*kj+j;
- }
- }
- }
- }
- }
- let i=0;
- while(i<oc.length){
- if( oc[i].o==1 ){
- t[oc[i].i][oc[i].j].v=i+1;
- // console.log('exclusion region: row '+(oc[i].i+1)+', col '+(oc[i].j+1)+' val='+(i+1))
- if( !sudoku.eliminate(t, i+1, oc[i].i, oc[i].j) ) // mean that the grid is unsolvable
- return -1;
- b++;
- }
- i++;
- }
- }
- }
- return b;
- },
- byExclusionColumn: function(t){
- let b=0;
- for(let kj=0;kj<9;kj++){
- let oc = [];
- for(let i=0;i<9;i++){
- oc.push({
- o: 0,
- i: 0, j: 0
- });
- }
- for(let i=0;i<9;i++){
- if( t[i][kj].v==0 ){
- for(let k=0;k<t[i][kj].p.length;k++){
- if( ++oc[t[i][kj].p[k]-1].o==1 ){
- oc[t[i][kj].p[k]-1].i = i;
- oc[t[i][kj].p[k]-1].j = kj;
- }
- }
- }
- }
- let i=0;
- while(i<oc.length){
- if( oc[i].o==1 ){
- t[oc[i].i][oc[i].j].v=i+1;
- // console.log('exclusion column: row '+(oc[i].i+1)+', col '+(oc[i].j+1)+' val='+(i+1))
- if( !sudoku.eliminate(t, i+1, oc[i].i, oc[i].j) ) // mean that the grid is unsolvable
- return -1;
- b++;
- }
- i++;
- }
- }
- return b;
- },
- byExclusionRow: function(t){
- let b=0;
- for(let ki=0;ki<9;ki++){
- let oc = [];
- for(let i=0;i<9;i++){
- oc.push({
- o: 0,
- i: 0, j: 0
- });
- }
- for(let i=0;i<9;i++){
- if( t[ki][i].v==0 ){
- for(let k=0;k<t[ki][i].p.length;k++){
- if( ++oc[t[ki][i].p[k]-1].o==1 ){
- oc[t[ki][i].p[k]-1].i = ki;
- oc[t[ki][i].p[k]-1].j = i;
- }
- }
- }
- }
- let i=0;
- while(i<oc.length){
- if( oc[i].o==1 ){
- t[oc[i].i][oc[i].j].v=i+1;
- // console.log('exclusion row: row '+(oc[i].i+1)+', col '+(oc[i].j+1)+' val='+(i+1))
- if( !sudoku.eliminate(t, i+1, oc[i].i, oc[i].j) ) // mean that the grid is unsolvable
- return -1;
- b++;
- }
- i++;
- }
- }
- return b;
- },
- byExclusivepairRegion: function(t){
- let b=0;
- for(let kc=0;kc<9;kc++){
- let ci = Math.floor(kc/3) , cj = kc%3;
- fi:
- for(let i=0;i<9;i++){
- while(i<9 &&
- !(t[3*ci+Math.floor(i/3)][3*cj+i%3].v==0 &&
- t[3*ci+Math.floor(i/3)][3*cj+i%3].p.length==2)) i++;
- if( i==9 ) break;
- let rri = Math.floor(i/3), rci = i%3;
- for(let j=i+1;j<9;j++){
- console.log()
- while(j<9 &&
- !(t[3*ci+Math.floor(j/3)][3*cj+j%3].v==0 &&
- t[3*ci+Math.floor(j/3)][3*cj+j%3].p.length==2)) j++;
- if( j==9 ) break fi;
- let rrj = Math.floor(j/3), rcj = j%3;
- if( t[3*ci+rri][3*cj+rci].p[0]==t[3*ci+rrj][3*cj+rcj].p[0]
- && t[3*ci+rri][3*cj+rci].p[1]==t[3*ci+rrj][3*cj+rcj].p[1] ){
- for(let k=0;k<9;k++){
- let rrk = Math.floor(k/3), rck = k%3;
- if( k==i || k==j || t[3*ci+rrk][3*cj+rck].v!=0 ) continue;
- t[3*ci+rrk][3*cj+rck].remove(t[3*ci+rri][3*cj+rci].p[0]);
- t[3*ci+rrk][3*cj+rck].remove(t[3*ci+rri][3*cj+rci].p[1]);
- if( t[3*ci+rrk][3*cj+rck].p.length==1 ){
- t[3*ci+rrk][3*cj+rck].v = t[3*ci+rrk][3*cj+rck].p[0];
- // console.log('exclusive pair region: row '+(3*ci+rrk+1)+', col '+(3*cj+rck+1)
- // +' val='+(t[3*ci+rrk][3*cj+rck].v))
- if( !sudoku.eliminate(t, t[3*ci+rrk][3*cj+rck].v, 3*ci+rrk, 3*cj+rck) ) // mean that the grid is unsolvable
- return -1;
- b++;
- }
- }
- }
- }
- }
- }
- return b;
- },
- byExclusivepairColumn: function(t){
- let b=0;
- for(let kj=0;kj<9;kj++){
- fi:
- for(let i=0;i<9;i++){
- while(i<9 && !(t[i][kj].v==0 && t[i][kj].p.length==2)) i++;
- if( i==9 ) break;
- for(let j=i+1;j<9;j++){
- while(j<9 && !(t[j][kj].v==0 && t[j][kj].p.length==2)) j++;
- if( j==9 ) break fi;
- if( t[i][kj].p[0]==t[j][kj].p[0]
- && t[i][kj].p[1]==t[j][kj].p[1] ){
- for(let k=0;k<9;k++){
- if( k==i || k==j || t[k][kj].v!=0 ) continue;
- t[k][kj].remove(t[i][kj].p[0]);
- t[k][kj].remove(t[i][kj].p[1]);
- if( t[k][kj].p.length==1 ){
- t[k][kj].v=t[k][kj].p[0];
- // sudoku.eliminate(t, t[k][kj].v, k, kj);
- // console.log('exclusive pair column: row '+(k+1)+', col '+(kj+1)
- // +' val='+(t[k][kj].v))
- if( !sudoku.eliminate(t, t[k][kj].v, k, kj) ) // mean that the grid is unsolvable
- return -1;
- b++;
- }
- }
- }
- }
- }
- }
- return b;
- },
- byExclusivepairRow: function(t){
- let b=0;
- for(let ki=0;ki<9;ki++){
- fi:
- for(let i=0;i<9;i++){
- while(i<9 && !(t[ki][i].v==0 && t[ki][i].p.length==2)) i++;
- if( i==9 ) break;
- for(let j=i+1;j<9;j++){
- while(j<9 && !(t[ki][j].v==0 && t[ki][j].p.length==2)) j++;
- if( j==9 ) break fi;
- if( t[ki][i].p[0]==t[ki][j].p[0]
- && t[ki][i].p[1]==t[ki][j].p[1] ){
- for(let k=0;k<9;k++){
- if( k==i || k==j || t[ki][k].v!=0 ) continue;
- t[ki][k].remove(t[ki][i].p[0]);
- t[ki][k].remove(t[ki][i].p[1]);
- if( t[ki][k].p.length==1 ){
- t[ki][k].v=t[ki][k].p[0];
- // sudoku.eliminate(t, t[ki][k].v, ki, k);
- // console.log('exclusive pair column: row '+(ki+1)+', col '+(k+1)
- // +' val='+(t[ki][k].v))
- if( !sudoku.eliminate(t, t[ki][k].v, ki, k) ) // mean that the grid is unsolvable
- return -1;
- b++;
- }
- }
- }
- }
- }
- }
- return b;
- },
- byExclusivetripletRegion: function(t){
- let b=0;
- for(let kc=0;kc<9;kc++){
- let ci=Math.floor(kc/3), cj=kc%3;
- fi:
- for(let i=0;i<9;i++){
- while(i<9 &&
- !(t[3*ci+Math.floor(i/3)][3*cj+i%3].v==0 &&
- t[3*ci+Math.floor(i/3)][3*cj+i%3].p.length==3)) i++;
- let rri = Math.floor(i/3), rci = i%3;
- if( i==9 ) break;
- for(let j=i+1;j<9;j++){
- while(j<9 &&
- !(t[3*ci+Math.floor(j/3)][3*cj+j%3].v==0 &&
- t[3*ci+Math.floor(j/3)][3*cj+j%3].p.length==3)) j++;
- let rrj = Math.floor(j/3), rcj = j%3;
- if( j==9 ) break fi;
- for(let k=j+1;k<9;k++){
- while(k<9 &&
- !(t[3*ci+Math.floor(k/3)][3*cj+k%3].v==0 &&
- t[3*ci+Math.floor(k/3)][3*cj+k%3].p.length==3)) k++;
- let rrk = Math.floor(k/3), rck = k%3;
- if( k==9 ) break fi;
- if( t[3*ci+rri][3*cj+rci].p[0]==t[3*ci+rrj][3*cj+rcj].p[0] &&
- t[3*ci+rri][3*cj+rci].p[0]==t[3*ci+rrk][3*cj+rck].p[0] &&
- t[3*ci+rri][3*cj+rci].p[1]==t[3*ci+rrj][3*cj+rcj].p[1] &&
- t[3*ci+rri][3*cj+rci].p[1]==t[3*ci+rrk][3*cj+rck].p[1] &&
- t[3*ci+rri][3*cj+rci].p[2]==t[3*ci+rrj][3*cj+rcj].p[2] &&
- t[3*ci+rri][3*cj+rci].p[2]==t[3*ci+rrk][3*cj+rck].p[2] ){
- for(let l=0;l<9;l++){
- let rrl = Math.floor(l/3), rcl = l%3;
- if( l==i || l==j || l==k || t[l][kj].v!=0 ) continue;
- t[3*ci+rrl][3*cj+rcl].remove(t[3*ci+rri][3*cj+rci].p[0]);
- t[3*ci+rrl][3*cj+rcl].remove(t[3*ci+rri][3*cj+rci].p[1]);
- t[3*ci+rrl][3*cj+rcl].remove(t[3*ci+rri][3*cj+rci].p[2]);
- if( t[3*ci+rrl][3*cj+rcl].p.length==1 ){
- t[3*ci+rrl][3*cj+rcl].v=t[3*ci+rrl][3*cj+rcl].p[0];
- // console.log('exclusive triplet region: row '+(3*ci+rrl+1)+', col '+(3*cj+rcl+1)
- // +' val='+(t[3*ci+rrl][3*cj+rcl].v));
- if( !sudoku.eliminate(t, t[3*ci+rrl][3*cj+rcl].v, 3*ci+rrl, 3*cj+rcl) ) // mean that the grid is unsolvable
- return -1;
- b++;
- }
- }
- }
- }
- }
- }
- }
- return b;
- },
- byExclusivetripletColumn: function(t){
- let b=0;
- for(let kj=0;kj<9;kj++){
- fi:
- for(let i=0;i<9;i++){
- while(i<9 && !(t[i][kj].v==0 && t[i][kj].p.length==3)) i++;
- if( i==9 ) break;
- for(let j=i+1;j<9;j++){
- while(j<9 && !(t[j][kj].v==0 && t[j][kj].p.length==3)) j++;
- if( j==9 ) break fi;
- for(let k=j+1;k<9;k++){
- while(k<9 && !(t[k][kj].v==0 && t[k][kj].p.length==3)) k++;
- if( k==9 ) break fi;
- if( t[i][kj].p[0]==t[j][kj].p[0] && t[i][kj].p[0]==t[k][kj].p[0]
- && t[i][kj].p[1]==t[j][kj].p[1] && t[i][kj].p[1]==t[k][kj].p[1]
- && t[i][kj].p[2]==t[j][kj].p[2] && t[i][kj].p[2]==t[k][kj].p[2] ){
- for(let l=0;l<9;l++){
- if( l==i || l==j || l==k || t[l][kj].v!=0 ) continue;
- t[l][kj].remove(t[i][kj].p[0]);
- t[l][kj].remove(t[i][kj].p[1]);
- t[l][kj].remove(t[i][kj].p[2]);
- if( t[l][kj].p.length==1 ){
- t[l][kj].v=t[l][kj].p[0];
- sudoku.eliminate(t, t[l][kj].v, l, kj);
- // console.log('exclusive triplet column: row '+(l+1)+', col '+(kj+1)
- // +' val='+(t[l][kj].v))
- if( !sudoku.eliminate(t, t[l][kj].v, l, kj) ) // mean that the grid is unsolvable
- return -1;
- b++;
- }
- }
- }
- }
- }
- }
- }
- return b;
- },
- byExclusivetripletRow: function(t){
- let b=0;
- for(let ki=0;ki<9;ki++){
- fi:
- for(let i=0;i<9;i++){
- while(i<9 && !(t[ki][i].v==0 && t[ki][i].p.length==3)) i++;
- if( i==9 ) break;
- for(let j=i+1;j<9;j++){
- while(j<9 && !(t[ki][j].v==0 && t[ki][j].p.length==3)) j++;
- if( j==9 ) break fi;
- for(let k=j+1;k<9;k++){
- while(k<9 && !(t[ki][k].v==0 && t[ki][k].p.length==3)) k++;
- if( k==9 ) break fi;
- if( t[ki][i].p[0]==t[ki][j].p[0] && t[ki][i].p[0]==t[ki][k].p[0]
- && t[ki][i].p[1]==t[ki][j].p[1] && t[ki][i].p[1]==t[ki][k].p[1]
- && t[ki][i].p[2]==t[ki][j].p[2] && t[ki][i].p[2]==t[ki][k].p[2] ){
- for(let l=0;l<9;l++){
- if( l==i || l==j || l==k || t[ki][l].v!=0 ) continue;
- t[ki][l].remove(t[ki][i].p[0]);
- t[ki][l].remove(t[ki][i].p[1]);
- t[ki][l].remove(t[ki][i].p[2]);
- if( t[ki][l].p.length==1 ){
- t[ki][l].v=t[ki][l].p[0];
- sudoku.eliminate(t, t[ki][l].v, ki, l);
- // console.log('exclusive triplet row: row '+(ki+1)+', col '+(l+1)
- // +' val='+(t[ki][l].v))
- if( !sudoku.eliminate(t, t[ki][l].v, ki, l) ) // mean that the grid is unsolvable
- return -1;
- b++;
- }
- }
- }
- }
- }
- }
- }
- return b;
- },
- // Multiple choice is the same as backtracking
- eval: function(t, sol){
- let score1, score2, score3;
- let ic={n:0};let ie={n:0};let iep={n:0};let iet={n:0};let imc={n:0};
- let sc={n:0};
- let mnbc = 9;
- for(let i=0;i<9;i++){
- // let tt=[];
- let nbc=0;
- for(let j=0;j<9;j++){
- if( t[i][j].v==0 ){
- t[i][j].p=[1,2,3,4,5,6,7,8,9];
- }else{
- t[i][j].p=[];sc.n++;nbc++;
- }
- }
- if( mnbc>nbc )
- mnbc = nbc;
- }
- // score 1
- if( sc.n>=50 )
- score1=1;
- else if( sc.n<=49 && sc.n>=36 )
- score1=2;
- else if( sc.n<=35 && sc.n>=32 )
- score1=3;
- else if( sc.n<=31 && sc.n>=28)
- score1=4;
- else if( sc.n<=27 && sc.n>=22)
- score1=5;
- // score 2
- if( mnbc>=5 )
- score2=1;
- else if( mnbc==4 )
- score2=2;
- else if( mnbc==3 )
- score2=3;
- else if( mnbc==2 )
- score2=4;
- else// if( mnbc==1 || mnbc==0 )
- score2=5;
- console.log(" start sc.n",sc.n)
- for(let i=0;i<9;i++){
- for(let j=0;j<9;j++){
- if( t[i][j].v!=0 ){
- sudoku.eliminate(t, t[i][j].v, i, j);
- }
- }
- }
- console.log('start solving...');
- sudoku.print(t);
- let st = this._solve(sudoku.copy(t),0,0,0, ic,ie,iep,iet,imc, sc);
- if( st!=null ){
- sudoku.print(st);
- for(let i=0;i<9;i++){
- let tt = [];
- for(let j=0;j<9;j++){
- tt.push(st[i][j]);
- }
- sol.push(tt);
- }
- }else{
- }
- // score 2
- if( imc.n>0 )
- score3=5;
- else if( iet.n>0 )
- score3=4;
- else if( iep.n>0 )
- score3=3;
- else if( ie.n>0 )
- score3=2;
- else if( ic.n>0 )
- score3=1;
- console.log('inclusion count: ', ic.n);
- console.log('exclusion count: ', ie.n);
- console.log('exclusive pair count: ', iep.n);
- console.log('exclusive triplet count: ', iet.n);
- console.log('multiple choice count: ', imc.n);
- let nl = Math.round((score1+score2+score3)/3), level="?";
- switch(nl){
- case 1:
- level = "Extremely Easy";
- break;
- case 2:
- level = "Easy";
- break;
- case 3:
- level = "Medium";
- break;
- case 4:
- level = "Difficult";
- break;
- case 5:
- level = "Evil";
- break;
- }
- console.log('scores: ', score1, score2, score3);
- console.log('nl: ', nl);
- console.log('level: ', level);
- return level;
- },
- _solve: function(t,nbr,i,j, ic,ie,iep,iet,imc, sc){
- // if(sts>100)
- // return null;
- // sts++;
- if( nbr!=0 )
- if( !sudoku.eliminate(t, nbr, i, j) )
- return null;
- if(sc.n==82) return t;
- let n;
- while( true ){
- // if(sts>100)
- // return null;
- // sts++;
- n=this.byInclusion(t);
- // console.log('inclusion n='+n);
- if( n>0 ){
- // sudoku.print(t);
- ic.n+=n;
- sc.n+=n;
- // console.log(sc.n)
- if(sc.n==81) return t;
- continue;
- }
- else if(n==-1)
- return null;
- n=this.byExclusionColumn(t);
- // console.log('exclusion n='+n);
- if( n>0 ){
- // sudoku.print(t);
- ie.n+=n;
- sc.n+=n;
- // console.log(sc.n)
- if(sc.n==81) return t;
- continue;
- }
- else if(n==-1)
- return null;
- n=this.byExclusionRegion(t);
- // console.log('exclusion n='+n);
- if( n>0 ){
- // sudoku.print(t);
- ie.n+=n;
- sc.n+=n;
- // console.log(sc.n)
- if(sc.n==81) return t;
- continue;
- }
- else if(n==-1)
- return null;
- n=this.byExclusionRow(t);
- // console.log('exclusion n='+n);
- if( n>0 ){
- // sudoku.print(t);
- ie.n+=n;
- sc.n+=n;
- // console.log(sc.n)
- if(sc.n==81) return t;
- continue;
- }
- else if(n==-1)
- return null;
- n=this.byExclusivepairColumn(t);
- // console.log('exclusion pair n='+n);
- if( n>0 ){
- // sudoku.print(t);
- iep.n+=n;
- sc.n+=n;
- // console.log(sc.n)
- if(sc.n==81) return t;
- continue;
- }
- else if(n==-1)
- return null;
- n=this.byExclusivepairRegion(t);
- // console.log('exclusion pair n='+n);
- if( n>0 ){
- // sudoku.print(t);
- iep.n+=n;
- sc.n+=n;
- // console.log(sc.n)
- if(sc.n==81) return t;
- continue;
- }
- else if(n==-1)
- return null;
- n=this.byExclusivepairRow(t);
- // console.log('exclusion pair n='+n);
- if( n>0 ){
- // sudoku.print(t);
- iep.n+=n;
- sc.n+=n;
- // console.log(sc.n)
- if(sc.n==81) return t;
- continue;
- }
- else if(n==-1)
- return null;
- n=this.byExclusivetripletColumn(t);
- // console.log('exclusion triplet n='+n);
- if( n>0 ){
- // sudoku.print(t);
- iet.n+=n;
- sc.n+=n;
- // console.log(sc.n)
- if(sc.n==81) return t;
- continue;
- }
- else if(n==-1)
- return null;
- n=this.byExclusivetripletRegion(t);
- // console.log('exclusion triplet n='+n);
- if( n>0 ){
- // sudoku.print(t);
- iet.n+=n;
- sc.n+=n;
- // console.log(sc.n)
- if(sc.n==81) return t;
- continue;
- }
- else if(n==-1)
- return null;
- n=this.byExclusivetripletRow(t);
- // console.log('exclusion triplet n='+n);
- if( n>0 ){
- // sudoku.print(t);
- iet.n+=n;
- sc.n+=n;
- // console.log(sc.n)
- if(sc.n==81) return t;
- continue;
- }
- else if(n==-1)
- return null;
- break;
- }
- let ni=i, nj=j;
- while( ni<9 && t[ni][nj].v!=0 ){
- if(nj==8){
- ni++;
- nj=0;
- }else{ nj++; }
- }
- if( ni==9 )
- return t;
- else{
- while( t[ni][nj].p.length>0 ){
- let nb = t[ni][nj].p[0];
- t[ni][nj].p.shift();
- t[ni][nj].v = nb;
- imc.n++;
- sc.n++;
- // console.log('multiple choice: row '+(ni+1)+', col '+(nj+1)
- // +' val='+(nb))
- // console.log("sc.n",sc.n)
- // sudoku.eliminate(t, nb, ni, nj);
- let nic={n:ic.n}, nie={n:ie.n}, niep={n:iep.n}, niet={n:iet.n}, nimc={n:imc.n};
- let nsc = {n:sc.n};
- let s = this._solve(sudoku.copy(t),nb,ni,nj, nic,nie,niep,niet,nimc, nsc);
- if( s!=null ){
- // console.log('s!=null')
- ic.n = nic.n;
- ie.n = nie.n;
- iep.n = niep.n;
- iet.n = niet.n;
- imc.n = nimc.n;
- sc.n = nsc.n;
- return s;
- }
- // console.log('multiple choice remove: row '+(ni+1)+', col '+(nj+1)
- // +' val='+(t[ni][nj].v))
- imc.n--;
- sc.n--;
- // console.log("sc.n",sc.n)
- }
- // no solution found
- return null;
- }
- }
- }
- let enter = document.getElementById('enter');
- let evaluate = document.getElementById('evaluate');
- let play = document.getElementById('play');
- let generate = document.getElementById('generate');
- let check = document.getElementById('check');
- let clear = document.getElementById('clear');
- let note = document.getElementById('note');
- enter.addEventListener('click', function(event){
- sudoku_UI.enter();
- });
- evaluate.addEventListener('click', function(event){
- sudoku_UI.evaluate();
- });
- play.addEventListener('click', function(event){
- sudoku_UI.play();
- });
- generate.addEventListener('click', function(event){
- console.log('click');
- try{
- sudoku_UI.gen();
- }
- catch(e){
- console.log(e);
- }
- let sto = setTimeout(function(){
- // console.log(sudoku_UI.sol)
- while( sudoku_UI.sol==undefined ){
- try{
- sudoku_UI.gen();
- }
- catch(e){
- console.log(e);
- }
- }
- clearTimeout(sto);
- }, 100);
- });
- check.addEventListener('click', function(event){
- sudoku_UI.check();
- });
- clear.addEventListener('click', function(event){
- sudoku_UI.clear();
- });
- let sudoku_UI = {
- init: function(){
- let rs = document.getElementsByClassName('row');
- for(let i=0;i<rs.length;i++){
- this.grid_UI.push( rs[i].getElementsByClassName('col') );
- }
- },
- enter: function(){
- note.textContent = "";
- this.sol = null;
- for(let i=0;i<9;i++){
- for(let j=0;j<9;j++){
- this.grid_UI[i][j].innerHTML = "<input class='inp' maxlength=1>";
- }
- }
- let inps = document.getElementsByClassName('inp');
- for(let i=0;i<inps.length;i++){
- inps[i].addEventListener('input', function(event){
- // console.log(event)
- if( !this.value.match(/[1-9]/g) ){
- this.value = "";
- }
- });
- }
- this.grid= [];
- },
- evaluate: function(){
- note.textContent = "";
- let tg = this.grid;
- this.grid=[];
- for(let i=0;i<9;i++){
- let t=[];
- for(let j=0;j<9;j++){
- let inp = this.grid_UI[i][j].getElementsByClassName('inp');
- if(inp.length==0){
- //exception
- if(tg==null)
- return null;
- else
- t.push(sudoku_cell_copy(parseInt(this.grid_UI[i][j].textContent), []));
- }else{
- let n = inp[0].value;
- if( n!="" ){
- this.grid_UI[i][j].innerHTML = n;
- t.push(sudoku_cell_copy(n, []));
- }else{
- t.push(sudoku_cell_copy(0, [1,2,3,4,5,6,7,8,9]));
- }
- }
- }
- this.grid.push(t);
- }
- // sudoku.print(this.grid);
- this.sol = [];
- let level = sudoku_Eval.eval(this.grid, this.sol);
- note.className = "";
- if( this.sol==[] )
- note.textContent = "This grid doesn't accept a solution";
- else
- note.textContent = "This grid is "+level;
- },
- play: function(){
- note.textContent = "";
- this.grid=[];
- for(let i=0;i<9;i++){
- let t=[];
- for(let j=0;j<9;j++){
- let inp = this.grid_UI[i][j].getElementsByClassName('inp');
- if(inp.length==0){
- //exception
- note.className = "";
- note.textContent = "You should enter grid to play it.";
- return null;
- }else{
- let n = inp[0].value;
- if( n!="" ){
- this.grid_UI[i][j].innerHTML = n;
- t.push(sudoku_cell_copy(n,[]));
- }else{
- t.push(sudoku_cell_copy(0, [1,2,3,4,5,6,7,8,9]));
- }
- }
- }
- this.grid.push(t);
- }
- this.sol = [];
- let level = sudoku_Eval.eval(this.grid, this.sol);
- note.className = "";
- if( this.sol==[] ){
- note.textContent = "This grid doesn't accept a solution";
- }else
- note.textContent = "This grid is "+level;
- },
- grid_UI: [],
- grid: null,
- sol: null,
- gen: function(){
- // let s, r;
- note.className = "";
- note.textContent = "Generating... (it may take long time)";
- let tab = sudoku.rand();
- // console.log(tab)
- this.grid = tab[0];
- this.sol = tab[1];
- if( this.sol==undefined )
- return null;
- // console.log(this.sol);
- // sudoku.print(this.sol);
- note.textContent = "";
- for(let i=0;i<this.grid.length;i++){
- for(let j=0;j<this.grid[i].length;j++){
- if( this.grid[i][j].v==0 ){
- this.grid_UI[i][j].innerHTML = "<input class='inp' maxlength=1>";
- }else{
- this.grid_UI[i][j].textContent = this.grid[i][j].v;
- }
- }
- }
- let inps = document.getElementsByClassName('inp');
- for(let i=0;i<inps.length;i++){
- inps[i].addEventListener('input', function(event){
- // console.log(event)
- if( !this.value.match(/[1-9]/g) ){
- this.value = "";
- }
- });
- }
- },
- check: function(){
- if( this.grid==null )
- return null;
- else{
- note.className = "";
- note.textContent = "No grid is entered or generated.";
- }
- let emp = 0;
- for(let i=0;i<this.grid.length;i++){
- for(let j=0;j<this.grid[i].length;j++){
- if( this.grid[i][j].v==0 ){
- let inp = this.grid_UI[i][j].getElementsByClassName('inp');
- // console.log(inp)
- if( inp.length==0 ){
- // exception
- return null;
- }
- if( inp[0].value!="" ){
- if( inp[0].value!=this.sol[i][j].v ){
- note.className = "not-ok-note";
- note.textContent = "You have made some mistakes.";
- inp[0].className = "inp not-ok-try";
- return null;
- }
- else{
- inp[0].className = "inp";
- }
- }
- else/* if( inp[0].value=="" )*/{
- inp[0].className = "inp";
- emp++;
- }
- }/*else{
- this.grid_UI[i][j].textContent = this.grid[i][j].v;
- }*/
- }
- }
- note.className = "ok-note";
- if( emp>0 ){
- note.textContent = "Everything is OK, you still have "+emp+" to go!";
- }else{
- note.textContent = "Sudoku solved. Congratulations!";
- }
- },
- clear: function(){
- if( this.grid==null )
- return null;
- for(let i=0;i<this.grid.length;i++){
- for(let j=0;j<this.grid[i].length;j++){
- if( this.grid[i][j].v==0 ){
- let inp = this.grid_UI[i][j].getElementsByClassName('inp');
- // console.log(inp)
- if( inp.length==0 ){
- // exception
- return null;
- }
- inp[0].value="";
- inp[0].className = "inp";
- }
- }
- }
- }
- }
- sudoku_UI.init();
Advertisement
Add Comment
Please, Sign In to add comment