diff --git a/src/algorithms/Recursion/sudokuSolver.js b/src/algorithms/Recursion/sudokuSolver.js new file mode 100644 index 0000000..340ce7b --- /dev/null +++ b/src/algorithms/Recursion/sudokuSolver.js @@ -0,0 +1,44 @@ +function isSafe(board, r, c, num) { + for (let x = 0; x < 9; x++) { + if (board[r][x] === num || board[x][c] === num) return false; + } + + const startRow = r - (r % 3); + const startCol = c - (c % 3); + for (let i = 0; i < 3; i++) { + for (let j = 0; j < 3; j++) { + if (board[startRow + i][startCol + j] === num) return false; + } + } + + return true; +} + +export async function solveSudoku(board, visualizeStep, r = 0, c = 0) { + if (r === 9) return true; + if (c === 9) return await solveSudoku(board, visualizeStep, r + 1, 0); + if (board[r][c] !== 0) return await solveSudoku(board, visualizeStep, r, c + 1); + + for (let num = 1; num <= 9; num++) { + if (isSafe(board, r, c, num)) { + board[r][c] = num; + visualizeStep(r, c, num, "filled"); + await sleep(50); + + if (await solveSudoku(board, visualizeStep, r, c + 1)) return true; + + + board[r][c] = 0; + visualizeStep(r, c, 0, "backtrack"); + await sleep(50); + } else { + visualizeStep(r, c, num, "trying"); + await sleep(20); + } + } + return false; +} + +function sleep(ms) { + return new Promise((resolve) => setTimeout(resolve, ms)); +} diff --git a/src/components/Recursion/sudokuSolver.jsx b/src/components/Recursion/sudokuSolver.jsx new file mode 100644 index 0000000..58c28d4 --- /dev/null +++ b/src/components/Recursion/sudokuSolver.jsx @@ -0,0 +1,84 @@ +// src/components/Recursion/SudokuVisualizer.jsx +import React, { useState } from "react"; +import { solveSudoku } from "../../algorithms/Recursion/sudokuSolver"; + +export default function SudokuVisualizer() { + const initialBoard = [ + [5, 3, 0, 0, 7, 0, 0, 0, 0], + [6, 0, 0, 1, 9, 5, 0, 0, 0], + [0, 9, 8, 0, 0, 0, 0, 6, 0], + [8, 0, 0, 0, 6, 0, 0, 0, 3], + [4, 0, 0, 8, 0, 3, 0, 0, 1], + [7, 0, 0, 0, 2, 0, 0, 0, 6], + [0, 6, 0, 0, 0, 0, 2, 8, 0], + [0, 0, 0, 4, 1, 9, 0, 0, 5], + [0, 0, 0, 0, 8, 0, 0, 7, 9], + ]; + + const [grid, setGrid] = useState(initialBoard); + const [cellStatus, setCellStatus] = useState({}); + const [solving, setSolving] = useState(false); + + const visualizeStep = (r, c, val, status) => { + setGrid((prev) => { + const copy = prev.map((row) => row.slice()); + copy[r][c] = val; + return copy; + }); + + setCellStatus((prev) => ({ + ...prev, + [`${r}-${c}`]: status, + })); + }; + + const handleSolve = async () => { + setSolving(true); + const copy = grid.map((row) => row.slice()); + await solveSudoku(copy, visualizeStep); + setSolving(false); + }; + + return ( +
+

Sudoku Solver Visualizer

+ +
+ {grid.map((row, r) => + row.map((val, c) => { + const status = cellStatus[`${r}-${c}`]; + let bg = "bg-gray-800"; + + if (status === "filled") bg = "bg-green-500"; + else if (status === "trying") bg = "bg-yellow-400"; + else if (status === "backtrack") bg = "bg-red-500"; + + return ( +
+ {val !== 0 ? val : ""} +
+ ); + }) + )} +
+ + +
+ ); +} diff --git a/src/pages/Recursion/RecursionPage.jsx b/src/pages/Recursion/RecursionPage.jsx index 3e2bbc8..8f5bf7d 100644 --- a/src/pages/Recursion/RecursionPage.jsx +++ b/src/pages/Recursion/RecursionPage.jsx @@ -2,6 +2,7 @@ import React, { useState } from "react"; import { X, Menu } from "lucide-react"; import MazeSolver from "./MazeSolver"; import NQueens from "./NQueens"; +import Sudoku from "./sudokuSolver"; export default function RecursionPage() { const [selectedAlgo, setSelectedAlgo] = useState(""); const [sidebarOpen, setSidebarOpen] = useState(true); @@ -20,6 +21,13 @@ export default function RecursionPage() { ); + case "SudokuSolver": + return( +
+ +
+ ); + default: return (
@@ -62,6 +70,7 @@ export default function RecursionPage() { +