0

Ok, so I looked into the stack overflow site and found some similar questions, but none of them seem to give me the solution to my problem here. If I am correct, arrays and objects are passed by reference automatically in JavaScript and TypeScript, so I can't seem to figure out why it is not working.

Here's my complete code: I am learning algorithms and data structures for my interviews

/**
 * sudoku Problem Board
 */
let sudokuBoard: Array<Array<number>> = [
  [0, 9, 5, 0, 0, 3, 0, 0, 2],
  [0, 0, 0, 0, 0, 1, 0, 0, 0],
  [6, 0, 2, 0, 0, 0, 0, 0, 9],
  [9, 0, 0, 7, 0, 0, 4, 0, 1],
  [0, 0, 0, 0, 0, 0, 5, 0, 0],
  [8, 0, 0, 0, 0, 0, 0, 3, 0],
  [0, 0, 7, 1, 0, 0, 0, 5, 0],
  [0, 1, 0, 8, 6, 0, 0, 2, 0],
  [3, 0, 0, 0, 0, 4, 0, 0, 0],
];

/**
 * Function to print the layout of sudoku board and its solution
 */
let printBoard = (sudokuBoard: Array<Array<number>>) => {
  for (let i: number = 0; i < sudokuBoard.length; i++) {
    if (i % 3 === 0 && i !== 0) {
      console.log("-----------------------");
    }
    let output = ``;
    for (let j: number = 0; j < sudokuBoard[0].length; j++) {
      if (j % 3 === 0 && j !== 0) {
        output += ` | `;
      }
      if (j === 8) {
        output += `${sudokuBoard[i][j]}`;
      } else {
        output += `${sudokuBoard[i][j]} `;
      }
    }
    console.log(output);
  }
  console.log("\n");
};

/**
 * Find the empty cell within the board
 * @param sudokuBoard board for which empty cell is to be found
 */
let findEmptyCell = (sudokuBoard: Array<Array<number>>): Array<number> => {
  for (let i: number = 0; i < sudokuBoard.length; i++) {
    for (let j: number = 0; j < sudokuBoard[0].length; j++) {
      if (sudokuBoard[i][j] === 0) {
        return [i, j];
      }
    }
  }
  return [-1, -1];
};

/**
 * Main Function to call while passing the entire sudoku board to solve
 * @param sudokuBoard
 */
let sudokuSolver = (sudokuBoard: Array<Array<number>>) => {
  const emptyCellPos: Array<number> = findEmptyCell(sudokuBoard);
  if (emptyCellPos[0] !== -1 && emptyCellPos[1] !== -1) {
    const row: number = emptyCellPos[0];
    const col: number = emptyCellPos[1];
    solveCell(row, col, sudokuBoard);
  }
};

/**
 * Function to fill the values in the board
 * @param row starting row index
 * @param col starting col index
 * @param sudokuBoard sudoku board to solve
 */
let solveCell = (
  row: number,
  col: number,
  sudokuBoard: Array<Array<number>>
): boolean => {
  let emptyEntry: number = 0; // value to fill when backtracking is done to restore the wrong cell with default value

  /**
   * Check if column and row bounds are intact and take actions accordingly
   * When col bound is met, change the row
   * When row bound is met, we have finished the board
   */
  if (col === sudokuBoard[row].length) {
    col = 0;
    row++;
    if (row === sudokuBoard.length) {
      return true;
    }
  }

  /**
   * If number present already, recurse for next cell in the row
   */
  if (sudokuBoard[row][col] !== emptyEntry) {
    return solveCell(row, col + 1, sudokuBoard);
  }

  /**
   * If empty cell is found, make a choice from decision set following the required constraint
   * We loop from 1 to board length as all numbers that lie within, will be our decision space
   * We then check each value whether it's suitable for that cell or not
   * If yes, we place it in that cell and check the move for next cell, If it proceeds with true, we do nothing, otherwise we empty that cell with our default 'emptyEntry'
   */
  for (let value: number = 1; value < sudokuBoard.length; value++) {
    let placeValue: number = value;

    if (placeCellValue(sudokuBoard, row, col, placeValue)) {
      sudokuBoard[row][col] = value;

      if (solveCell(row, col + 1, sudokuBoard)) {
        return true;
      }
      sudokuBoard[row][col] = emptyEntry;
    }
  }
  return false;
};

/**
 * Check constraints for value before placing it in the given cell
 * @param sudokuBoard sudoku board to solve
 * @param row row index
 * @param col col index
 * @param placeValue value to place in the given sudokuboard[row][col] cell
 */
let placeCellValue = (
  sudokuBoard: Array<Array<number>>,
  row: number,
  col: number,
  placeValue: number
): boolean => {
  /**
   * Check for the row whether the value is already present
   */
  for (let j: number = 0; j < sudokuBoard[0].length; j++) {
    if (sudokuBoard[row][j] === placeValue) {
      return false;
    }
  }

  /**
   * Check for the column whether the value is already present
   */
  for (let i: number = 0; i < sudokuBoard.length; i++) {
    if (sudokuBoard[i][col] === placeValue) {
      return false;
    }
  }

  /**
   * Check if the value is present in the subgrid
   */
  const regionSize = Math.sqrt(sudokuBoard.length);
  const box_row = Math.floor(row / 3);
  const box_col = Math.floor(col / 3);
  const top_left_box_row = box_row * regionSize;
  const top_left_box_col = box_col * regionSize;

  for (let i: number = 0; i < regionSize; i++) {
    for (let j: number = 0; j < regionSize; j++) {
      if (
        sudokuBoard[top_left_box_row + i][top_left_box_col + j] === placeValue
      ) {
        return false;
      }
    }
  }
  return true;
};

console.log("\nSudoku Problem:\n");
printBoard(sudokuBoard);
sudokuSolver(sudokuBoard);
console.log("\nSudoku Solution:\n");
printBoard(sudokuBoard);

Both the printBoard method is printing the same thing. One more additional information, I am running this TS file using deno directly in the terminal. It compiles typescript automatically, which I find great for this task.

Any help will be appreciated. Thanks.

  • You're calling twice `printBoard` without calling `sudokuSolver`. Aside from that it will still won't work because `sudokuSolver` does not work correctly, but that's another issue, – Marcos Casagrande May 24 '20 at 14:57
  • I edited the code above and both the board is still the same. And I still cannot figure out the issue here. If I change the value of sudokuBoard manually, it prints different boards. Where is my code messing up? – ibcoder.eth May 25 '20 at 13:04

0 Answers0