プログラムの実行結果は以下の通り。
た は さ な か あ な か あ た は さ あ さ は か な た か な た あ さ は さ た な は あ か は あ か さ た な
プログラムのソースは以下の通り。
#include "puzutl.h"
cstring food[] = { // 食材
"??", // dummy
"あ", // 1:あわび
"か", // 2:かに
"さ", // 3:さけ
"た", // 4:たい
"な", // 5:なっとう
"は", // 6:はまぐり
};
const int M = 6;
int mat[M][M] = {
{ 0, 0, 3, 0, 0, 0},
{ 0, 2, 0, 4, 0, 0},
{ 1, 0, 0, 0, 5, 0},
{ 0, 5, 0, 0, 0, 6},
{ 0, 0, 5, 0, 1, 0},
{ 0, 0, 0, 3, 0, 0}
};
YesNo check_ok( int row, int col, int val) // [row][col]に値valを設定できるか?
{
assert( mat[row][col] == 0); // 既に別の数字が設定されていたらプログラムに問題あり
// 同じ行内に同じ数字が無い
int xrow, xcol;
for( xcol=0; xcol< M; xcol++) {
if( xcol != col && mat[row][xcol] == val) return NO;
}
// 同じ列内に同じ数字が無い
for( xrow=0; xrow< M; xrow++) {
if( xrow != row && mat[xrow][col] == val) return NO;
}
// 3x2内に同じ数字が無い
int block_row, block_col;
block_row = row / 3 * 3;
block_col = col / 2 * 2;
for( xrow=0; xrow < 3; xrow++) {
for( xcol=0; xcol< 2; xcol++) {
if( mat[block_row+xrow][block_col+xcol] == val &&
!( block_row+xrow == row && block_col+xcol == col)) return NO;
}
}
// 2x3内に同じ数字が無い
block_row = row / 2 * 2;
block_col = col / 3 * 3;
for( xrow=0; xrow < 2; xrow++) {
for( xcol=0; xcol< 3; xcol++) {
if( mat[block_row+xrow][block_col+xcol] == val &&
!( block_row+xrow == row && block_col+xcol == col)) return NO;
}
}
return YES;
}
void dump() // 結果を出力する
{
int row, col;
for( row=0; row< M; row++) {
for( col=0; col< M; col++) {
ps( "%s ", food[mat[row][col]]); // 一応文字で出力する
}
ps( "\n");
}
}
void find( int pos) // 矩形の左上から探す
{
int row = pos / M;
int col = pos % M;
if( pos >= M*M) { // 見つかった?
dump(); // 見つかったよ
return;
}
if( mat[row][col]) { // 初期状態の数字?
find( pos+1); // 初期状態の数字はチェックせず次へ
return;
}
for( int val=1; val<= M; val++) { // [row][col]に1からMの数字を設定してみる
if( check_ok( row, col, val)) { // 置けるか?
mat[row][col] = val; // 置けた
find( pos+1); // 次は右隣に数字を置く
}
mat[row][col] = 0; // [row][col]に数字は置けなかった
}
}
int main( int argc, cstring argv[])
{
find( 0/*pos*/); // 左上から数字を置き始める
return 0;
}