/** * Create a playable Sudoku puzzle by removing random digits * from a fully solved board string. * * Difficulty only determines how many cells are removed. * - "easy": removes ~40 cells * - "medium": removes ~50 cells * - "hard": removes ~60 cells * * The returned string uses '.' for blanks. */ export function makePuzzle( solution: string, difficulty: "easy" | "medium" | "hard" = "medium" ): string { if (solution.length !== 81 || !/^[1-9]+$/.test(solution)) { throw new Error("Invalid solved board: must be 81 digits 1–9"); } // --- removal count based on difficulty --- const removeCount = { easy: 40, medium: 50, hard: 60, }[difficulty]; // --- create a mutable copy --- const board = solution.split(""); // --- build a shuffled list of indices 0–80 --- const indices = Array.from({ length: 81 }, (_, i) => i); for (let i = indices.length - 1; i > 0; i--) { const j = Math.floor(Math.random() * (i + 1)); [indices[i], indices[j]] = [indices[j], indices[i]]; } // --- remove the desired number of cells --- for (let i = 0; i < removeCount; i++) { const idx = indices[i]; board[idx] = "."; } return board.join(""); }