• ベストアンサー

C++でforや再帰関数を使わずに、総当りする方法はありますか?

C++等で、forを使わず、再帰関数を使わずに多量のループで総当りする方法はありますでしょうか? 自己末尾再帰関数というのがネットで出てきますが、C言語系では使えないみたいです。 再帰関数で変数を全てスタティックにしても、関数の多重呼び出しで容量を食ってプログラムが動かないほどの計算をこなす必要があるのですが、こういった多数の桁のやり方になれておらず、先が見えません… また、全部をforにするのも、桁が大きすぎて問題があります。 どなたかご教授くださいますと幸いです。

noname#86052
noname#86052

質問者が選んだベストアンサー

  • ベストアンサー
  • Werner
  • ベストアンサー率53% (395/735)
回答No.3

コンパイラに期待できないなら自分で末尾最適化してみるとか。 多重のループはこんな感じに書き直せると思う。 //--------------------------------------------------------- #include<stdio.h> int main(){  int i[8]; //ループカウンタ  int cnt[8] = { //ループ回数   4,3,2,1,2,4,1,3,  };  int depth = 0; //現在のループの深さ  int depth_max = 7; //ループの深さ最大  int j;  i[0] = 0;  while(i[0] < cnt[0]){   while(depth < depth_max){ //一番内側のループでない場合    depth++; //1つ内側のループへ    i[depth] = 0; //ループカウンタ初期値設定   }   //一番内側でやりたいこと   for(j=0;j<=depth_max;j++) printf("%d,",i[j]);   printf("\n");   //一番内側のループカウンタ+1   i[depth]++;   while(!(i[depth] < cnt[depth])){ //深さdepthのループ継続条件を満たさない場合    depth--; //1つ外側のループへ    i[depth]++; //外側のループカウンタ+1   }  }  return 0; }

noname#86052
質問者

お礼

ご解答ありがとうございます。 書き直しの方法を詳しくお教えくださってありがとうございます。 C++でもできるのですね。自分ではどうしても解法がわからずしまいでしたので助かりました。 参考にさせていただきたく思います。

その他の回答 (4)

  • titokani
  • ベストアンサー率19% (341/1726)
回答No.5

う~ん、別に20重でも30重でも多重にループを回せばいいんじゃないかと思いますけど。いったいなにが問題なのかわからないです。

  • Interest
  • ベストアンサー率31% (207/659)
回答No.4

普通に総当たりを考えると、素直に考えれば N個のデータが配列 data[N]に入っているとして、 for(i=0; i<N; i++){  for(j=i+1; j<N; j++){    やりたい処理( data[i], data[j] );  } } となると思います。 これでスタックが積み上がるとは思えないのですが、これでは何が問題なのですか? また、 (a) 具体的にどのようなデータを相手にしているのか (b) 多数の桁とは具体的に何桁なのか も補足してください。

noname#86052
質問者

お礼

ご解答ありがとうございます。 あまり詳しく説明できず申し訳ございません…。 forで1~9までの数値を、20以上の多重ループで回します。 再帰で渡す値は、現在の潜り位置で、ポインターです。 スタックが積みあがってしまうのは、多重に関数を呼び出しているため、関数の分のメモリを食っているのだと思います。(内部のデータは全てstaticですので、純粋に己の関数の容量が摘みあがっているのだと考えます)

  • salsberry
  • ベストアンサー率69% (495/711)
回答No.2

> 自己末尾再帰関数というのがネットで出てきますが、C言語系では使えないみたいです。 決して使えないわけではなく、賢いコンパイラなら末尾再帰をコンパイル時にループに変換できる場合があります。もちろん、そのような最適化が本質的にできない再帰呼び出しもあります。 > こういった多数の桁のやり方になれておらず、先が見えません… > また、全部をforにするのも、桁が大きすぎて問題があります。 その「多数の桁」というのがどんなものなのか、forループだとどんな問題があるのかを示したほうがアドバイスを得やすいと思います。

noname#86052
質問者

お礼

ご解答ありがとうございます。 あまり詳しく書くことができず申し訳ございません…。 1~9までの数値でループするものを、20以上の桁数の総当りとなります。 forループだと、20以上の多重ループになってしまうため、プログラムが煩雑になってしまいます。 そういった問題で、なるべくループを抑えたコーディングをしたいということになります。

  • chie65535
  • ベストアンサー率43% (8522/19371)
回答No.1

>また、全部をforにするのも、桁が大きすぎて問題があります。 「32桁分の0~9の数字をforループ」を素直に書くと以下のような、入れ子が32重になったforループになります。 int i0,i1,i2,i3,i4,i5,i6,i7,i8,i9,i10,i11,i12,i13,i14,i15; int i16,i17,i18,i19,i20,i21,i22,i23,i24,i25,i26,i27,i28,i29,i30,i31; for(i31 = 0;i31 < 10;i31++) {  for(i30 = 0;i30 < 10;i30++) {   for(i29 = 0;i29 < 10;i29++) {    for(i28 = 0;i28 < 10;i28++) {     for(i27 = 0;i27 < 10;i27++) {      for(i26 = 0;i26 < 10;i26++) {       (以下略) しかし、以下のようにすれば「4重」で済みます。 int ii0,ii1,ii2,ii3; int i0,i1,i2,i3,i4,i5,i6,i7,i8,i9,i10,i11,i12,i13,i14,i15; int i16,i17,i18,i19,i20,i21,i22,i23,i24,i25,i26,i27,i28,i29,i30,i31; for(ii0 = 0;ii0 < 100000000;ii0++) {  i31 = ii0 / 10000000;  i30 = (ii0 / 1000000) % 10;  i29 = (ii0 / 100000) % 10;  i28 = (ii0 / 10000) % 10;  i27 = (ii0 / 1000) % 10;  i26 = (ii0 / 100) % 10;  i25 = (ii0 / 10) % 10;  i24 = ii0 % 10;  for(ii1 = 0;ii1 < 100000000;ii1++) {   i23 = ii1 / 10000000;   i22 = (ii1 / 1000000) % 10;   i21 = (ii1 / 100000) % 10;   i20 = (ii1 / 10000) % 10;   i19 = (ii1 / 1000) % 10;   i18 = (ii1 / 100) % 10;   i17 = (ii1 / 10) % 10;   i16 = ii1 % 10;   for(ii2 = 0;ii2 < 100000000;ii2++) {    i15 = ii2 / 10000000;    i14 = (ii2 / 1000000) % 10;    i13 = (ii2 / 100000) % 10;    i12 = (ii2 / 10000) % 10;    i11 = (ii2 / 1000) % 10;    i10 = (ii2 / 100) % 10;    i9 = (ii2 / 10) % 10;    i8 = ii2 % 10;    for(ii3 = 0;ii3 < 100000000;ii3++) {     i7 = ii3 / 10000000;     i6 = (ii3 / 1000000) % 10;     i5 = (ii3 / 100000) % 10;     i4 = (ii3 / 10000) % 10;     i3 = (ii3 / 1000) % 10;     i2 = (ii3 / 100) % 10;     i1 = (ii3 / 10) % 10;     i0 = ii3 % 10;     //ループの中身    }   }  } }

noname#86052
質問者

お礼

ご解答ありがとうございます。 とても複雑な組み方なのですね…! しかし判定式を工夫するだけで、ループは単純に減らせるのですね。 じっくり考えて試したいと思います。

関連するQ&A

  • C言語のプログラムについて

    C言語のプログラムについて 3桁の自然数の中で、自分自身を含めた約数が奇数になるものがいくつあるかを求めるプログラムを作りたいのですが、swich文を使って、6通りの方法で出そうとしていまして、 while 文、 for文、 do while文に加え、 for文のを、1つの関数として独立させたもの、 さらに、for文のを重ループ部分のそれぞれのループに対応して、2つの関数として独立させたもの、 そして、この2つの関数のどちらともをループを用いずに再帰呼び出しを用いたもの の6通りで出したいのですが、swich文を使うところは自力でできたのですが、あとの6つそれぞれのプログラムの組み方がわかりません。 教えていただけないでしょうか?ややこしい書き方をしてすいません・・・。

  • VC++ 再帰呼び出しについて

    VC++6.0にてプログラミングを行っているものですが、 関数の再帰呼び出しについて質問です。 再帰呼び出しの際にスタックに積まれる変数というのは、 再帰呼び出しをする関数に渡す引数のことですか? スタックオーバーフローを起こさないために、 staticなポインタにHeap領域上の 変数を割り当てるとよい。 と分かったのですが、 この意味は、例えば static int *a = new int; ということなのですか?

  • 再帰的な関数の作り方

    C言語の勉強をしている初心者です。 まだまだ始めたばかりでよく分かっていない状態です。 再帰的な関数が便利そうな事が書かれているのをよく目にしますが、何が便利でどう作ればいいのか分かりません。 分かりやすく教えていただけませんか。

  • 再帰関数のインライン展開

    再帰関数のインライン展開は出来るのでしょうか? もし、出来るようならアセンブラではどのように表現されているんですか? C以外の言語でも、再帰関数のインライン展開が出来るプログラム言語があれば教えてください。

  • C言語 再帰処理のメリットとデメリット

    最近、C言語の関数にも再帰定義ができるということを初めて知りました。 そこで聞きたいのですが、再帰処理のメリット・デメリットは何でしょうか? 思いついたものとしては メリット … 簡単に表記できる デメリット … 無限ループが発生する可能性あり でしょうか。 また、全計算が終わるまでに、途中の演算結果を保持しなければならないので、 メモリを無駄遣いしそうな気もします。

  • C言語で、再帰呼び出しを使用せずに、文字列"(12 + 3) * (

    C言語で、再帰呼び出しを使用せずに、文字列"(12 + 3) * ( 3 * (4 + 5 ))"を、優先順位が低い順に二分木に入れる関数を作成したいのですが・・・。 char str[15] = ""(12 + 3) * ( 3 * (4 + 5 ))";なら char n[100];に n[0] = '*' n[1] = '+' n[2] = '*' n[3] = 12 n[4] = 3 n[5] = 3 n[6] = '+' n[7] = \0 n[8] = \0 n[9] = \0 n[10] = \0 n[11] = \0 n[12] = \0 n[13] = 4 n[14] = 5 (n[15] 以降は\0が格納されています。) というように入れたいのですが関数からその関数を呼び出す再帰を使わずに作成する方法がわかりません。 再帰を使用しなければかなり処理が複雑になるような気がしますがどなたか詳しい方よろしくお願いします。 言語はC言語です。

  • 再帰関数のサポートについて

    http://ja.phptherightway.com/pages/Functional-Programming.html 上記ページにありますようにPHPは再帰関数をサポートとあります。 関数プログラミングなるものはこの再帰関数を使ってループをつくったりすると ききました。 たとえば function roop($i){ print($i); $n = $i + 1; if($n < 100){ roop($n); } } roop(1); というようなコードでしょうか。 これは1~99までのループですよね。 これはPHPがインタープリターといえど、一度 PHP専用のバイトコードに変換して からPHPエンジンがバイトコードを実行するため再帰が可能という解釈でもんだいないですかね? もしほんとうに逐次解釈なインタープリターなら解釈途中に、その関数自体の定義をインタープリターが認識? し終わる前に未定義状態の関数が出現してしまうってことですよね? undefined な関数があるといようなエラーがでてくのでしょうか? 生Cのソースみればわかるのでしょうけれども、私はCがわからないので・・・。 概要でよいのでご教授ください。

    • ベストアンサー
    • PHP
  • C言語 再帰呼びだし

    C言語 再帰呼びだし 問題が解けません。もしよろしければご指導お願いします。 フィボナッチ数を求めるプログラミングを作成せよ。 非負の整数nに対するフィボナッチ数Fnは以下のように再帰的に定義される。 Fn=0 (n=0の時) Fn=1 (n=1の時) Fn=F(n-1)+F(n-2) (n>1の時) ・関数int fibo(int n)を作成し、関数mainで、複数のnに対して関数fiboを呼びだし、その結果を表示せよ。 ・関数fiboは、再帰的にfiboを呼びだすようにせよ。 よろしくお願いします。

  • 二重ループのあるプログラム(C言語)

    #include <stdio.h> int main(void) { int i, j, c, c2; c = 0; for(i = 100; i < 1000; i++) { c2 = 0; for(j = 1; j <= i; j++) { if (i % j == 0) c2++; } if (c2 % 2 == 1) c++; } printf("%d個です。\n", c); return 0; } というプログラムがあるのですが、2重ループ部分のそれぞれのループに対応して、 2つの関数として独立させるとどのようになりますか? また、2つの関数のいずれにおいても、ループを用いずに再帰呼び出しを用いるとどうなりますか?

  • 再帰呼び出し

    C++のクラスで n!=n(n-1)(n-2)...1 n!を求めるprogramを作らなくてはならないのですが 再帰を使わずに、関数factorial(n)を使わないといけません。 ちんぷんかんぷんです。 for(counterとcounter--を使った)物しか思いうかびません。 関数factorial(n)を使うというのはnに戻るつまり再帰というふうには ならないのですか? 関数と再帰の意味を漠然としかわかっていないのですが。 よろしくお願いします。

専門家に質問してみよう