第30講 数独(ナンバープレイス)問題解決ソフトVer.1の制作
(数独(ナンバープレイス)問題作成ソフトに挑戦する人は☆☆)
第16話 数独(ナンバープレイス)問題解決ソフトVer.1の完成
コード変更部分
・
・
・
void f(char g){
if(s==2)return;
char
x,y;
x=g%9;
y=g/9;
char h,i,j,k,k1,k2,ii,iii;
if(a[y][x]>0){
if(g+1<81){
f(g+1);
}
else{
k1=0;
for(i=0;i<13;i++){
if(i%4==0){
k1++;
for(j=0;j<13;j++)dataGridView1[j,i+14]->Value=L"*";
}
if(i%4>0){
k2=0;
for(j=0;j<13;j++){
if(j%4==0){
dataGridView1[j,i+14]->Value=L"*";
k2++;
}
if(j%4>0){
dataGridView1[j,i+14]->Value=a[i-k1][j-k2];
}
}
}
}
s++;
if(s==2)return;
}
}
if(a[y][x]==0){
ii=rand()%9;
for(i=1;i<10;i++){
iii=(i+ii)%9+1;
h=1;
if(x>0){
for(j=0;j<x;j++){
if(a[y][j]==iii){
h=0;
break;
}
}
}
if(h==1){
if(x+1<8){
for(j=x+1;j<9;j++){
if(a[y][j]==iii){
h=0;
break;
}
}
}
}
if(h==1){
if(y>0){
for(j=0;j<y;j++){
if(a[j][x]==iii){
h=0;
break;
}
}
}
}
if(h==1){
if(y+1<8){
for(j=y+1;j<9;j++){
if(a[j][x]==iii){
h=0;
break;
}
}
}
}
if(h==1){
for(j=0;j<3;j++){
if(j!=ya){
for(k=0;k<3;k++){
if(k!=xa){
if(a[3*ys+j][3*xs+k]>0){
if(a[3*ys+j][3*xs+k]==iii){
h=0;
break;
}
}
}
}
if(h==0)break;
}
}
}
if(h==1){
a[y][x]=iii;
if(g+1<81){
f(g+1);
}
else{
k1=0;
for(i=0;i<13;i++){
if(i%4==0){
k1++;
for(j=0;j<13;j++)dataGridView1[j,i+14]->Value=L"*";
}
if(i%4>0){
k2=0;
for(j=0;j<13;j++){
if(j%4==0){
dataGridView1[j,i+14]->Value=L"*";
k2++;
}
if(j%4>0){
dataGridView1[j,i+14]->Value=a[i-k1][j-k2];
}
}
}
}
s++;
if(s==2)return;
}
a[y][x]=0;
}
}
}
}
・
・
・
解説
iをiii(=(ii+i)%9+1さらにiiはrand()%9で9未満のランダムな正の整数)に変更するだけで、
変更前にには1時間かけても解けなかった問題が、なんと0.004秒程度で解けてしまいました。
プログラムとは、本当に面白いものです。
ほんのちょっとした小改良で、3600÷0.004=9000000倍の速さになってしまいました。
実験を途中で打ち切ってしまいましたから、改良前は1時間と仮定してです。
実際には、1時間では解けないでしょうから、それ以上でしょう。
900万倍以上の速さになったのです。
ですが、今度はの方の問題を解くのに52秒も要してしまいました。
22秒から52秒になってしまったのです。
もちろん、rand();を無駄打ちしたり、srand(0);によってシード値を変更すればもっと短い時間で出来るようになるでしょう。
シード値とは、srand(・);の括弧内の数値です。シード値を変えると、乱数系列自体が変わります。
後で数独(ナンバープレイス)問題作成ソフトの制作に挑戦しますが、シード値を変更しないと毎回同じ問題を作ってしまいます。
毎回異なる問題を作らせるためには、srand(static_cast<unsigned int>(time(0)));とすればよいのです。
static_cast<unsigned int>(time(0))は現在の時間を、整数に変更したものです。
実行ボタンを押すタイミングは毎回ずれますから、決して同じ問題を作ってしまうことはありません。
同じ問題を作ってしまう確率は1/1京(兆の1万倍)より遙かに小さいので、実質0です。
シード値を変更すれば、が0.001秒以内で解けるようになる可能性はありますが、
すべての問題に対して、0.001秒以内で解けるようにするためには、そのような小手先の変更ではだめです。
どんな問題でも0.001秒以内で解けるソフトを作るのが目的です。
したがって、抜本的な改良が必要になってきます。
Verの変更が必要なわけです。
Ver.2では、問題全体構造解析を付け加え、そして問題全体構造解析に基づいた番号付け変更を行います。
Ver.1では、
* | 0 | 1 | 2 | 3 | 4 | * | 5 | 6 |
7 | 8 | * | * | 9 | * | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | * | 27 | 28 | 29 |
30 | 31 | * | 32 | 33 | 34 | 35 | 36 | * |
37 | 38 | 39 | 40 | * | * | 41 | * | 42 |
43 | 44 | 45 | * | 46 | 47 | 48 | * | * |
* | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 |
* | 57 | 58 | * | 59 | 60 | 61 | 62 | 63 |
の順にセルに値を入れていっています。これだと20秒以上かかってしまうわけですが、問題全体構造解析を行い、
入力順番を次にのように変更すると
* | 48 | 21 | 1 | 22 | 7 | * | 23 | 24 |
2 | 25 | * | * | 26 | * | 27 | 8 | 28 |
29 | 59 | 49 | 30 | 50 | 31 | 63 | 51 | 52 |
32 | 60 | 53 | 3 | 54 | * | 33 | 55 | 34 |
9 | 61 | * | 0 | 10 | 11 | 35 | 56 | * |
12 | 36 | 13 | 4 | * | * | 37 | * | 14 |
5 | 15 | 16 | * | 17 | 6 | 38 | * | * |
* | 62 | 39 | 40 | 41 | 18 | 42 | 43 | 57 |
* | 58 | 19 | * | 44 | 20 | 45 | 46 | 47 |
1秒もかからず解けるようになります。問題全体構造解析とは、次のものです。
* | 6 | 5 | 3 | 5 | 4 | * | 5 | 5 |
3 | 5 | * | * | 5 | * | 5 | 4 | 5 |
5 | 7 | 6 | 5 | 6 | 5 | 8 | 6 | 6 |
5 | 7 | 6 | 3 | 6 | * | 5 | 6 | 5 |
4 | 7 | * | 1 | 4 | 4 | 5 | 6 | * |
4 | 5 | 4 | 3 | * | * | 5 | * | 4 |
3 | 4 | 4 | * | 4 | 3 | 5 | * | * |
* | 7 | 5 | 5 | 5 | 4 | 5 | 5 | 6 |
* | 6 | 4 | * | 5 | 4 | 5 | 5 | 5 |
いったいこれは何を意味するのでしょうか。
第15話へ 第31講第1話へ
VC++講義第1部へ
vb講義へ
VB講義基礎へ
初心者のための世界で一番わかりやすいVisual C++入門基礎講座
初心者のための世界で一番わかりやすいVisual
Basic入門基礎講座
初心者のための世界で一番わかりやすいVBA入門講義(基礎から応用まで)