第9講 関数の再帰的使用
第7話 関数の再帰的使用によるn次順列生成解説その4

コード再掲
#include<iostream>
using namespace std;
void f(int g);
void h();
int x[15],n;
long cn;
void main(){
   cout<<"何次順列を生成しますか?"<<endl;
   scanf("%d",&n);
   cout<<endl;
   cn=0;
   f(0];
   cout<<n<<"次順列が"<<cn<<"個生成されました。"<<endl;
}
void f(int g){
   int i,j;
   for(
i=1;i<n+1;i++){
     x[g]=
i;
     if(
g>0){
        for(j=0;j<g;j++){
          if(x[g]==x[j])goto tobi;
        }
     }
     if(
g+1<n){
        f(
g+1);
     }
     else{
        h();
        cn++;
     }
     tobi:;
   }
}
void h(){
   for(char i=0;i<n;i++)cout<<x[i]<<" ";
   cout<<endl;
}
b

解説

 0
2 1 3

これでf (2)の3回目の生は終わりを告げ、消滅しf (1)へと戻ります。

 0
2 1

そして、for文のi++により

 0
2 2

となりますが、これは
     if(g>0){
        for(j=0;j<g;j++){
          if(x[g]==x[j])goto tobi;
        }
     }

によってチェックされてしまい、
     if(g+1<n){
        f(
g+1);
     }
     else{
        h();
        cn++;
     }

無視されますから、for文のi++により

 0
2 3

今回は
     if(g>0){
        for(j=0;j<g;j++){
          if(x[g]==x[j])goto tobi;
        }
     }
の試験に合格して
     if(g+1<n){
        f(g+1);
     }
     else{
        h();
        cn++;
     }
命令が実施され、f (
2)の4回目の発生となります。

 0
2 3

   for(=1;<n+1;++){
     x[g]=
;
によって

 0
2 3 1

3つともセルの内容が違いますので、
試験
     if(g>0){
        for(j=0;j<g;j++){
          if(x[g]==x[j])goto tobi;
        }
     }
はあっさりクリアして
     if(g+1<n){
        f(g+1);
     }
     else{
        h();
        cn++;
     }
の否定側の
     else{
        h();
        cn++;
     }
の命令が遂行され、4個目の順列
qをコンソールにはき出します。
for文のi++により、

 0
2 3 2

となりますが、これは1番目のセルと3番目のセルが同じなので、
検査
     if(g>0){
        for(j=0;j<g;j++){
          if(x[g]==x[j])goto tobi;
        }
     }
に抵触して、

 0
2 3 3

となります。
今度は、2番目のセルと3番目のセルの内容が同じなので、やはり
     if(g>0){
        for(j=0;j<g;j++){
          if(x[g]==x[j])goto tobi;
        }
     }
の試験をクリアできません。
これで、f (
2)の4回目の生が寿命を迎え、消滅します。

 0
2 3

そして、セル番号1の世界も天寿を全うし、
2度目の消滅を体験します。

 0
2

for文のi++により

 0
3

となり、g=0なので試験
     if(g>0){
        for(j=0;j<g;j++){
          if(x[g]==x[j])goto tobi;
        }
     }
スルーされ、
     if(g+1<n){
        f(g+1);
     }
     else{
        h();
        cn++;
     }
の肯定側
     if(g+1<n){
        f(g+1);
     }
が実行されf (1)の3度目の誕生を迎えます。

 0
3

   for(=1;<n+1;++){
     x[g]=
;
によって、

 0
3 1

これは、2つのセルに内容が違いますので、
     if(g+1<n){
        f(g+1);
     }
     else{
        h();
        cn++;
     }
の肯定部分が遂行され、f (2)の5度目の生誕となります。

 0
3 1 i

   for(=1;<n+1;++){
     x[g]=
;
によって、

 0
3 1 1


 0
3 1 2

と変化していって、はじめて3つのセルの内容がすべて異なり、
     if(g+1<n){
        f(g+1);
     }
     else{
        h();
        cn++;
     }
の否定部分の命令が遂行され5個目の順列
wがコンソールに出力されます。
以下、

 0
3 1 3

セル番号の世界の5度目の消滅。

 0
3 1


 0
3 2


 0
3 2 1

と変化していき、6個目の順列
eがコンソールに打ち出されます。

 0
3 2 2


 0
3 2 3

セル番号の世界の6度目の消滅。


 0
3 2


 0
3 3

セル番号の世界の3度目の消滅。

 0
3

セル番号0の世界のはじめての消滅を迎え、
プログラムはf (0)を呼び出してから
はじめてPrivate Sub CommandButton1_Clickに戻り、
自分の任務をすべて完遂し終焉を迎えます。
プログラムは、消滅しましたが、コンソールには結果
bが燦然と輝いています。

最後の方、叙述を簡単にしましたが、
簡略にした部分を皆さんが補ってください。
詳しい記述を延々と繰り返したのでは、
逆に読む気力が失せると考え、簡単にしました。

n=3を選んだ理由はお分かりですね。
n=2ではトレースとして簡単すぎます。
しかし、n=4では、私も書く気になれませんし、
読む皆さんもウンザリですよね。

みなさん、n=4のトレースは大変ですが、
頭の中でやってみてください。
コンピュータの動きを追うことはとても大切なことです。

では、n次順列生成

#include<iostream>
using namespace std;
void f(int g);
void h();
int x[15],n;
long cn;
void main(){
   cout<<"何次順列を生成しますか?"<<endl;
   scanf("%d",&n);
   cout<<endl;
   cn=0;
   f(0];
   cout<<n<<"次順列が"<<cn<<"個生成されました。"<<endl;
}
void f(int g){
   int i,j;
   for(
i=1;i<n+1;i++){
     x[g]=
i;
     if(
g>0){
        for(j=0;j<g;j++){
          if(x[g]==x[j])goto tobi;
        }
     }
     if(
g+1<n){
        f(
g+1);
     }
     else{
        h();
        cn++;
     }
     tobi:;
   }
}
void h(){
   for(char i=0;i<n;i++)cout<<x[i]<<" ";
   cout<<endl;
}
プログラムを改良して、
n次魔方陣自動生成プログラムを作成してください。
コードを複雑にしすぎないために
int x[30][30],n;
long cn;
はグローバル配列およびグローバル変数にしておきましょう。

第8講で作った方式では、
4次が限界ですが、
将来は改良して30次魔方陣までも作成可能にしますので、
配列は大きめにx[30][30]にしてあります。
r

n次魔方陣の行などの合計は
n*(n*n+1)/2
で計算できます。
なぜなら
(1+2+3+・・・+n*n)÷n
=n*n(n*n+1)/2÷n
=n*(n*n+1)/2
です。
さあ、汎用的魔方陣自動生成ソフトに挑戦しましょう!


第6話へ 第8話へ


a

魔方陣 数独で学ぶ VBA 入門
数独のシンプルな解き方・簡単な解法の研究
VB講義へ
VB講義基礎へ
初心者のための世界で一番わかりやすいVisual C++入門基礎講座
初心者のための世界で一番わかりやすいVisual Basic入門基礎講座
初心者のための世界で一番わかりやすいVBA入門講義(基礎から応用まで)
初心者のための VC++による C言語 C++ 入門 基礎から応用まで第1部
eclipse java 入門
java 入門 サイト 基礎から応用まで
VC++ C言語 C++ 入門 初心者 基礎から応用まで
本サイトトップへ