HiveBrain v1.2.0
Get Started
← Back to all entries
snippetjavascriptTip

Implementing a Sudoku validator in JavaScript

Submitted by: @import:30-seconds-of-code··
0
Viewed 0 times
sudokuimplementingjavascriptvalidator

Problem

I was recently solving LeetCode problems and came across the Valid Sudoku problem. The task is simple: given a partially filled 9x9 Sudoku board, determine if it is valid according to the rules of Sudoku.
If you aren't familiar, the rules are as follows:
  1. Each row must contain the digits 1-9 without repetition.
  2. Each column must contain the digits 1-9 without repetition.
  3. Each of the nine 3x3 sub-boxes must contain the digits 1-9 without repetition.

Solution

const isValidSudoku = board => {
  // Rows check
  for (let i = 0; i < 9; i++) {
    const boardValues = board[i];
    const filled = boardValues.filter(v => v !== '.');
    if (filled.length !== new Set(filled).size) return false;
  }

  // Column check
  for (let i = 0; i < 9; i++) {
    const boardValues = board.map(x => x[i]);
    const filled = boardValues.filter(v => v !== '.');
    if (filled.length !== new Set(filled).size) return false;
  }

  // Sub-box check
  for (let i = 0; i < 9; i++) {
    const y = Math.floor(i / 3) * 3;
    const x = (i % 3) * 3;
    const boardValues = [
      ...board[y].slice(x, x + 3),
      ...board[y + 1].slice(x, x + 3),
      ...board[y + 2].slice(x, x + 3),
    ];
    const filled = boardValues.filter(v => v !== '.');
    if (filled.length !== new Set(filled).size) return false;
  }

  // If all checks pass, the board is valid
  return true;
};


  1. Each row must contain the digits 1-9 without repetition.
  2. Each column must contain the digits 1-9 without repetition.
  3. Each of the nine 3x3 sub-boxes must contain the digits 1-9 without repetition.


Data is represented as a 2D array, where empty cells are represented by '.' and the rest of the values are strings of digits from 1-9.
There are various ways to go about this, but we'll be using a simple brute-force approach, as I think there's still a lot to learn from tackling the sub-box problem, as well as optimizing the solution for the given input constraints.
One of the first things that came to mind was to sum each row, column, and sub-box and compare the value to the expected sum of 45. However, this approach has a few drawbacks:

Code Snippets

const isValidSudoku = board => {
  // Rows check
  for (let i = 0; i < 9; i++) {
    const boardValues = board[i];
    const filled = boardValues.filter(v => v !== '.');
    if (filled.length !== new Set(filled).size) return false;
  }

  // Column check
  for (let i = 0; i < 9; i++) {
    const boardValues = board.map(x => x[i]);
    const filled = boardValues.filter(v => v !== '.');
    if (filled.length !== new Set(filled).size) return false;
  }

  // Sub-box check
  for (let i = 0; i < 9; i++) {
    const y = Math.floor(i / 3) * 3;
    const x = (i % 3) * 3;
    const boardValues = [
      ...board[y].slice(x, x + 3),
      ...board[y + 1].slice(x, x + 3),
      ...board[y + 2].slice(x, x + 3),
    ];
    const filled = boardValues.filter(v => v !== '.');
    if (filled.length !== new Set(filled).size) return false;
  }

  // If all checks pass, the board is valid
  return true;
};
### Return early

Another clear optimization is to **return early when we find a duplicate**. Right now, we are processing the entire row, column, or sub-box, before we can check for duplicates. But, our `Set` can be used earlier to **check for duplicates as we iterate** through the values. We can use the humble `for` loop for this, as it allows us to break out of the loop when we find a duplicate. This way, we can stop processing as soon as we find a duplicate.

Context

From 30-seconds-of-code: sudoku-validator

Revisions (0)

No revisions yet.