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
- 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;
- }
- }
- }
- 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 obj = objs[Math.floor(Math.random()*objs.length)];
- r[obj.i][obj.j].v = obj.v;
- }
- 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, 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 generate = document.getElementById('generate');
- let check = document.getElementById('check');
- let clear = document.getElementById('clear');
- let note = document.getElementById('note');
- generate.addEventListener('click', function(event){
- try{
- sudoku_UI.gen();
- }
- catch(e){
- console.log(e);
- }
- let sto = setTimeout(function(){
- 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') );
- }
- },
- 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];
- // 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 type='text' class='inp'></td>";
- }else{
- this.grid_UI[i][j].textContent = this.grid[i][j].v;
- }
- }
- }
- },
- check: function(){
- if( this.grid==null )
- return null;
- 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!="" && inp[0].value!=this.sol[i][j].v ){
- note.className = "not-ok-note";
- note.textContent = "You have made some mistakes.";
- return null;
- }
- else if( inp[0].value=="" ){
- 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="";
- }
- }
- }
- }
- }
- sudoku_UI.init();
Advertisement
Add Comment
Please, Sign In to add comment