snippetjavascriptTip
Implementing a Sudoku validator in JavaScript
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:
If you aren't familiar, the rules are as follows:
- Each row must contain the digits 1-9 without repetition.
- Each column must contain the digits 1-9 without repetition.
- 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;
};- Each row must contain the digits 1-9 without repetition.
- Each column must contain the digits 1-9 without repetition.
- 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.