Help us understand the problem. What is going on with this article?

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

More than 1 year has passed since last update.

環境

サクラエディタ 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

自動で問題が解ける。

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

ltzz
仕事ではバックエンドしてます。元組み込み屋。いろいろ。
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away