LoginSignup
3
1

More than 5 years have passed since last update.

サクラエディタで数独を解く

Last updated at Posted at 2019-03-05

環境

サクラエディタ 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に変換される文字列なら"?"じゃなく、"_"とかでも良い。)

image.png

マクロ実行。(「共通設定」→「マクロ」から登録でも良い)

変な入力でマクロが暴走しても責任持てないので実行は自己責任で

image.png

10秒ぐらい掛かるので待つ。

image.png

自動で問題が解ける。

なお、アルゴリズム上、入力ミスとかで複数の解があるような入力をすると最初に見つけた解が出る。

3
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
1