const grid8 = [ '', '', '', 5, 1, 2, '', 6, '', 2, 5, '', '', '', '', 9, 1, '', 1, 7, '', '', '', 6, '', 5, 8, '', '', '', '', 8, '', 1, '', '', 5, 1, '', 3, '', 4, '', 9, 6, '', '', 2, '', 6, '', '', '', '', 9, 2, '', 4, '', '', '', 8, 7, '', 4, 3, '', '', '', '', 2, 1, '', 6, '', 2, 7, 1, '', '', '', ]; const grid1 = [ 2, '', 5, '', '', 7, '', '', 6, 4, '', '', 9, 6, '', '', 2, '', '', '', '', '', 8, '', '', 4, 5, 9, 8, '', '', 7, 4, '', '', '', 5, 7, '', 8, '', 2, '', 6, 9, '', '', '', 6, 3, '', '', 5, 7, 7, 5, '', '', 2, '', '', '', '', '', 6, '', '', 5, 1, '', '', 2, 3, '', '', 4, '', '', 5, '', 8, ]; const grid6 = [ 2, '', 3, '', 6, '', '', '', 8, '', 7, '', '', 5, 1, 3, '', '', '', 5, 9, '', '', '', '', '', '', 4, '', 2, 6, 3, '', '', 5, 9, '', '', '', '', 9, '', '', '', '', 3, 9, '', '', 1, 4, 2, '', 6, '', '', '', '', '', '', 4, 2, '', '', '', 1, 8, 4, '', '', 3, '', 7, '', '', '', 2, '', 9, '', 5, ]; function makeGrid() { const sujiDiv = document.getElementById("suji"); for (let x = 0; x < 3; x++) { const bigRow = document.createElement("div"); for (let y = 0; y < 3; y++) { const bigCol = document.createElement("span"); bigCol.classList.add("big-cell"); for (let i = 0; i < 3; i++) { const row = document.createElement("div"); for (let j = 0; j < 3; j++) { const col = document.createElement("span"); const id = 9*(x*3 + i) + y*3 + j; col.classList.add("cell"); col.id = 'cell' + id; col.innerHTML = 'A' row.appendChild(col); } bigCol.appendChild(row); } bigRow.appendChild(bigCol); } sujiDiv.appendChild(bigRow); } } function setCell(id, value, highlight=false) { const cell = document.getElementById('cell' + id); cell.innerHTML = value; if (highlight) { cell.classList.add('cell-highlight'); } else { cell.classList.remove('cell-highlight'); } } function setGrid(grid) { for (let i = 0; i < grid.length; i++) { setCell(i, grid[i]); } } function boxIndices(i) { const indices = []; const boxRow = 3 * Math.floor(i / 27); const boxCol = 3 * Math.floor((i % 9) / 3); let j = boxRow*9 + boxCol; indices.push(j, j+1, j+2); j += 9; indices.push(j, j+1, j+2); j += 9; indices.push(j, j+1, j+2); return indices; } function trimPossibles(grid, i, possibles) { function trim(i, j) { if (grid[j] !== '') return; const k = possibles[j].indexOf(grid[i]); if (possibles[j].includes(grid[i])) { possibles[j].splice(possibles[j].indexOf(grid[i]), 1); } } // 1. trim row const rowStart = 9 * Math.floor(i / 9); for (let j = rowStart; j < rowStart + 9; j++) { trim(i, j); } // 2. trim column const colStart = i % 9; for (let j = colStart; j < grid.length; j+=9) { trim(i, j); } // 3. trim box for (let j of boxIndices(i)) { trim(i, j); } } function checkOnlyOptionInBox(grid, i, possibles) { if (possibles[i].length < 2) { return; } for (let x = 1; x < 10; x++) { let other = false; for (let j of boxIndices(i)) { if (i === j) continue; if (possibles[j].includes(x) || grid[j] === x) { other = true; break; } } if (!other) { possibles[i] = [x]; return; } } } function updateGrid(grid, possibles) { // 4. update grid for (let i = 0; i < grid.length; i++) { if (possibles[i].length === 1) { grid[i] = possibles[i][0]; possibles[i] = []; setCell(i, grid[i], true); } } } function solveGrid(grid) { const possibles = []; // populate possibles for (let i = 0; i < grid.length; i++) { if (grid[i] === '') { possibles[i] = [1, 2, 3, 4, 5, 6, 7, 8, 9]; } else { possibles[i] = []; } } let count = 0; while (grid.indexOf('') >= 0 && count < 10000) { for (let i = 0; i < grid.length; i++) { if (grid[i] === '') { checkOnlyOptionInBox(grid, i, possibles); continue; } trimPossibles(grid, i, possibles); updateGrid(grid, possibles); } count += 1; } return grid.indexOf('') === -1; } let grid = grid6.slice(); function rand(n) { return Math.floor(Math.random() * n); } function pick(arr) { return arr[rand(arr.length)]; } function fillGridRecursive(grid, possibles, i) { if (i >= 81) { return true; } let ok; do { const x = pick(possibles[i]); if (x === undefined) { return false; } grid[i] = x; const newPossibles = possibles.map(x => x.slice()); newPossibles[i] = []; trimPossibles(grid, i, newPossibles); ok = fillGridRecursive(grid, newPossibles, i+1); if (ok) { break; } grid[i+1] = ''; possibles[i].splice(possibles[i].indexOf(x), 1); } while (!ok); return true; } function makeFullGrid() { const possibles = []; const grid = new Array(81); grid.fill(''); // populate possibles for (let i = 0; i < 81; i++) { possibles[i] = [1, 2, 3, 4, 5, 6, 7, 8, 9]; } fillGridRecursive(grid, possibles, 0); return grid; } function generate() { grid = makeFullGrid(); setGrid(grid); } function knock() { const start = Date.now(); while (Date.now() - start < 2000) { const index = rand(81); const preSolve = grid.slice(); grid[index] = ''; const ok = solveGrid(grid); grid = preSolve; if (ok) { grid[index] = ''; } setGrid(grid); } } function main() { makeGrid(); setGrid(grid); document.getElementById("solve").onclick = e => { solveGrid(grid); }; document.getElementById("generate").onclick = e => { generate(); }; document.getElementById("knock").onclick = e => { knock(); }; } window.addEventListener('load', main);