function Sudoku(x,y){this.tamano=9;this.XOrigen=x;this.YOrigen=y;this.ESav=false;this.C_Fila=new Array(this.tamano);this.C_Columna=new Array(this.tamano);this.C_Cuadro=new Array(this.tamano);this.Contador=new Array(this.tamano);this.Quedan=this.tamano*this.tamano;this.Tablero=new Tipo_Tablero(this.tamano,this.tamano);this.Tablero_save=new Tipo_Tablero(this.tamano,this.tamano);this.Posibles=new Tipo_Tablero(this.tamano,this.tamano,this.tamano);this.Inicializar=Inicializa_Tabla;this.Contiene=Contiene;this.CPOS=CPOS;this.Salvar=Salva;this.Posiciona=Posiciona;this.BT_Fila=BT_Fila;this.BT_Columna=BT_Columna;this.BT_Cuadro=BT_Cuadro;this.BP_Fila=BP_Fila;this.BP_Columna=BP_Columna;this.BP_Cuadro=BP_Cuadro;this.PeFila=PeFila;this.PeColumna=PeColumna;this.MU=MU;this.Resuelve=Resuelve;this.XWing=XWing;this.YWing=YWing;this.Chequea=Chequea;this.Prepara=Prepara;this.Reiniciar=Reiniciar;this.Genera_Cuadro=Genera_Cuadro;}function Tipo_Tablero(x,y){var Tabla=new Array(x);var i,j;for (i=0;i<x;i++){Tabla[i]=new Array(y); if (Tipo_Tablero.arguments.length==3) for (j=0;j<y;j++) Tabla[i][j]=new Array(Tipo_Tablero.arguments[2]);}return Tabla;}function Inicializa_Tabla(){var i,j,k,elemento;for (i=0;i<this.tamano;i++){for (j=0;j<this.tamano;j++){this.Tablero[i][j]=0; elemento=window.document.getElementById('caja'+(i+this.XOrigen)+'_'+(j+this.YOrigen)); elemento.disabled=false; elemento.value=""; for (k=0;k<9;k++) this.Posibles[i][j][k]=k+1;}this.C_Fila[i]=this.tamano; this.C_Columna[i]=this.tamano; this.C_Cuadro[i]=this.tamano; this.Contador[i]=0;}this.ESav=false;this.Quedan=this.tamano*this.tamano;}function Reiniciar(){var i,j;this.Inicializar();for (i=0;i<9;i++) for (j=0;j<9;j++) if (this.Tablero_save[i][j]>0) this.Posiciona(i,j,this.Tablero_save[i][j]);}function Contiene(x,y){if (this.XOrigen<=x && (this.XOrigen+this.tamano)>x) if (this.YOrigen<=y && (this.YOrigen+this.tamano)>y) return true;return false;}function CPOS(x,y){var posibles=new Array();for (var i=0;i<9;i++) if (this.Posibles[x][y][i]>0) posibles.push(i+1);return posibles;}function Salva(){var i,j;for (i=0;i<9;i++) for (j=0;j<9;j++) this.Tablero_save[i][j]=this.Tablero[i][j];this.ESav=true;}function Posiciona(x,y,Numero){var i,j;var X=x-(x%3);var Y=y-(y%3);var elemento=window.document.getElementById('caja'+(x+this.XOrigen)+'_'+(y+this.YOrigen));this.Tablero[x][y]=Numero;this.Quedan--;elemento.value=Numero;elemento.style.color="";elemento.disabled=true;Solucion+="("+(this.XOrigen+x+1)+","+(this.XOrigen+y+1)+") &#8594; "+Numero+"<br>";Numero--;for (i=0;i<9;i++){this.Posibles[i][y][Numero]=0; this.Posibles[x][i][Numero]=0; this.Posibles[x][y][i]=0;}for (i=X;i<=X+2;i++) for (j=Y;j<=Y+2;j++) this.Posibles[i][j][Numero]=0;this.Posibles[x][y][Numero]=Numero+1;this.C_Fila[x]--;this.C_Columna[y]--;this.C_Cuadro[X+parseInt(Y/3)]--;this.Contador[Numero]++;return (this.Quedan>0)}function BT_Fila(x){var i,j,k,l,n;var cpos1,cpos2,cpos3;for (i=0;i<7;i++) if(this.Tablero[x][i]==0){cpos1=this.CPOS(x,i); if (cpos1.length<4) for (j=i+1;j<8;j++) if (this.Tablero[x][j]==0){cpos2=this.CPOS(x,j); if (cpos2.length<4) for (n=j+1;n<9;n++) if (this.Tablero[x][n]==0){cpos3=this.CPOS(x,n); if (cpos3.length<4){cpos3=Union(cpos1,cpos2,cpos3); if (cpos3.length==3){for (k=0;k<9;k++) if ((k!=i) && (k!=j) && (k!=n)) for (l=0;l<cpos3.length;l++) this.Posibles[x][k][cpos3[l]-1]=0; j=n=9;}}}}}}function BT_Columna(y){var i,j,k,l,n;var cpos1,cpos2,cpos3;for (i=0;i<7;i++) if (this.Tablero[i][y]==0){cpos1=this.CPOS(i,y); if (cpos1.length<4) for (j=i+1;j<8;j++) if (this.Tablero[j][y]==0){cpos2=this.CPOS(j,y); if (cpos2.length<4) for (n=j+1;n<9;n++) if (this.Tablero[n][y]==0){cpos3=this.CPOS(n,y); if (cpos3.length<4){cpos3=Union(cpos1,cpos2,cpos3); if (cpos3.length==3){for (k=0;k<9;k++) if ((k!=i) && (k!=j) && (k!=n)) for (l=0;l<cpos3.length;l++) this.Posibles[k][y][cpos3[l]-1]=0; j=n=9;}}}}}}function BT_Cuadro(x,y){var i,j,k,l,m,n,o,a,b;var X=x-(x%3);var Y=y-(y%3);var cpos1,cpos2,cpos3;for (i=X;i<=X+2;i++) for (j=Y;j<=Y+2;j++) if (this.Tablero[i][j]==0){cpos1=this.CPOS(i,j); if (cpos1.length<4) for (k=i;k<=X+2;k++) for (l=Y;l<=Y+2;l++) if ((3*i+j<3*k+l) && this.Tablero[k][l]==0){cpos2=this.CPOS(k,l); if (cpos2.length<4){for (a=k;a<=X+2;a++) for (b=Y;b<=Y+2;b++) if ((3*k+l<3*a+b) && this.Tablero[a][b]==0){cpos3=this.CPOS(a,b); if (cpos3.length<4){cpos3=Union(cpos1,cpos2,cpos3); if (cpos3.length==3){for (m=X;m<=X+2;m++) for (n=Y;n<=Y+2;n++) if (((m!=i) || (n!=j)) && ((m!=k) || (n!=l)) && ((m!=a) || (n!=b))) for (o=0;o<cpos3.length;o++) this.Posibles[m][n][cpos3[o]-1]=0; a=b=k=l=9;}}}}}}}function BP_Fila(x){var i,j,k,l;var cpos1,cpos2;for (i=0;i<8;i++) if(this.Tablero[x][i]==0){cpos1=this.CPOS(x,i); if (cpos1.length==2) for (j=i+1;j<9;j++) if (this.Tablero[x][j]==0){cpos2=this.CPOS(x,j); if (cpos2.length==2) if (cpos1.join('')==cpos2.join('')){for (k=0;k<9;k++) if ((k!=i) && (k!=j)) for (l=0;l<cpos1.length;l++) this.Posibles[x][k][cpos1[l]-1]=0; j=9;}}}}function BP_Columna(y){var i,j,k,l;var cpos1,cpos2;for (i=0;i<8;i++) if (this.Tablero[i][y]==0){cpos1=this.CPOS(i,y); if (cpos1.length==2) for (j=i+1;j<9;j++) if (this.Tablero[j][y]==0){cpos2=this.CPOS(j,y); if (cpos2.length==2) if (cpos1.join('')==cpos2.join('')){for (k=0;k<9;k++) if ((k!=i) && (k!=j)) for (l=0;l<cpos1.length;l++) this.Posibles[k][y][cpos1[l]-1]=0; j=9;}}}}function BP_Cuadro(x,y){var i,j,k,l,m,n,o;var X=x-(x%3);var Y=y-(y%3);var cpos1,cpos2;for (i=X;i<=X+2;i++) for (j=Y;j<=Y+2;j++) if (this.Tablero[i][j]==0){cpos1=this.CPOS(i,j); if (cpos1.length==2) for (k=i;k<=X+2;k++) for (l=Y;l<=Y+2;l++) if (3*i+j<3*k+l && this.Tablero[k][l]==0){cpos2=this.CPOS(k,l); if (cpos2.length==2) if (cpos1.join('')==cpos2.join('')){for (m=X;m<=X+2;m++) for (n=Y;n<=Y+2;n++) if (((m!=i) || (n!=j)) && ((m!=k) || (n!=l))) for (o=0;o<cpos1.length;o++) this.Posibles[m][n][cpos1[o]-1]=0; k=l=9;}}}}function PeFila(x,y){var i,j,k,l;var Cuantas=new Array(3);var X=x-(x%3);var Y=y-(y%3);for (k=0;k<9;k++){for (i=0;i<=2;i++) Cuantas[i]=0; for (i=X;i<=X+2;i++) if (this.C_Fila[i]>0) for (j=Y;j<=Y+2;j++) if (this.Tablero[i][j]==0 && this.Posibles[i][j][k]>0) Cuantas[i-X]=1; if ((Cuantas[0]+Cuantas[1]+Cuantas[2])==1){for (i=0;i<=2;i++) if (Cuantas[i]==1) l=X+i; for (j=0;j<9;j++) if ((this.Tablero[l][j]==0) && ((j<Y) || (j>Y+2))) this.Posibles[l][j][k]=0;}}}function PeColumna(x,y){var i,j,k,l;var Cuantas=new Array(3);var X=x-(x%3);var Y=y-(y%3);for (k=0;k<9;k++){for (i=0;i<=2;i++) Cuantas[i]=0; for (i=Y;i<=Y+2;i++) if (this.C_Columna[i]>0) for (j=X;j<=X+2;j++) if (this.Tablero[j][i]==0 && this.Posibles[j][i][k]>0) Cuantas[i-Y]=1; if ((Cuantas[0]+Cuantas[1]+Cuantas[2])==1){for (i=0;i<=2;i++) if (Cuantas[i]==1) l=Y+i; for (i=0;i<9;i++) if ((this.Tablero[i][l]==0) && ((i<X) || (i>X+2))) this.Posibles[i][l][k]=0;}}}function MU(x,y){var i,j,k,retorno;var p1,p2;var X=x-(x%3);var Y=y-(y%3);var hay_alguno=false;for (k=0;k<9;k++){for (i=X;i<=X+2;i++){retorno=0; for (j=0;j<9;j++) if ((this.Tablero[i][j]==0) && (this.Posibles[i][j][k]>0)){retorno++; p2=j;}if (retorno==1) hay_alguno=(hay_alguno || this.Posiciona(i,p2,k+1));}for (j=Y;j<=Y+2;j++){retorno=0; for (i=0;i<9;i++) if ((this.Tablero[i][j]==0) && (this.Posibles[i][j][k]>0)){retorno++; p1=i;}if (retorno==1) hay_alguno=(hay_alguno || this.Posiciona(p1,j,k+1));}retorno=0; for (i=X;i<=X+2;i++) for (j=Y;j<=Y+2;j++) if ((this.Tablero[i][j]==0) && (this.Posibles[i][j][k]>0)){retorno++; p1=i; p2=j;}if (retorno==1) hay_alguno=(hay_alguno || this.Posiciona(p1,p2,k+1)); if (this.Quedan==0) return false;}return hay_alguno;}function Resuelve(){var i,j,k,l;var cpos;var Hay_Alguno=true;while (Hay_Alguno==true){Hay_Alguno=false; for (i=0;i<9;i+=3) for(j=0;j<9;j+=3){this.PeFila(i,j); this.PeColumna(i,j);}for (i=0;i<9;i++) if (this.C_Fila[i]>0){if (this.C_Fila[i]>3) this.BT_Fila(i); if (this.C_Fila[i]>2) this.BP_Fila(i); for (j=0;j<9;j++) if (this.C_Columna[j]>0){if (this.C_Columna[j]>3) this.BT_Columna(j); if (this.C_Columna[j]>2) this.BP_Columna(j); if (this.Tablero[i][j]==0){cpos=this.CPOS(i,j); if (cpos.length==1) Hay_Alguno=this.Posiciona(i,j,cpos[0]); l=k; k=3*parseInt(i/3)+parseInt(j/3); if (k!=l){if (this.C_Cuadro[k]>3) this.BT_Cuadro(i,j); if (this.C_Cuadro[k]>2) this.BP_Cuadro(i,j);}Hay_Alguno=(Hay_Alguno || this.MU(i,j)); if (this.Quedan==0) return;}}}if (Hay_Alguno==false && this.Quedan>0) Hay_Alguno=this.XWing() || this.YWing();}}function XWing(){var i,j,k,l,hay=0;var columnas=new Array();var tmp=new Array();for (k=0;k<9;k++) if (this.Contador[k]<8){for (i=0;i<9;i++) if (this.C_Fila[i]>1){for (j=0;j<9;j++) if (this.Tablero[i][j]==0 && this.Posibles[i][j][k]>0) tmp.push(j); if (tmp.length==2) columnas[columnas.length]=new Array(i,tmp[0],tmp[1]); tmp.splice(0,tmp.length);}if (columnas.length>=2){for (i=0;i<columnas.length-1;i++) for (j=1;j<columnas.length;j++) if (i!=j) if (columnas[i][1]==columnas[j][1] && columnas[i][2]==columnas[j][2]){for (l=0;l<9;l++){if (this.Tablero[columnas[i][0]][l]==0 && l!=columnas[i][1] && l!=columnas[i][2]){hay+=this.Posibles[columnas[i][0]][l][k]; this.Posibles[columnas[i][0]][l][k]=0;}if (this.Tablero[columnas[j][0]][l]==0 && l!=columnas[j][1] && l!=columnas[j][2]){hay+=this.Posibles[columnas[j][0]][l][k]; this.Posibles[columnas[j][0]][l][k]=0;}if (this.Tablero[l][columnas[i][1]]==0 && l!=columnas[i][0] && l!=columnas[j][0]){hay+=this.Posibles[l][columnas[i][1]][k]; this.Posibles[l][columnas[i][1]][k]=0;}if (this.Tablero[l][columnas[i][2]]==0 && l!=columnas[i][0] && l!=columnas[j][0]){hay+=this.Posibles[l][columnas[i][2]][k]; this.Posibles[l][columnas[i][2]][k]=0;}}}}columnas.splice(0,columnas.length);}return (hay>0 ? true : false);}function YWing(){var i,j,k,l,hay=0;var filas=new Array();var tmp=new Array();for (k=0;k<9;k++) if (this.Contador[k]<8){for (j=0;j<9;j++) if (this.C_Columna[j]>1){for (i=0;i<9;i++) if (this.Tablero[i][j]==0 && this.Posibles[i][j][k]>0) tmp.push(i); if (tmp.length==2) filas[filas.length]=new Array(j,tmp[0],tmp[1]); tmp.splice(0,tmp.length);}if (filas.length>=2){for (i=0;i<filas.length-1;i++) for (j=1;j<filas.length;j++) if (i!=j) if (filas[i][1]==filas[j][1] && filas[i][2]==filas[j][2]){for (l=0;l<9;l++){if (this.Tablero[l][filas[i][0]]==0 && l!=filas[i][1] && l!=filas[i][2]){hay+=this.Posibles[l][filas[i][0]][k]; this.Posibles[l][filas[i][0]][k]=0;}if (this.Tablero[l][filas[j][0]]==0 && l!=filas[j][1] && l!=filas[j][2]){hay+=this.Posibles[l][filas[j][0]][k]; this.Posibles[l][filas[j][0]][k]=0;}if (this.Tablero[filas[i][1]][l]==0 && l!=filas[i][0] && l!=filas[j][0]){hay+=this.Posibles[filas[i][1]][l][k]; this.Posibles[filas[i][1]][l][k]=0;}if (this.Tablero[filas[i][2]][l]==0 && l!=filas[i][0] && l!=filas[j][0]){hay+=this.Posibles[filas[i][2]][l][k]; this.Posibles[filas[i][2]][l][k]=0;}}}}filas.splice(0,filas.length);}return (hay>0 ? true : false);}function Chequea(){var i,j;var elemento;var Hay_Alguno=false;for (i=0;i<9;i++) for (j=0;j<9;j++){elemento=window.document.getElementById('caja'+(this.XOrigen+i)+'_'+(this.YOrigen+j)); if ((elemento.value>0) && (this.Posibles[i][j][elemento.value-1]==0)) Hay_Alguno=Marca_Color(elemento,"red");}return Hay_Alguno;}function Prepara(){var i,j,k,l,n;var elemento,valor;var anterior=new Array(9);var Tabla_Errores=new Array();if (this.Chequea()) return;for (i=0;i<9;i++){anterior[i]=new Array(9); for (j=0;j<9;j++) anterior[i][j]=this.Tablero[i][j];}for (i=0;i<9;i++) for (j=0;j<9;j++) if (this.Tablero[i][j]==0){valor=window.document.getElementById('caja'+(this.XOrigen+i)+"_"+ (this.YOrigen+j)).value; if (valor>0){if (this.Posibles[i][j][valor-1]>0) this.Posiciona(i,j,valor); else{for (k=0;k<9;k++) for (l=0;l<9;l++){elemento=window.document.getElementById('caja'+(this.XOrigen+k)+"_"+(this.YOrigen+l)); if (anterior[k][l]==0 && elemento.value!='') Tabla_Errores.push(elemento,elemento.value);}this.Inicializa_Tablero(); for (k=0;k<9;k++) for (l=0;l<9;l++) if (anterior[k][l]>0) this.Posiciona(k,l,anterior[k][l]); for (k=0;k<Tabla_Errores.length;k=k+2){Tabla_Errores[k].value=Tabla_Errores[k+1]; Marca_Color(Tabla_Errores[k],"red");}alert("Hay errores en las posiciones marcadas en rojo."); return false;}}}if (this.ESav==false) this.Salvar();return true;}function Genera_Cuadro(plantilla,numeros){var i,j,p=0;var pat,texto=plantilla;var letra=new Array('a','b','c','d','e','f','g','h','i');for (i=0;i<9;i++){pat=eval("/"+letra[i]+"/gi"); texto=texto.replace(pat,numeros[i]);}pat=texto.split('');for (i=0;i<9;i++) for (j=0;j<9;j++,p++){if (pat[p]>0) this.Posiciona(i,j,pat[p]); this.Tablero_save[i][j]=pat[p]}this.ESav=true;}
