Files
vim-sudoku/src_old/sudoku/validate-board.ts
T
2025-10-19 17:59:12 +01:00

105 lines
3.2 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* Validate a fully filled Sudoku board (81-char string)
* Returns true if:
* - 81 characters long
* - all characters are digits 1–9
* - all rows, columns, and 3×3 boxes sum to 45
*/
export function validateFullBoard(board: string): boolean {
// --- Basic sanity ---
if (board.length !== 81) return false;
if (!/^[1-9]+$/.test(board)) return false;
const getCell = (r: number, c: number) => Number(board[r * 9 + c]);
// --- Validate rows ---
for (let r = 0; r < 9; r++) {
const sum = Array.from({ length: 9 }, (_, c) => getCell(r, c))
.reduce((a, b) => a + b, 0);
if (sum !== 45) return false;
}
// --- Validate columns ---
for (let c = 0; c < 9; c++) {
const sum = Array.from({ length: 9 }, (_, r) => getCell(r, c))
.reduce((a, b) => a + b, 0);
if (sum !== 45) return false;
}
// --- Validate 3×3 boxes ---
for (let br = 0; br < 3; br++) {
for (let bc = 0; bc < 3; bc++) {
const sum = Array.from({ length: 9 }, (_, i) => {
const r = br * 3 + Math.floor(i / 3);
const c = bc * 3 + (i % 3);
return getCell(r, c);
}).reduce((a, b) => a + b, 0);
if (sum !== 45) return false;
}
}
return true;
}
/**
* 🔍 Assert that a Sudoku board string represents a valid, fully filled grid.
*
* Format:
* - 81 characters
* - Only digits 1–9
* - Each row, column, and 3×3 box contains unique digits that sum to 45
*
* Throws descriptive errors on failure.
*/
export function assertValidFullBoard(board: string): void {
// --- Basic integrity checks ---
console.assert(board.length === 81, `❌ Board length must be 81, got ${board.length}`);
if (board.length !== 81) throw new Error(`Invalid board length: ${board.length}`);
// All characters must be digits 1–9
console.assert(/^[1-9]+$/.test(board), "❌ Board must contain only digits 1–9 (no 0s or dots)");
if (!/^[1-9]+$/.test(board)) throw new Error("Board contains invalid characters");
const get = (r: number, c: number) => Number(board[r * 9 + c]);
// --- Helper to assert uniqueness and sum ---
const assertGroup = (label: string, cells: number[]) => {
const sum = cells.reduce((a, b) => a + b, 0);
const unique = new Set(cells);
console.assert(sum === 45, `❌ ${label} sum=${sum} (should be 45)`);
console.assert(unique.size === 9, `❌ ${label} has duplicates: [${cells.join(",")}]`);
if (sum !== 45) throw new Error(`${label} does not sum to 45`);
if (unique.size !== 9) throw new Error(`${label} contains duplicates`);
};
// --- Validate rows ---
for (let r = 0; r < 9; r++) {
const row = Array.from({ length: 9 }, (_, c) => get(r, c));
assertGroup(`Row ${r + 1}`, row);
}
// --- Validate columns ---
for (let c = 0; c < 9; c++) {
const col = Array.from({ length: 9 }, (_, r) => get(r, c));
assertGroup(`Column ${c + 1}`, col);
}
// --- Validate 3×3 boxes ---
for (let br = 0; br < 3; br++) {
for (let bc = 0; bc < 3; bc++) {
const box: number[] = [];
for (let r = 0; r < 3; r++) {
for (let c = 0; c < 3; c++) {
box.push(get(br * 3 + r, bc * 3 + c));
}
}
const idx = br * 3 + bc + 1;
assertGroup(`Box ${idx}`, box);
}
}
}