パズルを解く考え方
問題の形のままで解く方法にすると難しくなるので一度表にしてから計算します。
まず、すべてのマスに対応する表を作り1〜9の列を作りフラッグとして1を入れます、表には縦列の番号、横列の番号、グループごとの番号を作ります。
(図1)
ヒントの番号を読み(たとえば4とします)、指令MPUを使いその番号の縦列、横列、グループ内の場所をフラッグ0にします。
すべてのヒント番号をMPUし終わったらSTを使って横番号の中で1入る可能性が1つの番号を探し出し(図4)ヒントの時と同様にMPUしてフラッグを0にします((3)。
同様に縦番号やグループ番号でもSTをしてMPUしフラッグを0にしていきます、横番号の後に縦番号、グループ番号とMPUで消すとフラッグの数が減るのでまた横番号からまた始めます、フラッグの合計が変わらなくなるまでこれを繰り返します、合計が0にならない時は解答が求められなかった時ですが、その時も半端のまま表示します。
使用方法
プログラムを起動すると入力用の表が現れます、数字を入力してください。終わったらEscキーを押すと解答を計算します。
同様の問題が載った本を買ってきて試してみました、初級・中級は解けたのですが上級問題はこのプログラムでは解けませんでした、さらなるアルゴリズムを考えないとダメなようです、また、本には25*25のような大きな物や、9*9がいくつか組み合わさった物などいろいろ載っています、組み合わせて考えればより良いものが出来ると思います。
<PAZ> SET;S;M;1;120;;Y; /* 6行目まで計算表と記入表の作成 */ O;回答表;4;横;4;縦;4;G;4;基;4;答;3*9;1;2;3;4;5;6;7;8;9;4;計;ESC; IR;S;4;82;NUM/C;;C;1;;1;0.11;;C;2;5;1;1/9/C;ESC; ATR;N;DF0;1; DR;4;; FILL;1;A;6,15;Y; FOR X1=0 TO 80;LET [X1+4,3]=NUM$(((X1/27)*3)+(X1MOD9)/3+1);NEXT S;O;記入表;3*9;;;;;;;;;;ESC;IR;S;4;9;DRL/C;C;1/4/7;C;N;R;7/10;ESC; W;4;2; /* 手動入力 */ DISP OPEN(10,19,39,21);DISP [2,1],"入力終了はESCを押す" ENTRY; ESC; DISP CLOSE; DRL;D;S; FOR X1=1 TO 9 ; FOR X2=1 TO 9; LET X10=VAL({X1+3,X2}); /* X10=ヒントの読み込み */ IF X10=0 THEN GOTO $NE1; /* ヒント番号がない時は戻る */ LET X20=(X1*9)+X2-6 /* 計算表でのヒントの位置を計算 */ LET [X20,4]=NUM$(X10); /* ヒント数字を表に書き込み */ LET X21=VAL([X20,1]); /* X21=横行番号の読み込み */ LET X22=VAL([X20,2]); /* X22=縦列番号の読み込み */ LET X23=VAL([X20,3]); /* X23=グループ番号の読み込み */ LET X11=X10+5; /* 表上のヒント番号列 */ MPU;;;C1=%X21 OR C2=%X22 OR C3=%X23;C%X11*0=C%X11;E;; FILL;0;%X20;6,14;; /* MPUとFILLでフラッグを0にする */ $NE1:CLEAR X10,25; NEXT; NEXT; $SAI:SORT;;@横;A/N;@縦;A/N;;; ST;;S;1;;;6,14;;; S;GOSUB ERS SORT;;@縦;A/N;@横;A/N;;; ST;;S;2;;;6,14;;; S;GOSUB ERS SORT;;@G;A/N;@横;A/N;@縦;A/N;;; ST;;S;3;;;6,14;;; S;GOSUB ERS CAL/C;C6+C14=/C15;C[15];R4+RT=/R4;ESC;/* 残っているフラッグの合計 */ IF X12=VAL([4,@計 ]) THEN GOTO $表示; /* 変化が無くなったら表示へ */ LET X12=VAL([4,@計 ]); /* 合計数の記憶 */ GOTO $SAI; /* 解答計算のし直しへ */ $表示:SORT;;@横;A/N;@縦;A/N;;; S; O;記入表;3*9;;;;;;;;;;ESC; IR;S;4;9; /* 解答表の作成 */ FOR X1=1 TO 9; FOR X2=1 TO 9; LET X20=(X1*9)+X2-6 /* 計算表と解答表の位置計算 */ IF {X20,@基 }="" THEN GOTO $答1; /* 答えの場合は 答1へ */ LET [X1+3,X2]={X20,@基 }; COL;C;%X1+3;%X2; GOTO $NE2; $答1: LET [X1+3,X2]={X20,@答 }; $NE2:NEXT;NEXT; DRL/C;C;1/4/7;C;N;R;7/10;ESC; /* 見やすくする為の線引き */ STOP <ERS> /* 解答用サブルーチン */ FOR X1=1 TO 9; /* STされたサブバッファの表から */ FOR X2=1 TO 9; /* 1の場所を探す */ IF {X1+3,X2+5}="1" THEN GOTO $ARI;/* あったら $ARI へ */ NEXT; GOTO $NE4; $ARI:FOR X3=1 TO 9; /* 表の中から1の場所を探す */ IF [X1*9-6+X3,X2+5 ]="0" THEN GOTO $NE3; LET X20=X1*9-6+X3; /* 計算表の答えの位置を計算 */ LET [X20,5]=NUM$(X2); /* 答えを書き込む */ LET X21=VAL([X20,1]); /* x21=横行番号 */ LET X22=VAL([X20,2]); /* x22=縦列番号 */ LET X23=VAL([X20,3]); /* x23=グループ番号 */ LET X11=X2+5; /* 表上の答え番号列 */ MPU;;;C1=%X21 OR C2=%X22 OR C3=%X23;C%X11*0=C%X11;E;; FILL;0;%X20;6,14;; /* MPUとFILLでフラッグを0にする */ $NE3:NEXT; $NE4:NEXT; RETURN; STOP
回答箱のプログラムがプログラム集に収録されています。 |
□