├── .gitignore ├── dist-types └── index.d.ts ├── package.json ├── README.md ├── dist-web ├── index.js └── index.js.map ├── dist-node ├── index.js └── index.js.map └── dist-src └── index.js /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules -------------------------------------------------------------------------------- /dist-types/index.d.ts: -------------------------------------------------------------------------------- 1 | export function makepuzzle(): any; 2 | export function posfor(x: any,y: any,axis: any): any; 3 | export function ratepuzzle(puzzle: any,samples: any): any; 4 | export function solvepuzzle(board: any): any; 5 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "sudoku", 3 | "description": "Sudoku generator and solver for node.js and Web", 4 | "version": "0.0.3", 5 | "files": [ 6 | "dist-*/" 7 | ], 8 | "pika": true, 9 | "sideEffects": false, 10 | "keywords": [ 11 | "sudoku", 12 | "generate", 13 | "solve", 14 | "puzzle", 15 | "game", 16 | "board" 17 | ], 18 | "homepage": "https://github.com/dachev/sudoku", 19 | "repository": { 20 | "type": "git", 21 | "url": "git://github.com/dachev/sudoku.git" 22 | }, 23 | "dependencies": {}, 24 | "devDependencies": {}, 25 | "esnext": "dist-src/index.js", 26 | "main": "dist-node/index.js", 27 | "module": "dist-web/index.js", 28 | "types": "dist-types/index.d.ts" 29 | } 30 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | # sudoku 3 | 4 | [![Stand With Ukraine](https://raw.githubusercontent.com/vshymanskyy/StandWithUkraine/main/banner2-direct.svg)](https://stand-with-ukraine.pp.ua) 5 | 6 | Sudoku generator and solver for [node.js](http://nodejs.org) and Web. 7 | 8 | ## Live demo 9 | [http://shnapps.dachev.com/sudoku](http://shnapps.dachev.com/sudoku) 10 | 11 | ## Installation 12 | 13 | ``` bash 14 | $ npm install sudoku 15 | ``` 16 | 17 | ## Usage 18 | 19 | ``` javascript 20 | var sudoku = require('sudoku'); 21 | 22 | var puzzle = sudoku.makepuzzle(); 23 | var solution = sudoku.solvepuzzle(puzzle); 24 | var difficulty = sudoku.ratepuzzle(puzzle, 4); 25 | ``` 26 | OR 27 | 28 | ``` typescript 29 | import { makepuzzle, solvepuzzle, ratepuzzle } from "sudoku"; 30 | ``` 31 | 32 | 33 | ## License 34 | Copyright 2010, Blagovest Dachev. 35 | 36 | This program is free software: you can redistribute it and/or modify 37 | it under the terms of the GNU General Public License as published by 38 | the Free Software Foundation, either version 3 of the License, or 39 | (at your option) any later version. 40 | 41 | This program is distributed in the hope that it will be useful, 42 | but WITHOUT ANY WARRANTY; without even the implied warranty of 43 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 44 | GNU General Public License for more details. 45 | 46 | You should have received a copy of the GNU General Public License 47 | along with this program. If not, see . 48 | -------------------------------------------------------------------------------- /dist-web/index.js: -------------------------------------------------------------------------------- 1 | // Sudoku Generator and Solver for node.js 2 | // Copyright (c) 2011 Blagovest Dachev. All rights reserved. 3 | // 4 | // This is a port of David Bau's python implementation: 5 | // http://davidbau.com/archives/2006/09/04/sudoku_generator.html 6 | function makepuzzle(board) { 7 | var puzzle = []; 8 | var deduced = Array(81).fill(null); 9 | var order = [...Array(81).keys()]; 10 | shuffleArray(order); 11 | 12 | for (var i = 0; i < order.length; i++) { 13 | var pos = order[i]; 14 | 15 | if (deduced[pos] === null) { 16 | puzzle.push({ 17 | pos: pos, 18 | num: board[pos] 19 | }); 20 | deduced[pos] = board[pos]; 21 | deduce(deduced); 22 | } 23 | } 24 | 25 | shuffleArray(puzzle); 26 | 27 | for (var i = puzzle.length - 1; i >= 0; i--) { 28 | var e = puzzle[i]; 29 | removeElement(puzzle, i); 30 | var rating = checkpuzzle(boardforentries(puzzle), board); 31 | 32 | if (rating === -1) { 33 | puzzle.push(e); 34 | } 35 | } 36 | 37 | return boardforentries(puzzle); 38 | } 39 | 40 | function ratepuzzle(puzzle, samples) { 41 | var total = 0; 42 | 43 | for (var i = 0; i < samples; i++) { 44 | var tuple = solveboard(puzzle); 45 | 46 | if (tuple.answer === null) { 47 | return -1; 48 | } 49 | 50 | total += tuple.state.length; 51 | } 52 | 53 | return total / samples; 54 | } 55 | 56 | function checkpuzzle(puzzle, board) { 57 | if (board === undefined) { 58 | board = null; 59 | } 60 | 61 | var tuple1 = solveboard(puzzle); 62 | 63 | if (tuple1.answer === null) { 64 | return -1; 65 | } 66 | 67 | if (board != null && !boardmatches(board, tuple1.answer)) { 68 | return -1; 69 | } 70 | 71 | var difficulty = tuple1.state.length; 72 | var tuple2 = solvenext(tuple1.state); 73 | 74 | if (tuple2.answer != null) { 75 | return -1; 76 | } 77 | 78 | return difficulty; 79 | } 80 | 81 | function solvepuzzle(board) { 82 | return solveboard(board).answer; 83 | } 84 | 85 | function solveboard(original) { 86 | var board = [].concat(original); 87 | var guesses = deduce(board); 88 | 89 | if (guesses === null) { 90 | return { 91 | state: [], 92 | answer: board 93 | }; 94 | } 95 | 96 | var track = [{ 97 | guesses: guesses, 98 | count: 0, 99 | board: board 100 | }]; 101 | return solvenext(track); 102 | } 103 | 104 | function solvenext(remembered) { 105 | while (remembered.length > 0) { 106 | var tuple1 = remembered.pop(); 107 | 108 | if (tuple1.count >= tuple1.guesses.length) { 109 | continue; 110 | } 111 | 112 | remembered.push({ 113 | guesses: tuple1.guesses, 114 | count: tuple1.count + 1, 115 | board: tuple1.board 116 | }); 117 | var workspace = [].concat(tuple1.board); 118 | var tuple2 = tuple1.guesses[tuple1.count]; 119 | workspace[tuple2.pos] = tuple2.num; 120 | var guesses = deduce(workspace); 121 | 122 | if (guesses === null) { 123 | return { 124 | state: remembered, 125 | answer: workspace 126 | }; 127 | } 128 | 129 | remembered.push({ 130 | guesses: guesses, 131 | count: 0, 132 | board: workspace 133 | }); 134 | } 135 | 136 | return { 137 | state: [], 138 | answer: null 139 | }; 140 | } 141 | 142 | function deduce(board) { 143 | while (true) { 144 | var stuck = true; 145 | var guess = null; 146 | var count = 0; // fill in any spots determined by direct conflicts 147 | 148 | var tuple1 = figurebits(board); 149 | var allowed = tuple1.allowed; 150 | var needed = tuple1.needed; 151 | 152 | for (var pos = 0; pos < 81; pos++) { 153 | if (board[pos] === null) { 154 | var numbers = listbits(allowed[pos]); 155 | 156 | if (numbers.length === 0) { 157 | return []; 158 | } else if (numbers.length === 1) { 159 | board[pos] = numbers[0]; 160 | stuck = false; 161 | } else if (stuck) { 162 | var t = numbers.map(function (val, key) { 163 | return { 164 | pos: pos, 165 | num: val 166 | }; 167 | }); 168 | var tuple2 = pickbetter(guess, count, t); 169 | guess = tuple2.guess; 170 | count = tuple2.count; 171 | } 172 | } 173 | } 174 | 175 | if (!stuck) { 176 | var tuple3 = figurebits(board); 177 | allowed = tuple3.allowed; 178 | needed = tuple3.needed; 179 | } // fill in any spots determined by elimination of other locations 180 | 181 | 182 | for (var axis = 0; axis < 3; axis++) { 183 | for (var x = 0; x < 9; x++) { 184 | var numbers = listbits(needed[axis * 9 + x]); 185 | 186 | for (var i = 0; i < numbers.length; i++) { 187 | var n = numbers[i]; 188 | var bit = 1 << n; 189 | var spots = []; 190 | 191 | for (var y = 0; y < 9; y++) { 192 | var pos = posfor(x, y, axis); 193 | 194 | if (allowed[pos] & bit) { 195 | spots.push(pos); 196 | } 197 | } 198 | 199 | if (spots.length === 0) { 200 | return []; 201 | } else if (spots.length === 1) { 202 | board[spots[0]] = n; 203 | stuck = false; 204 | } else if (stuck) { 205 | var t = spots.map(function (val, key) { 206 | return { 207 | pos: val, 208 | num: n 209 | }; 210 | }); 211 | var tuple4 = pickbetter(guess, count, t); 212 | guess = tuple4.guess; 213 | count = tuple4.count; 214 | } 215 | } 216 | } 217 | } 218 | 219 | if (stuck) { 220 | if (guess != null) { 221 | shuffleArray(guess); 222 | } 223 | 224 | return guess; 225 | } 226 | } 227 | } 228 | 229 | function figurebits(board) { 230 | var needed = []; 231 | var allowed = board.map(function (val, key) { 232 | return val === null ? 511 : 0; 233 | }, []); 234 | 235 | for (var axis = 0; axis < 3; axis++) { 236 | for (var x = 0; x < 9; x++) { 237 | var bits = axismissing(board, x, axis); 238 | needed.push(bits); 239 | 240 | for (var y = 0; y < 9; y++) { 241 | var pos = posfor(x, y, axis); 242 | allowed[pos] = allowed[pos] & bits; 243 | } 244 | } 245 | } 246 | 247 | return { 248 | allowed: allowed, 249 | needed: needed 250 | }; 251 | } 252 | 253 | function posfor(x, y, axis) { 254 | if (axis === undefined) { 255 | axis = 0; 256 | } 257 | 258 | if (axis === 0) { 259 | return x * 9 + y; 260 | } else if (axis === 1) { 261 | return y * 9 + x; 262 | } 263 | 264 | return [0, 3, 6, 27, 30, 33, 54, 57, 60][x] + [0, 1, 2, 9, 10, 11, 18, 19, 20][y]; 265 | } 266 | 267 | function axismissing(board, x, axis) { 268 | var bits = 0; 269 | 270 | for (var y = 0; y < 9; y++) { 271 | var e = board[posfor(x, y, axis)]; 272 | 273 | if (e != null) { 274 | bits |= 1 << e; 275 | } 276 | } 277 | 278 | return 511 ^ bits; 279 | } 280 | 281 | function listbits(bits) { 282 | var list = []; 283 | 284 | for (var y = 0; y < 9; y++) { 285 | if ((bits & 1 << y) != 0) { 286 | list.push(y); 287 | } 288 | } 289 | 290 | return list; 291 | } 292 | 293 | 294 | function pickbetter(b, c, t) { 295 | if (b === null || t.length < b.length) { 296 | return { 297 | guess: t, 298 | count: 1 299 | }; 300 | } else if (t.length > b.length) { 301 | return { 302 | guess: b, 303 | count: c 304 | }; 305 | } else if (randomInt(c) === 0) { 306 | return { 307 | guess: t, 308 | count: c + 1 309 | }; 310 | } 311 | 312 | return { 313 | guess: b, 314 | count: c + 1 315 | }; 316 | } 317 | 318 | function boardforentries(entries) { 319 | var board = Array(81).fill(null); 320 | 321 | for (var i = 0; i < entries.length; i++) { 322 | var item = entries[i]; 323 | var pos = item.pos; 324 | var num = item.num; 325 | board[pos] = num; 326 | } 327 | 328 | return board; 329 | } 330 | 331 | function boardmatches(b1, b2) { 332 | for (var i = 0; i < 81; i++) { 333 | if (b1[i] != b2[i]) { 334 | return false; 335 | } 336 | } 337 | 338 | return true; 339 | } 340 | 341 | function randomInt(max) { 342 | return Math.floor(Math.random() * (max + 1)); 343 | } 344 | 345 | function shuffleArray(original) { 346 | // Swap each element with another randomly selected one. 347 | for (var i = original.length - 1; i > 0; i--) { 348 | var j = randomInt(i); 349 | var contents = original[i]; 350 | original[i] = original[j]; 351 | original[j] = contents; 352 | } 353 | } 354 | 355 | function removeElement(array, from, to) { 356 | var rest = array.slice((to || from) + 1 || array.length); 357 | array.length = from < 0 ? array.length + from : from; 358 | return array.push.apply(array, rest); 359 | } 360 | module.exports = { 361 | makepuzzle: function () { 362 | return makepuzzle(solvepuzzle(Array(81).fill(null))); 363 | }, 364 | solvepuzzle: solvepuzzle, 365 | ratepuzzle: ratepuzzle, 366 | posfor: posfor 367 | }; 368 | //# sourceMappingURL=index.js.map 369 | -------------------------------------------------------------------------------- /dist-node/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | // Sudoku Generator and Solver for node.js 4 | // Copyright (c) 2011 Blagovest Dachev. All rights reserved. 5 | // 6 | // This is a port of David Bau's python implementation: 7 | // http://davidbau.com/archives/2006/09/04/sudoku_generator.html 8 | function makepuzzle(board) { 9 | var puzzle = []; 10 | var deduced = Array(81).fill(null); 11 | var order = [...Array(81).keys()]; 12 | shuffleArray(order); 13 | 14 | for (var i = 0; i < order.length; i++) { 15 | var pos = order[i]; 16 | 17 | if (deduced[pos] === null) { 18 | puzzle.push({ 19 | pos: pos, 20 | num: board[pos] 21 | }); 22 | deduced[pos] = board[pos]; 23 | deduce(deduced); 24 | } 25 | } 26 | 27 | shuffleArray(puzzle); 28 | 29 | for (var i = puzzle.length - 1; i >= 0; i--) { 30 | var e = puzzle[i]; 31 | removeElement(puzzle, i); 32 | var rating = checkpuzzle(boardforentries(puzzle), board); 33 | 34 | if (rating === -1) { 35 | puzzle.push(e); 36 | } 37 | } 38 | 39 | return boardforentries(puzzle); 40 | } 41 | 42 | function ratepuzzle(puzzle, samples) { 43 | var total = 0; 44 | 45 | for (var i = 0; i < samples; i++) { 46 | var tuple = solveboard(puzzle); 47 | 48 | if (tuple.answer === null) { 49 | return -1; 50 | } 51 | 52 | total += tuple.state.length; 53 | } 54 | 55 | return total / samples; 56 | } 57 | 58 | function checkpuzzle(puzzle, board) { 59 | if (board === undefined) { 60 | board = null; 61 | } 62 | 63 | var tuple1 = solveboard(puzzle); 64 | 65 | if (tuple1.answer === null) { 66 | return -1; 67 | } 68 | 69 | if (board != null && !boardmatches(board, tuple1.answer)) { 70 | return -1; 71 | } 72 | 73 | var difficulty = tuple1.state.length; 74 | var tuple2 = solvenext(tuple1.state); 75 | 76 | if (tuple2.answer != null) { 77 | return -1; 78 | } 79 | 80 | return difficulty; 81 | } 82 | 83 | function solvepuzzle(board) { 84 | return solveboard(board).answer; 85 | } 86 | 87 | function solveboard(original) { 88 | var board = [].concat(original); 89 | var guesses = deduce(board); 90 | 91 | if (guesses === null) { 92 | return { 93 | state: [], 94 | answer: board 95 | }; 96 | } 97 | 98 | var track = [{ 99 | guesses: guesses, 100 | count: 0, 101 | board: board 102 | }]; 103 | return solvenext(track); 104 | } 105 | 106 | function solvenext(remembered) { 107 | while (remembered.length > 0) { 108 | var tuple1 = remembered.pop(); 109 | 110 | if (tuple1.count >= tuple1.guesses.length) { 111 | continue; 112 | } 113 | 114 | remembered.push({ 115 | guesses: tuple1.guesses, 116 | count: tuple1.count + 1, 117 | board: tuple1.board 118 | }); 119 | var workspace = [].concat(tuple1.board); 120 | var tuple2 = tuple1.guesses[tuple1.count]; 121 | workspace[tuple2.pos] = tuple2.num; 122 | var guesses = deduce(workspace); 123 | 124 | if (guesses === null) { 125 | return { 126 | state: remembered, 127 | answer: workspace 128 | }; 129 | } 130 | 131 | remembered.push({ 132 | guesses: guesses, 133 | count: 0, 134 | board: workspace 135 | }); 136 | } 137 | 138 | return { 139 | state: [], 140 | answer: null 141 | }; 142 | } 143 | 144 | function deduce(board) { 145 | while (true) { 146 | var stuck = true; 147 | var guess = null; 148 | var count = 0; // fill in any spots determined by direct conflicts 149 | 150 | var tuple1 = figurebits(board); 151 | var allowed = tuple1.allowed; 152 | var needed = tuple1.needed; 153 | 154 | for (var pos = 0; pos < 81; pos++) { 155 | if (board[pos] === null) { 156 | var numbers = listbits(allowed[pos]); 157 | 158 | if (numbers.length === 0) { 159 | return []; 160 | } else if (numbers.length === 1) { 161 | board[pos] = numbers[0]; 162 | stuck = false; 163 | } else if (stuck) { 164 | var t = numbers.map(function (val, key) { 165 | return { 166 | pos: pos, 167 | num: val 168 | }; 169 | }); 170 | var tuple2 = pickbetter(guess, count, t); 171 | guess = tuple2.guess; 172 | count = tuple2.count; 173 | } 174 | } 175 | } 176 | 177 | if (!stuck) { 178 | var tuple3 = figurebits(board); 179 | allowed = tuple3.allowed; 180 | needed = tuple3.needed; 181 | } // fill in any spots determined by elimination of other locations 182 | 183 | 184 | for (var axis = 0; axis < 3; axis++) { 185 | for (var x = 0; x < 9; x++) { 186 | var numbers = listbits(needed[axis * 9 + x]); 187 | 188 | for (var i = 0; i < numbers.length; i++) { 189 | var n = numbers[i]; 190 | var bit = 1 << n; 191 | var spots = []; 192 | 193 | for (var y = 0; y < 9; y++) { 194 | var pos = posfor(x, y, axis); 195 | 196 | if (allowed[pos] & bit) { 197 | spots.push(pos); 198 | } 199 | } 200 | 201 | if (spots.length === 0) { 202 | return []; 203 | } else if (spots.length === 1) { 204 | board[spots[0]] = n; 205 | stuck = false; 206 | } else if (stuck) { 207 | var t = spots.map(function (val, key) { 208 | return { 209 | pos: val, 210 | num: n 211 | }; 212 | }); 213 | var tuple4 = pickbetter(guess, count, t); 214 | guess = tuple4.guess; 215 | count = tuple4.count; 216 | } 217 | } 218 | } 219 | } 220 | 221 | if (stuck) { 222 | if (guess != null) { 223 | shuffleArray(guess); 224 | } 225 | 226 | return guess; 227 | } 228 | } 229 | } 230 | 231 | function figurebits(board) { 232 | var needed = []; 233 | var allowed = board.map(function (val, key) { 234 | return val === null ? 511 : 0; 235 | }, []); 236 | 237 | for (var axis = 0; axis < 3; axis++) { 238 | for (var x = 0; x < 9; x++) { 239 | var bits = axismissing(board, x, axis); 240 | needed.push(bits); 241 | 242 | for (var y = 0; y < 9; y++) { 243 | var pos = posfor(x, y, axis); 244 | allowed[pos] = allowed[pos] & bits; 245 | } 246 | } 247 | } 248 | 249 | return { 250 | allowed: allowed, 251 | needed: needed 252 | }; 253 | } 254 | 255 | function posfor(x, y, axis) { 256 | if (axis === undefined) { 257 | axis = 0; 258 | } 259 | 260 | if (axis === 0) { 261 | return x * 9 + y; 262 | } else if (axis === 1) { 263 | return y * 9 + x; 264 | } 265 | 266 | return [0, 3, 6, 27, 30, 33, 54, 57, 60][x] + [0, 1, 2, 9, 10, 11, 18, 19, 20][y]; 267 | } 268 | 269 | function axismissing(board, x, axis) { 270 | var bits = 0; 271 | 272 | for (var y = 0; y < 9; y++) { 273 | var e = board[posfor(x, y, axis)]; 274 | 275 | if (e != null) { 276 | bits |= 1 << e; 277 | } 278 | } 279 | 280 | return 511 ^ bits; 281 | } 282 | 283 | function listbits(bits) { 284 | var list = []; 285 | 286 | for (var y = 0; y < 9; y++) { 287 | if ((bits & 1 << y) != 0) { 288 | list.push(y); 289 | } 290 | } 291 | 292 | return list; 293 | } 294 | 295 | 296 | function pickbetter(b, c, t) { 297 | if (b === null || t.length < b.length) { 298 | return { 299 | guess: t, 300 | count: 1 301 | }; 302 | } else if (t.length > b.length) { 303 | return { 304 | guess: b, 305 | count: c 306 | }; 307 | } else if (randomInt(c) === 0) { 308 | return { 309 | guess: t, 310 | count: c + 1 311 | }; 312 | } 313 | 314 | return { 315 | guess: b, 316 | count: c + 1 317 | }; 318 | } 319 | 320 | function boardforentries(entries) { 321 | var board = Array(81).fill(null); 322 | 323 | for (var i = 0; i < entries.length; i++) { 324 | var item = entries[i]; 325 | var pos = item.pos; 326 | var num = item.num; 327 | board[pos] = num; 328 | } 329 | 330 | return board; 331 | } 332 | 333 | function boardmatches(b1, b2) { 334 | for (var i = 0; i < 81; i++) { 335 | if (b1[i] != b2[i]) { 336 | return false; 337 | } 338 | } 339 | 340 | return true; 341 | } 342 | 343 | function randomInt(max) { 344 | return Math.floor(Math.random() * (max + 1)); 345 | } 346 | 347 | function shuffleArray(original) { 348 | // Swap each element with another randomly selected one. 349 | for (var i = original.length - 1; i > 0; i--) { 350 | var j = randomInt(i); 351 | var contents = original[i]; 352 | original[i] = original[j]; 353 | original[j] = contents; 354 | } 355 | } 356 | 357 | function removeElement(array, from, to) { 358 | var rest = array.slice((to || from) + 1 || array.length); 359 | array.length = from < 0 ? array.length + from : from; 360 | return array.push.apply(array, rest); 361 | } 362 | module.exports = { 363 | makepuzzle: function () { 364 | return makepuzzle(solvepuzzle(Array(81).fill(null))); 365 | }, 366 | solvepuzzle: solvepuzzle, 367 | ratepuzzle: ratepuzzle, 368 | posfor: posfor 369 | }; 370 | //# sourceMappingURL=index.js.map 371 | -------------------------------------------------------------------------------- /dist-src/index.js: -------------------------------------------------------------------------------- 1 | // Sudoku Generator and Solver for node.js 2 | // Copyright (c) 2011 Blagovest Dachev. All rights reserved. 3 | // 4 | // This is a port of David Bau's python implementation: 5 | // http://davidbau.com/archives/2006/09/04/sudoku_generator.html 6 | function makepuzzle(board) { 7 | var puzzle = []; 8 | var deduced = Array(81).fill(null); 9 | var order = [...Array(81).keys()]; 10 | shuffleArray(order); 11 | 12 | for (var i = 0; i < order.length; i++) { 13 | var pos = order[i]; 14 | 15 | if (deduced[pos] === null) { 16 | puzzle.push({ 17 | pos: pos, 18 | num: board[pos] 19 | }); 20 | deduced[pos] = board[pos]; 21 | deduce(deduced); 22 | } 23 | } 24 | 25 | shuffleArray(puzzle); 26 | 27 | for (var i = puzzle.length - 1; i >= 0; i--) { 28 | var e = puzzle[i]; 29 | removeElement(puzzle, i); 30 | var rating = checkpuzzle(boardforentries(puzzle), board); 31 | 32 | if (rating === -1) { 33 | puzzle.push(e); 34 | } 35 | } 36 | 37 | return boardforentries(puzzle); 38 | } 39 | 40 | function ratepuzzle(puzzle, samples) { 41 | var total = 0; 42 | 43 | for (var i = 0; i < samples; i++) { 44 | var tuple = solveboard(puzzle); 45 | 46 | if (tuple.answer === null) { 47 | return -1; 48 | } 49 | 50 | total += tuple.state.length; 51 | } 52 | 53 | return total / samples; 54 | } 55 | 56 | function checkpuzzle(puzzle, board) { 57 | if (board === undefined) { 58 | board = null; 59 | } 60 | 61 | var tuple1 = solveboard(puzzle); 62 | 63 | if (tuple1.answer === null) { 64 | return -1; 65 | } 66 | 67 | if (board != null && !boardmatches(board, tuple1.answer)) { 68 | return -1; 69 | } 70 | 71 | var difficulty = tuple1.state.length; 72 | var tuple2 = solvenext(tuple1.state); 73 | 74 | if (tuple2.answer != null) { 75 | return -1; 76 | } 77 | 78 | return difficulty; 79 | } 80 | 81 | function solvepuzzle(board) { 82 | return solveboard(board).answer; 83 | } 84 | 85 | function solveboard(original) { 86 | var board = [].concat(original); 87 | var guesses = deduce(board); 88 | 89 | if (guesses === null) { 90 | return { 91 | state: [], 92 | answer: board 93 | }; 94 | } 95 | 96 | var track = [{ 97 | guesses: guesses, 98 | count: 0, 99 | board: board 100 | }]; 101 | return solvenext(track); 102 | } 103 | 104 | function solvenext(remembered) { 105 | while (remembered.length > 0) { 106 | var tuple1 = remembered.pop(); 107 | 108 | if (tuple1.count >= tuple1.guesses.length) { 109 | continue; 110 | } 111 | 112 | remembered.push({ 113 | guesses: tuple1.guesses, 114 | count: tuple1.count + 1, 115 | board: tuple1.board 116 | }); 117 | var workspace = [].concat(tuple1.board); 118 | var tuple2 = tuple1.guesses[tuple1.count]; 119 | workspace[tuple2.pos] = tuple2.num; 120 | var guesses = deduce(workspace); 121 | 122 | if (guesses === null) { 123 | return { 124 | state: remembered, 125 | answer: workspace 126 | }; 127 | } 128 | 129 | remembered.push({ 130 | guesses: guesses, 131 | count: 0, 132 | board: workspace 133 | }); 134 | } 135 | 136 | return { 137 | state: [], 138 | answer: null 139 | }; 140 | } 141 | 142 | function deduce(board) { 143 | while (true) { 144 | var stuck = true; 145 | var guess = null; 146 | var count = 0; // fill in any spots determined by direct conflicts 147 | 148 | var tuple1 = figurebits(board); 149 | var allowed = tuple1.allowed; 150 | var needed = tuple1.needed; 151 | 152 | for (var pos = 0; pos < 81; pos++) { 153 | if (board[pos] === null) { 154 | var numbers = listbits(allowed[pos]); 155 | 156 | if (numbers.length === 0) { 157 | return []; 158 | } else if (numbers.length === 1) { 159 | board[pos] = numbers[0]; 160 | stuck = false; 161 | } else if (stuck) { 162 | var t = numbers.map(function (val, key) { 163 | return { 164 | pos: pos, 165 | num: val 166 | }; 167 | }); 168 | var tuple2 = pickbetter(guess, count, t); 169 | guess = tuple2.guess; 170 | count = tuple2.count; 171 | } 172 | } 173 | } 174 | 175 | if (!stuck) { 176 | var tuple3 = figurebits(board); 177 | allowed = tuple3.allowed; 178 | needed = tuple3.needed; 179 | } // fill in any spots determined by elimination of other locations 180 | 181 | 182 | for (var axis = 0; axis < 3; axis++) { 183 | for (var x = 0; x < 9; x++) { 184 | var numbers = listbits(needed[axis * 9 + x]); 185 | 186 | for (var i = 0; i < numbers.length; i++) { 187 | var n = numbers[i]; 188 | var bit = 1 << n; 189 | var spots = []; 190 | 191 | for (var y = 0; y < 9; y++) { 192 | var pos = posfor(x, y, axis); 193 | 194 | if (allowed[pos] & bit) { 195 | spots.push(pos); 196 | } 197 | } 198 | 199 | if (spots.length === 0) { 200 | return []; 201 | } else if (spots.length === 1) { 202 | board[spots[0]] = n; 203 | stuck = false; 204 | } else if (stuck) { 205 | var t = spots.map(function (val, key) { 206 | return { 207 | pos: val, 208 | num: n 209 | }; 210 | }); 211 | var tuple4 = pickbetter(guess, count, t); 212 | guess = tuple4.guess; 213 | count = tuple4.count; 214 | } 215 | } 216 | } 217 | } 218 | 219 | if (stuck) { 220 | if (guess != null) { 221 | shuffleArray(guess); 222 | } 223 | 224 | return guess; 225 | } 226 | } 227 | } 228 | 229 | function figurebits(board) { 230 | var needed = []; 231 | var allowed = board.map(function (val, key) { 232 | return val === null ? 511 : 0; 233 | }, []); 234 | 235 | for (var axis = 0; axis < 3; axis++) { 236 | for (var x = 0; x < 9; x++) { 237 | var bits = axismissing(board, x, axis); 238 | needed.push(bits); 239 | 240 | for (var y = 0; y < 9; y++) { 241 | var pos = posfor(x, y, axis); 242 | allowed[pos] = allowed[pos] & bits; 243 | } 244 | } 245 | } 246 | 247 | return { 248 | allowed: allowed, 249 | needed: needed 250 | }; 251 | } 252 | 253 | function posfor(x, y, axis) { 254 | if (axis === undefined) { 255 | axis = 0; 256 | } 257 | 258 | if (axis === 0) { 259 | return x * 9 + y; 260 | } else if (axis === 1) { 261 | return y * 9 + x; 262 | } 263 | 264 | return [0, 3, 6, 27, 30, 33, 54, 57, 60][x] + [0, 1, 2, 9, 10, 11, 18, 19, 20][y]; 265 | } 266 | 267 | function axisfor(pos, axis) { 268 | if (axis === 0) { 269 | return Math.floor(pos / 9); 270 | } else if (axis === 1) { 271 | return pos % 9; 272 | } 273 | 274 | return Math.floor(pos / 27) * 3 + Math.floor(pos / 3) % 3; 275 | } 276 | 277 | function axismissing(board, x, axis) { 278 | var bits = 0; 279 | 280 | for (var y = 0; y < 9; y++) { 281 | var e = board[posfor(x, y, axis)]; 282 | 283 | if (e != null) { 284 | bits |= 1 << e; 285 | } 286 | } 287 | 288 | return 511 ^ bits; 289 | } 290 | 291 | function listbits(bits) { 292 | var list = []; 293 | 294 | for (var y = 0; y < 9; y++) { 295 | if ((bits & 1 << y) != 0) { 296 | list.push(y); 297 | } 298 | } 299 | 300 | return list; 301 | } 302 | 303 | function allowed(board, pos) { 304 | var bits = 511; 305 | 306 | for (var axis = 0; axis < 3; axis++) { 307 | var x = axisfor(pos, axis); 308 | bits = bits & axismissing(board, x, axis); 309 | } 310 | 311 | return bits; 312 | } // TODO: make sure callers utilize the return value correctly 313 | 314 | 315 | function pickbetter(b, c, t) { 316 | if (b === null || t.length < b.length) { 317 | return { 318 | guess: t, 319 | count: 1 320 | }; 321 | } else if (t.length > b.length) { 322 | return { 323 | guess: b, 324 | count: c 325 | }; 326 | } else if (randomInt(c) === 0) { 327 | return { 328 | guess: t, 329 | count: c + 1 330 | }; 331 | } 332 | 333 | return { 334 | guess: b, 335 | count: c + 1 336 | }; 337 | } 338 | 339 | function boardforentries(entries) { 340 | var board = Array(81).fill(null); 341 | 342 | for (var i = 0; i < entries.length; i++) { 343 | var item = entries[i]; 344 | var pos = item.pos; 345 | var num = item.num; 346 | board[pos] = num; 347 | } 348 | 349 | return board; 350 | } 351 | 352 | function boardmatches(b1, b2) { 353 | for (var i = 0; i < 81; i++) { 354 | if (b1[i] != b2[i]) { 355 | return false; 356 | } 357 | } 358 | 359 | return true; 360 | } 361 | 362 | function randomInt(max) { 363 | return Math.floor(Math.random() * (max + 1)); 364 | } 365 | 366 | function shuffleArray(original) { 367 | // Swap each element with another randomly selected one. 368 | for (var i = original.length - 1; i > 0; i--) { 369 | var j = randomInt(i); 370 | var contents = original[i]; 371 | original[i] = original[j]; 372 | original[j] = contents; 373 | } 374 | } 375 | 376 | function removeElement(array, from, to) { 377 | var rest = array.slice((to || from) + 1 || array.length); 378 | array.length = from < 0 ? array.length + from : from; 379 | return array.push.apply(array, rest); 380 | } 381 | 382 | ; 383 | module.exports = { 384 | makepuzzle: function () { 385 | return makepuzzle(solvepuzzle(Array(81).fill(null))); 386 | }, 387 | solvepuzzle: solvepuzzle, 388 | ratepuzzle: ratepuzzle, 389 | posfor: posfor 390 | }; 391 | -------------------------------------------------------------------------------- /dist-web/index.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"index.js","sources":["../dist-src/index.js"],"sourcesContent":["// Sudoku Generator and Solver for node.js\n// Copyright (c) 2011 Blagovest Dachev. All rights reserved.\n//\n// This is a port of David Bau's python implementation:\n// http://davidbau.com/archives/2006/09/04/sudoku_generator.html\nfunction makepuzzle(board) {\n var puzzle = [];\n var deduced = Array(81).fill(null);\n var order = [...Array(81).keys()];\n shuffleArray(order);\n\n for (var i = 0; i < order.length; i++) {\n var pos = order[i];\n\n if (deduced[pos] === null) {\n puzzle.push({\n pos: pos,\n num: board[pos]\n });\n deduced[pos] = board[pos];\n deduce(deduced);\n }\n }\n\n shuffleArray(puzzle);\n\n for (var i = puzzle.length - 1; i >= 0; i--) {\n var e = puzzle[i];\n removeElement(puzzle, i);\n var rating = checkpuzzle(boardforentries(puzzle), board);\n\n if (rating === -1) {\n puzzle.push(e);\n }\n }\n\n return boardforentries(puzzle);\n}\n\nfunction ratepuzzle(puzzle, samples) {\n var total = 0;\n\n for (var i = 0; i < samples; i++) {\n var tuple = solveboard(puzzle);\n\n if (tuple.answer === null) {\n return -1;\n }\n\n total += tuple.state.length;\n }\n\n return total / samples;\n}\n\nfunction checkpuzzle(puzzle, board) {\n if (board === undefined) {\n board = null;\n }\n\n var tuple1 = solveboard(puzzle);\n\n if (tuple1.answer === null) {\n return -1;\n }\n\n if (board != null && !boardmatches(board, tuple1.answer)) {\n return -1;\n }\n\n var difficulty = tuple1.state.length;\n var tuple2 = solvenext(tuple1.state);\n\n if (tuple2.answer != null) {\n return -1;\n }\n\n return difficulty;\n}\n\nfunction solvepuzzle(board) {\n return solveboard(board).answer;\n}\n\nfunction solveboard(original) {\n var board = [].concat(original);\n var guesses = deduce(board);\n\n if (guesses === null) {\n return {\n state: [],\n answer: board\n };\n }\n\n var track = [{\n guesses: guesses,\n count: 0,\n board: board\n }];\n return solvenext(track);\n}\n\nfunction solvenext(remembered) {\n while (remembered.length > 0) {\n var tuple1 = remembered.pop();\n\n if (tuple1.count >= tuple1.guesses.length) {\n continue;\n }\n\n remembered.push({\n guesses: tuple1.guesses,\n count: tuple1.count + 1,\n board: tuple1.board\n });\n var workspace = [].concat(tuple1.board);\n var tuple2 = tuple1.guesses[tuple1.count];\n workspace[tuple2.pos] = tuple2.num;\n var guesses = deduce(workspace);\n\n if (guesses === null) {\n return {\n state: remembered,\n answer: workspace\n };\n }\n\n remembered.push({\n guesses: guesses,\n count: 0,\n board: workspace\n });\n }\n\n return {\n state: [],\n answer: null\n };\n}\n\nfunction deduce(board) {\n while (true) {\n var stuck = true;\n var guess = null;\n var count = 0; // fill in any spots determined by direct conflicts\n\n var tuple1 = figurebits(board);\n var allowed = tuple1.allowed;\n var needed = tuple1.needed;\n\n for (var pos = 0; pos < 81; pos++) {\n if (board[pos] === null) {\n var numbers = listbits(allowed[pos]);\n\n if (numbers.length === 0) {\n return [];\n } else if (numbers.length === 1) {\n board[pos] = numbers[0];\n stuck = false;\n } else if (stuck) {\n var t = numbers.map(function (val, key) {\n return {\n pos: pos,\n num: val\n };\n });\n var tuple2 = pickbetter(guess, count, t);\n guess = tuple2.guess;\n count = tuple2.count;\n }\n }\n }\n\n if (!stuck) {\n var tuple3 = figurebits(board);\n allowed = tuple3.allowed;\n needed = tuple3.needed;\n } // fill in any spots determined by elimination of other locations\n\n\n for (var axis = 0; axis < 3; axis++) {\n for (var x = 0; x < 9; x++) {\n var numbers = listbits(needed[axis * 9 + x]);\n\n for (var i = 0; i < numbers.length; i++) {\n var n = numbers[i];\n var bit = 1 << n;\n var spots = [];\n\n for (var y = 0; y < 9; y++) {\n var pos = posfor(x, y, axis);\n\n if (allowed[pos] & bit) {\n spots.push(pos);\n }\n }\n\n if (spots.length === 0) {\n return [];\n } else if (spots.length === 1) {\n board[spots[0]] = n;\n stuck = false;\n } else if (stuck) {\n var t = spots.map(function (val, key) {\n return {\n pos: val,\n num: n\n };\n });\n var tuple4 = pickbetter(guess, count, t);\n guess = tuple4.guess;\n count = tuple4.count;\n }\n }\n }\n }\n\n if (stuck) {\n if (guess != null) {\n shuffleArray(guess);\n }\n\n return guess;\n }\n }\n}\n\nfunction figurebits(board) {\n var needed = [];\n var allowed = board.map(function (val, key) {\n return val === null ? 511 : 0;\n }, []);\n\n for (var axis = 0; axis < 3; axis++) {\n for (var x = 0; x < 9; x++) {\n var bits = axismissing(board, x, axis);\n needed.push(bits);\n\n for (var y = 0; y < 9; y++) {\n var pos = posfor(x, y, axis);\n allowed[pos] = allowed[pos] & bits;\n }\n }\n }\n\n return {\n allowed: allowed,\n needed: needed\n };\n}\n\nfunction posfor(x, y, axis) {\n if (axis === undefined) {\n axis = 0;\n }\n\n if (axis === 0) {\n return x * 9 + y;\n } else if (axis === 1) {\n return y * 9 + x;\n }\n\n return [0, 3, 6, 27, 30, 33, 54, 57, 60][x] + [0, 1, 2, 9, 10, 11, 18, 19, 20][y];\n}\n\nfunction axisfor(pos, axis) {\n if (axis === 0) {\n return Math.floor(pos / 9);\n } else if (axis === 1) {\n return pos % 9;\n }\n\n return Math.floor(pos / 27) * 3 + Math.floor(pos / 3) % 3;\n}\n\nfunction axismissing(board, x, axis) {\n var bits = 0;\n\n for (var y = 0; y < 9; y++) {\n var e = board[posfor(x, y, axis)];\n\n if (e != null) {\n bits |= 1 << e;\n }\n }\n\n return 511 ^ bits;\n}\n\nfunction listbits(bits) {\n var list = [];\n\n for (var y = 0; y < 9; y++) {\n if ((bits & 1 << y) != 0) {\n list.push(y);\n }\n }\n\n return list;\n}\n\nfunction allowed(board, pos) {\n var bits = 511;\n\n for (var axis = 0; axis < 3; axis++) {\n var x = axisfor(pos, axis);\n bits = bits & axismissing(board, x, axis);\n }\n\n return bits;\n} // TODO: make sure callers utilize the return value correctly\n\n\nfunction pickbetter(b, c, t) {\n if (b === null || t.length < b.length) {\n return {\n guess: t,\n count: 1\n };\n } else if (t.length > b.length) {\n return {\n guess: b,\n count: c\n };\n } else if (randomInt(c) === 0) {\n return {\n guess: t,\n count: c + 1\n };\n }\n\n return {\n guess: b,\n count: c + 1\n };\n}\n\nfunction boardforentries(entries) {\n var board = Array(81).fill(null);\n\n for (var i = 0; i < entries.length; i++) {\n var item = entries[i];\n var pos = item.pos;\n var num = item.num;\n board[pos] = num;\n }\n\n return board;\n}\n\nfunction boardmatches(b1, b2) {\n for (var i = 0; i < 81; i++) {\n if (b1[i] != b2[i]) {\n return false;\n }\n }\n\n return true;\n}\n\nfunction randomInt(max) {\n return Math.floor(Math.random() * (max + 1));\n}\n\nfunction shuffleArray(original) {\n // Swap each element with another randomly selected one.\n for (var i = 0; i < original.length; i++) {\n var j = i;\n\n while (j === i) {\n j = Math.floor(Math.random() * original.length);\n }\n\n var contents = original[i];\n original[i] = original[j];\n original[j] = contents;\n }\n}\n\nfunction removeElement(array, from, to) {\n var rest = array.slice((to || from) + 1 || array.length);\n array.length = from < 0 ? array.length + from : from;\n return array.push.apply(array, rest);\n}\n\n;\nmodule.exports = {\n makepuzzle: function () {\n return makepuzzle(solvepuzzle(Array(81).fill(null)));\n },\n solvepuzzle: solvepuzzle,\n ratepuzzle: ratepuzzle,\n posfor: posfor\n};"],"names":[],"mappings":"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"} -------------------------------------------------------------------------------- /dist-node/index.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"index.js","sources":["../dist-src/index.js"],"sourcesContent":["// Sudoku Generator and Solver for node.js\n// Copyright (c) 2011 Blagovest Dachev. All rights reserved.\n//\n// This is a port of David Bau's python implementation:\n// http://davidbau.com/archives/2006/09/04/sudoku_generator.html\nfunction makepuzzle(board) {\n var puzzle = [];\n var deduced = Array(81).fill(null);\n var order = [...Array(81).keys()];\n shuffleArray(order);\n\n for (var i = 0; i < order.length; i++) {\n var pos = order[i];\n\n if (deduced[pos] === null) {\n puzzle.push({\n pos: pos,\n num: board[pos]\n });\n deduced[pos] = board[pos];\n deduce(deduced);\n }\n }\n\n shuffleArray(puzzle);\n\n for (var i = puzzle.length - 1; i >= 0; i--) {\n var e = puzzle[i];\n removeElement(puzzle, i);\n var rating = checkpuzzle(boardforentries(puzzle), board);\n\n if (rating === -1) {\n puzzle.push(e);\n }\n }\n\n return boardforentries(puzzle);\n}\n\nfunction ratepuzzle(puzzle, samples) {\n var total = 0;\n\n for (var i = 0; i < samples; i++) {\n var tuple = solveboard(puzzle);\n\n if (tuple.answer === null) {\n return -1;\n }\n\n total += tuple.state.length;\n }\n\n return total / samples;\n}\n\nfunction checkpuzzle(puzzle, board) {\n if (board === undefined) {\n board = null;\n }\n\n var tuple1 = solveboard(puzzle);\n\n if (tuple1.answer === null) {\n return -1;\n }\n\n if (board != null && !boardmatches(board, tuple1.answer)) {\n return -1;\n }\n\n var difficulty = tuple1.state.length;\n var tuple2 = solvenext(tuple1.state);\n\n if (tuple2.answer != null) {\n return -1;\n }\n\n return difficulty;\n}\n\nfunction solvepuzzle(board) {\n return solveboard(board).answer;\n}\n\nfunction solveboard(original) {\n var board = [].concat(original);\n var guesses = deduce(board);\n\n if (guesses === null) {\n return {\n state: [],\n answer: board\n };\n }\n\n var track = [{\n guesses: guesses,\n count: 0,\n board: board\n }];\n return solvenext(track);\n}\n\nfunction solvenext(remembered) {\n while (remembered.length > 0) {\n var tuple1 = remembered.pop();\n\n if (tuple1.count >= tuple1.guesses.length) {\n continue;\n }\n\n remembered.push({\n guesses: tuple1.guesses,\n count: tuple1.count + 1,\n board: tuple1.board\n });\n var workspace = [].concat(tuple1.board);\n var tuple2 = tuple1.guesses[tuple1.count];\n workspace[tuple2.pos] = tuple2.num;\n var guesses = deduce(workspace);\n\n if (guesses === null) {\n return {\n state: remembered,\n answer: workspace\n };\n }\n\n remembered.push({\n guesses: guesses,\n count: 0,\n board: workspace\n });\n }\n\n return {\n state: [],\n answer: null\n };\n}\n\nfunction deduce(board) {\n while (true) {\n var stuck = true;\n var guess = null;\n var count = 0; // fill in any spots determined by direct conflicts\n\n var tuple1 = figurebits(board);\n var allowed = tuple1.allowed;\n var needed = tuple1.needed;\n\n for (var pos = 0; pos < 81; pos++) {\n if (board[pos] === null) {\n var numbers = listbits(allowed[pos]);\n\n if (numbers.length === 0) {\n return [];\n } else if (numbers.length === 1) {\n board[pos] = numbers[0];\n stuck = false;\n } else if (stuck) {\n var t = numbers.map(function (val, key) {\n return {\n pos: pos,\n num: val\n };\n });\n var tuple2 = pickbetter(guess, count, t);\n guess = tuple2.guess;\n count = tuple2.count;\n }\n }\n }\n\n if (!stuck) {\n var tuple3 = figurebits(board);\n allowed = tuple3.allowed;\n needed = tuple3.needed;\n } // fill in any spots determined by elimination of other locations\n\n\n for (var axis = 0; axis < 3; axis++) {\n for (var x = 0; x < 9; x++) {\n var numbers = listbits(needed[axis * 9 + x]);\n\n for (var i = 0; i < numbers.length; i++) {\n var n = numbers[i];\n var bit = 1 << n;\n var spots = [];\n\n for (var y = 0; y < 9; y++) {\n var pos = posfor(x, y, axis);\n\n if (allowed[pos] & bit) {\n spots.push(pos);\n }\n }\n\n if (spots.length === 0) {\n return [];\n } else if (spots.length === 1) {\n board[spots[0]] = n;\n stuck = false;\n } else if (stuck) {\n var t = spots.map(function (val, key) {\n return {\n pos: val,\n num: n\n };\n });\n var tuple4 = pickbetter(guess, count, t);\n guess = tuple4.guess;\n count = tuple4.count;\n }\n }\n }\n }\n\n if (stuck) {\n if (guess != null) {\n shuffleArray(guess);\n }\n\n return guess;\n }\n }\n}\n\nfunction figurebits(board) {\n var needed = [];\n var allowed = board.map(function (val, key) {\n return val === null ? 511 : 0;\n }, []);\n\n for (var axis = 0; axis < 3; axis++) {\n for (var x = 0; x < 9; x++) {\n var bits = axismissing(board, x, axis);\n needed.push(bits);\n\n for (var y = 0; y < 9; y++) {\n var pos = posfor(x, y, axis);\n allowed[pos] = allowed[pos] & bits;\n }\n }\n }\n\n return {\n allowed: allowed,\n needed: needed\n };\n}\n\nfunction posfor(x, y, axis) {\n if (axis === undefined) {\n axis = 0;\n }\n\n if (axis === 0) {\n return x * 9 + y;\n } else if (axis === 1) {\n return y * 9 + x;\n }\n\n return [0, 3, 6, 27, 30, 33, 54, 57, 60][x] + [0, 1, 2, 9, 10, 11, 18, 19, 20][y];\n}\n\nfunction axisfor(pos, axis) {\n if (axis === 0) {\n return Math.floor(pos / 9);\n } else if (axis === 1) {\n return pos % 9;\n }\n\n return Math.floor(pos / 27) * 3 + Math.floor(pos / 3) % 3;\n}\n\nfunction axismissing(board, x, axis) {\n var bits = 0;\n\n for (var y = 0; y < 9; y++) {\n var e = board[posfor(x, y, axis)];\n\n if (e != null) {\n bits |= 1 << e;\n }\n }\n\n return 511 ^ bits;\n}\n\nfunction listbits(bits) {\n var list = [];\n\n for (var y = 0; y < 9; y++) {\n if ((bits & 1 << y) != 0) {\n list.push(y);\n }\n }\n\n return list;\n}\n\nfunction allowed(board, pos) {\n var bits = 511;\n\n for (var axis = 0; axis < 3; axis++) {\n var x = axisfor(pos, axis);\n bits = bits & axismissing(board, x, axis);\n }\n\n return bits;\n} // TODO: make sure callers utilize the return value correctly\n\n\nfunction pickbetter(b, c, t) {\n if (b === null || t.length < b.length) {\n return {\n guess: t,\n count: 1\n };\n } else if (t.length > b.length) {\n return {\n guess: b,\n count: c\n };\n } else if (randomInt(c) === 0) {\n return {\n guess: t,\n count: c + 1\n };\n }\n\n return {\n guess: b,\n count: c + 1\n };\n}\n\nfunction boardforentries(entries) {\n var board = Array(81).fill(null);\n\n for (var i = 0; i < entries.length; i++) {\n var item = entries[i];\n var pos = item.pos;\n var num = item.num;\n board[pos] = num;\n }\n\n return board;\n}\n\nfunction boardmatches(b1, b2) {\n for (var i = 0; i < 81; i++) {\n if (b1[i] != b2[i]) {\n return false;\n }\n }\n\n return true;\n}\n\nfunction randomInt(max) {\n return Math.floor(Math.random() * (max + 1));\n}\n\nfunction shuffleArray(original) {\n // Swap each element with another randomly selected one.\n for (var i = 0; i < original.length; i++) {\n var j = i;\n\n while (j === i) {\n j = Math.floor(Math.random() * original.length);\n }\n\n var contents = original[i];\n original[i] = original[j];\n original[j] = contents;\n }\n}\n\nfunction removeElement(array, from, to) {\n var rest = array.slice((to || from) + 1 || array.length);\n array.length = from < 0 ? array.length + from : from;\n return array.push.apply(array, rest);\n}\n\n;\nmodule.exports = {\n makepuzzle: function () {\n return makepuzzle(solvepuzzle(Array(81).fill(null)));\n },\n solvepuzzle: solvepuzzle,\n ratepuzzle: ratepuzzle,\n posfor: posfor\n};"],"names":["makepuzzle","board","puzzle","deduced","Array","fill","order","keys","shuffleArray","i","length","pos","push","num","deduce","e","removeElement","rating","checkpuzzle","boardforentries","ratepuzzle","samples","total","tuple","solveboard","answer","state","undefined","tuple1","boardmatches","difficulty","tuple2","solvenext","solvepuzzle","original","concat","guesses","track","count","remembered","pop","workspace","stuck","guess","figurebits","allowed","needed","numbers","listbits","t","map","val","key","pickbetter","tuple3","axis","x","n","bit","spots","y","posfor","tuple4","bits","axismissing","list","b","c","randomInt","entries","item","b1","b2","max","Math","floor","random","j","contents","array","from","to","rest","slice","apply","module","exports"],"mappings":"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"} --------------------------------------------------------------------------------