2
\$\begingroup\$

I'm creating Sudoku in JS but can't find the way to extract the numbers from the squares. The numbers from the rows and columns are easy to extract but I can't find the way around the squares. According to users input, I'll validate the column, then the row and finally the squares to see if the numbers are being repeated. Is this best practice?

Globals:

 var numIni = 9; //Number of squares per side;
 var squared = Math.sqrt(numIni); // I'll need this.

Column check:

function getColumn(){
var num = 30; //USER's INPUT
var colNums = []; //numbers IN the column
var countCol = num; // column anchor
while(countCol > numIni ){
    countCol -= numIni      
}
colNums[0] = countCol;

for(i=1;i< numIni;i++){     
    colNums[i]= colNums[i-1]+9;
 }  
}

Row check:

function getRow(){
var num = 50; //USER's INPUT
var rowAnchor = (Math.ceil(num/numIni))*numIni-(numIni-1);

var rowNums=[rowAnchor]//numbers IN the row

for(i=1;i< numIni;i++){     
    rowNums[i]= rowAnchor+i;
}


}

These last two work, but the squares are killing me. I'm first extracting the anchors, then building the squares and validating the number against that. It's getting quite long. Is there a better way to write this? Is the logic inefficient? If it's right, I'm stuck anyway.

Squares check (so far):

function getSquare(){
var boxes = []; 
var boxesAnchor = []; 
boxes[0]=1;
boxesAnchor[0]=1;

for(i=0; i< numIni*numIni ; i++){
    boxes[i]= squared + ((i-1)* squared )+1;
    }

for(i=0; i< numIni*squared ; i++){
   for(j=0; j< squared ; j++){ 
      boxesAnchor[i] = boxes[i];
      boxesAnchor[i+j] = boxes[i+j];
      boxesAnchor[i+j] = boxes[i+j];
   }
  i +=(numIni-1);  
}

boxesAnchor.clean(undefined);// method added to the Array object

}
\$\endgroup\$
0
3
\$\begingroup\$

As we know, the numbers that could be placed in sudoku cells are limited (1..9). So we can easily make an index to existence of 1 through 9 in each row, column and square. Consider we use rowIndex[9][10], colIndex[9][10] and sqrIndex[9][10] for this purpose. Now checking that putting value v in row x and column y would be like below:

if ( rowIndex[x][v] ) return FAILURE;
if ( colIndex[y][v] ) return FAILURE;
var sqrID = (x/3)*3 + (y/3);
if ( sqrIndex[sqrID][v] ) return FAILURE;
return SUCCESS;

and if SUCCESS is returned we can put that value in the specified cell and update our maps:

rowIndex[x][v] = colIndex[y][v] = sqrIndex[(x/3)*3+(y/3)][v] = 1;

P.S: sqrIndex address all squares in row major.

\$\endgroup\$
2
  • \$\begingroup\$ Can you explain further?? \$\endgroup\$ – Maroshii Feb 18 '12 at 13:17
  • \$\begingroup\$ rowIndex[i][v] is 1 if there is a value v in ith row and 0 otherwise. The same definition stands for colIndex and sqrIndex. Since there are 9 rows, columns and squares, first index is enough to be 9, but values could be at most 9, so second index should be 10 to cover all values (array indices are 0-based). Square ID is easily obtained by dividing row and column IDs by 3. But I assumed squares as a 1D array, so index of your square in this 1D array is X*3+Y. \$\endgroup\$ – saeedn Feb 19 '12 at 15:06
3
\$\begingroup\$

+1 to @saeedn for showing a nice approach to tracking the state of the board in a way that makes checking easy -- I suspect it would involve some major code restructuring from the OP, though the improvement would likely be worth the effort.

That said, here's how getSquares might work within the original approach:

BTW, The (apparent) use of 1-based numbers for the game cells 1-81 vs. 0-80 adds awkwardness as these functions have to keep adjusting for it.

For example, a formula like:

var rowAnchor = (Math.ceil(num/numIni))*numIni-(numIni-1);

more cleanly expressed as

var rowAnchor = Math.floor((num-1)/numIni)*numIni +1;

would be even cleaner if you didn't have to subtract 1 at the start and add 1 at the end, all just to accommodate a 1-based value range.

function getSquare(){
    var squares = []; 
    var rowOfSquares = numIni*squared; // squared?
    // num-1 to account for 1-based range
    var rowAnchor = Math.floor((num-1)/rowOfSquares)*rowOfSquares;
    var colAnchor = Math.floor(((num-1) % numIni) / squared ) * squared;

    squareAnchor = rowAnchor + colAnchor + 1; // + 1 to account for 1-based range


    for (i = 0; i < rowOfSquares ; i += numIni)
        for (j = 0; j < squared; j++)
            square[k] = squareAnchor+i+j;
}

Some final comments: the name squared for the square root made my head hurt. Suggest: root or squareSide. And NOT passing num as an input to these functions or returning the resulting vectors (locals?) added much confusion. I am hoping that these are just artifacts of an attempt to "clean up" for code review.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.