環境
サクラエディタ Ver. 2.2.0.1
Windows 10
数独ソルバーマクロ
動機は謎。
業務で数独を解く必要に迫られた場合にどうぞ。
※一応言っておくと私は業務時間中に数独を解いたりはしていない。
前に普通にJavaScriptで書いたのをサクラエディタのマクロで使えるJScriptに移植。
JScriptだと文字列の添え字アクセス出来ないんだろうか…?(charAt()で代用した)
長いので、実用の項目をクリックしてスキップ。
sudoku_solver.js
function idxToBlock(c, r) {
return (r / 3 | 0) * 3 + (c / 3 | 0);
};
function check(arr) {
var chist = [], rhist = [], bhist = [];
for (var i = 0; i < 9; ++i) {
//chist[i] = new Array(9).fill(0);
//rhist[i] = new Array(9).fill(0);
//bhist[i] = new Array(9).fill(0);
chist[i] = new Array(9);
rhist[i] = new Array(9);
bhist[i] = new Array(9);
for (var j = 0; j < 9; ++j) {
chist[i][j] = 0;
bhist[i][j] = 0;
rhist[i][j] = 0;
}
}
var maxcnt = 0;
for (var r = 0; r < 9; ++r) {
for (var c = 0; c < 9; ++c) {
var val = arr[r * 9 + c] - 1;
if (val >= 0) {
maxcnt = Math.max(++chist[c][val], maxcnt);
maxcnt = Math.max(++rhist[r][val], maxcnt);
maxcnt = Math.max(++bhist[idxToBlock(c, r)][val], maxcnt);
}
}
}
var ret = {
chist: chist,
rhist: rhist,
bhist: bhist,
valid: (maxcnt >= 2) ? false : true
};
return ret;
};
function solve(inArr){
var Q = [], ans = null;
Q.push(inArr.concat());
while ( Q.length > 0 ) {
var arr = Q.pop(), i = 0;
if ( false == check(arr).valid ){
continue;
}
for (i = 0; i < 9 * 9; ++i) {
if ( 0 === arr[i] ) {
for (var j = 1; j <= 9; ++j) {
arr[i] = j;
Q.push(arr.concat());
}
break;
}
}
if ( 9 * 9 === i ) {
ans = arr;
break;
}
}
if( ans ){
return ans;
}
else {
return null;
}
}
// ここからエディタマクロ
var text = Editor.GetSelectedString(0);
lines = text.split("\n");
var arr = [];
for( var i = 0; i < lines.length && i < 9; ++i ) {
for( var j = 0; j < lines[i].length && j < 9; ++j ) {
var num = parseInt(lines[i].charAt(j));
if( "?" === lines[i].charAt(j) ){
arr[ i * 9 + j ] = 0;
}
else if( 0 <= num && num <= 9 ){
arr[ i * 9 + j ] = num;
}
else{
arr[ i * 9 + j ] = 0;
}
}
}
var ans = solve(arr);
var outText = "";
for(var i = 0; i < 9; ++i){
for(var j = 0; j < 9; ++j){
outText += ans[ i * 9 + j ]
}
outText += "\n"
}
Editor.InsText( outText );
実用
数独の問題の数字を入力し、以下のように文字列選択する。
(コードを見ればわかるが、parseIntで0に変換される文字列なら"?"じゃなく、"_"とかでも良い。)
マクロ実行。(「共通設定」→「マクロ」から登録でも良い)
変な入力でマクロが暴走しても責任持てないので実行は自己責任で
10秒ぐらい掛かるので待つ。
自動で問題が解ける。
なお、アルゴリズム上、入力ミスとかで複数の解があるような入力をすると最初に見つけた解が出る。