マルチスレッド版数独自動生成ソフトC++コードを題材とする超初心者のためのVisual Studio C++講義
第9章 関数の再帰的使用

第6話 主要概念 s と i + 1 の説明


プログラムコード再掲

#include<iostream>//インクルードファイルiostreamの読み込み

 

#include<conio.h>//while(!_kbhit());を使うためのお呪い

 

#include<string> //文字列変数を使えるようにするために組み込む

 

#include <iomanip> //setprecisionを使えるように組み込む

 

#include <cmath>//powなどを使うときに必要

 

#include <ctime>//time()(←現時刻発生する関数)を使うために必要

 

using namespace std;//coutを使うときに必要なお呪い

 

const int n = 5;//具体的な数字を使うのではなく、 n を使うと汎用性のあるプログラムになる!

 

void f(int s);//順列生成関数←引数名をgからsに変更(2026年3月19日)

 

int a[25]; //将来5次魔方陣まで生成できるように25に変更

 

int cn = 0; //anに変更 変更理由はnuberの頭文字nは整数を表す場合が多いからです

 

int main() {

 

              f(0);

 

              cout << endl << "生成された順列は" << cn << "個です。" << endl;//←2026年3月19日訂正

 

              while (!_kbhit());//待機させるための命令


 

              return(0);

 

}

void f(int s) {

 

              int h;

 

              for (int i = 0; i < n; i++) {

 

                            if (s == 0)a[s] = i + 1;

 

                            h = 1;

 

                            if (s > 0) {

 

                                          for (int j = 0; j < s; j++) {

 

                                                        if (a[j] == i + 1) {

 

                                                                      h = 0;

 

                                                                      break;

 

                                                        }

                                          }

 

                                          if (h == 1)a[s] = i + 1;

 

                            }

                            if (h == 1) {

 

                                          if (s + 1 < n) {

 

                                                        f(s + 1);

 

                                          }

                                          else {

 

                                                        for (int j = 0; j < n; j++)cout << a[j];

 

                                                        cout << " ";

 

                                                        cn++;

 

                                                        if (cn % 10 == 0)cout << endl;

 

                                          }

                            }

              }

}


〔解説〕

物事を理解するのに大切なことは概念を適切に理解することです。

今回理解しなければならないことは s と i + 1 の2つです。

両者は

0,1,2,3,・・・

1,2,3,4,・・・

であり似ていますが、2つは全く異なる概念です。

これからホテルを比喩にして説明していきます。

そのホテルは全室シングルとします。

しかも、1階しかなく1つの廊下にシングルの部屋が並んでいるものとします。

皆さんは修学旅行で生徒を引率する場合を考えてください。。

当然部屋割りを考えなければなりません。

部屋数が多いと混乱しますので、部屋数3かつ生徒人数3と仮定します。

そして部屋割りを考えるのですが、

部屋の番号は

0,1,2

であるとして生徒の方も出席番号

1,2,3

で部屋割りを考えると想定してください。

この段階で勘のいいひとは

0,1,2,3,・・・

1,2,3,4,・・・

上は部屋番号で下は部屋に入れる生徒の出席番号を表していることに気が付くのではないでしょうか。

つまり、 s と i + 1 は部屋番号と人です。

関数の再帰的使用が理解できない人は

0,1,2,3,・・・

1,2,3,4,・・・

が似ていて混同するからです。

でも部屋番号とその番号の部屋に入る人では混同しようがないほど明確です。

例え、生徒を出席番号で管理しようが、2つを混同してしまう人はいません。

s と i + 1 は部屋番号と出席番号です。

引率者で部屋と生徒を混同する人はいません。

2つは全く異なる概念であり混同する人はいません。

部屋番号と出席番号と説明すれば、

初心者の方でも理解できます。

ところが、入門書でも入門サイトでもこの比喩を使って説明している人を見たことがありません。。

それは入門書や入門サイトを書いている人にとって当たり前のことで、

説明を不要と考えているからです。

大学教授やプロのプログラマーにとって説明が必要なことは思いもよらないのでしょう。

結局、

0,1,2,3,・・・

1,2,3,4,・・・

は大変似ているので初心者が混同することさえ想像がついていないのです。

ここまで私の講義についてきた人は、

私が初心者の立場に立ってどこを誤解するのかを完全に把握して講義を進めてきたことはお判りでしょう。

さて、第6話では部屋数3・生徒数3の場合について具体的に見ていきます。



第9章第5話へ 第9章第7話へ

本講義トップへ