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

第11話 部屋数3・生徒数3の場合におけるトレースその3と新しい解釈の続き

プログラムコード再掲

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

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

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

#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;

                                          }

                            }

              }

}


第10話で打ち出しました世界観をもう少し詳しく見てからトレースの続きに戻ります。

フォイエルバッハという哲学者が、

本質は外側にある、環境にあると主張しました。

魚の本質は、魚の中にはなくて環境である水にあると主張しました。

人間の本質も社会にある、と主張したわけです。

ヘーゲルの死後、ヘーゲル学派は右派、中央派、左派に分裂しました。

フォイエルバッハは左派に属してヘーゲルを批判しました。

キリスト教の本質は人間の本質の疎外態であるという主張は、エンゲルス・マルクスに巨大な影響力を与えました。

神の本質は所詮人間の本質の疎外態 = 本来の姿から悪しきものへの変形にすぎないという洞察は、

当時のドイツ哲学界を震撼させるものだったのです。

絶対王者であったヘーゲルに果敢に挑戦した人たちがヘーゲル左派だったのであり、

その最先方を行っていた人がフォイエルバッハだったのです。

私も、学生時代に『キリスト教の本質』というフォイエルバッハの本を読んで深く影響を受けました。

ミノムシの本質が、彼が住んでいる葉っぱにあるという洞察には震えたものです。

この思想がやがてマルクスによって「人間の本質は、社会的関係の総体である」という世界観を生み出す契機になりました。

廣松渉はマルクスの初期から後期への発展は、

西洋哲学におけるデカルト以降の実体的世界観から関係的世界観への跳躍であるという主張をしています。

マルクスが、資本論を書いて関係主義的世界観を披露したのが1867年です。

実存哲学・現象学・分析哲学など現代哲学が、関係主義的世界観について一斉に砲門を開いたのが20世紀初頭だったので、

マルクスが主観-客観図式と実体主義的世界観を乗り越え新しい世界観である関係主義的世界観を約1/4世紀を先取りしていたという主張は真

実だった、と思っています。

いわゆるパラダイム転換を成し遂げた、と解釈しています。

フォイエルバッハを一方では高く評価しながら、ヘーゲルの真理は内に宿るという思想にも私は共鳴していました。

ヘーゲルの開いた世界観は、生成・消滅・流転という風に世界は弁証法的に発展していくという世界観だったのです。

現実を止揚してより高いものへ発展させるという弁証法的世界観にも学生時代は夢中になったものです。

入れ子式人形の比喩は、ヘーゲルの真理は内にあるという発想に負っています。

関数の再帰的使用は、生成・消滅・止揚をなす世界観です。

空間の中に突然人形が現れ、その人形に中にも突然人形が重層的に現れるのです。

そして、一番内側の人形から順に消滅していき、最後に一番外側の人形f(0)が消滅するのです。

これは、まさに死の儀式だと思われます。

さて、脱線は以上にしましてトレースに戻ります。

前話の最後は「


             f(2)が再生成されます。」

             でした。
      
      新たなるfor文

             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;

                            }

       が始まります。i = 0 によって i + 1 は1となりますが、

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

                                         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)a[s] = i + 1;

      は実行されません。

      i は一つ進んで

             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;

                            }


         i + 1 は2となり

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

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

                                                                      h = 0;

                                                                      break;

                                                        }

                                          }
      を重複検査を乗り越えて


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

      が実行されてa[2] = 2 となり



      から2番目の順列が生成され

                                         else {

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

                                                        cout << " ";

                                                        cn++;

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

                                          }

      によってコンソール画面にが打ち出されます。

      ですから、我々の旅はまだまだ続きます。









          











   






第9章第10話へ 第9章第12話へ

本講義トップへ