質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.49%
C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Q&A

解決済

5回答

3180閲覧

再帰を使わずに再帰のようなことを実現したい

toshiyan

総合スコア74

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

0グッド

0クリップ

投稿2017/12/31 03:29

編集2017/12/31 07:52
[1,1,1,1,1] [1,1,1,1,2] ... [1,1,1,1,9] [1,1,1,2,2] [1,1,1,2,3] ... [8,9,9,9,9] [9,9,9,9,9]

上記のような出力をするC++のプログラムを、再帰を使わずに実現したいです。
どうすればよいでしょうか。

以下は、再帰を使った実装です(一応、丸投げではないアピールです)。

cpp

1#include <iostream> 2#include <vector> 3 4using namespace std; 5 6void recurse(vector<int> *v, int len, int max) 7{ 8 int start; 9 int i, j; 10 if (v->size() == len) { 11 cout << "["; 12 for (j = 0; j < len-1; j++) { 13 cout << v->at(j) << ","; 14 } 15 cout << v->at(len-1) << "]" << endl; 16 return; 17 } 18 if (v->size() == 0) { 19 start = 1; 20 } else { 21 start = v->back(); 22 } 23 for (i = start; i <= max; i++) { 24 v->push_back(i); 25 recurse(v, len, max); 26 v->pop_back(); 27 } 28} 29 30int main(void) 31{ 32 vector<int> v; 33 recurse(&v, 5, 9); 34 return 0; 35}

【追記】
長さと最大値は可変にしたいです。最小値は、とりあえずは1で固定です。

【更に追記】
baseballyamaさんの回答を元に書いた、再帰無しのコードです。一応再帰無しで同等の処理が実現できましたので解決済みとします。回答してくださった皆様、ありがとうございました!ただ、僕としては、maxが2桁以上の場合でも正常に動作してほしいですし、再帰処理を再帰無しで記述する「普遍的な」方法を知りたかったです。その方法を知れれば、機械的に再帰無しコードに書き換えられるような…そんなメソッドが知りたかったのです。

cpp

1#include <iostream> 2 3using namespace std; 4 5void recurse(int len, int max) 6{ 7 // 数値型↔文字型の変換は、0x30を加算・減算することで行う 8 string smax = string(5, max + 0x30); 9 int imax = stoi(smax); 10 11 for (int i = 1; i <= imax; i++) { 12 bool flag = true; 13 string s = to_string(i); 14 15 for (int j = 0; j < s.size(); j++) { 16 // 要素が1以上max以下の条件を満たさない場合は出力しない 17 if (s[j] - 0x30 < 1 || s[j] - 0x30 > max) { 18 flag = false; 19 break; 20 } 21 // 左から右に昇順でない場合は出力しない 22 if (j > 0 && s[j - 1] > s[j]) { 23 flag = false; 24 break; 25 } 26 } 27 28 if (flag) { 29 cout << "["; 30 for (int j = 0; j < s.size(); j++) { 31 cout << s[j]; 32 if (j < s.size() - 1) { 33 cout << ","; 34 } 35 } 36 cout << "]" << endl; 37 } 38 } 39} 40 41int main(void) 42{ 43 recurse(5, 9); 44 return 0; 45}

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

iwanote

2017/12/31 03:58

これは桁数があらかじめ決まっているものですか?決まっているならfor文で回せばいいですし、決まっていないならプログラム中のprintfのところがおかしいように思われます
toshiyan

2017/12/31 04:08

ご指摘ありがとうございます。ご指摘の内容をソースコードに反映しました。配列の長さと最大値は、引数として渡すことを想定しています。
guest

回答5

0

カウンタ変数を1から100,000までカウントアップしていき、各桁を拾えば良いと思います(0である桁があるケースは除外が必要)。各桁を拾うのは10で割った剰余を順に使えば良いです。

投稿2017/12/31 07:29

HogeAnimalLover

総合スコア4830

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

toshiyan

2017/12/31 07:59

回答ありがとうございます。
退会済みユーザー

退会済みユーザー

2017/12/31 11:25

9で割ったあまりに1足すとか。
guest

0

ベストアンサー

正月の遊びのつもりで作ってみましたが、出力仕様に合っていますか。

c++

1#include <iostream> 2#include <vector> 3 4using namespace std; 5 6void init(vector<int> *v, int len) { 7 for (int i = 0; i < len; i++) v->push_back(1); 8} 9 10void print(vector<int> *v) { 11 cout << "["; 12 for (int i = 0; i < v->size()-1; i++) cout << v->at(i) << ","; 13 cout << v->at(v->size()-1) << "]" << endl; 14} 15 16bool checkMax(vector<int> *v, int start, int end, int max) { 17 for (int i = start; i <= end; i++) { 18 if (v->at(i) < max) return false; 19 } 20 return true; 21} 22 23int main(void) 24{ 25 vector<int> v; 26 int len = 5; 27 int max = 9; 28 29 init(&v, len); 30 31 while (true) { 32 print(&v); 33 34 if (checkMax(&v, 0, len-1, max)) break; 35 36 for (int i = len-1; i >= 0; i--) { 37 if (v.at(i) < max) { 38 if (i < len-1) { 39 if (checkMax(&v, i+1, len-1, max)) { 40 v.at(i)++; 41 } 42 } else { 43 v.at(i)++; 44 } 45 break; 46 } else if (v.at(i) == max) { 47 if (i > 0) { 48 if (v.at(i-1) < max) { 49 v.at(i-1)++; 50 if (checkMax(&v, i, len-1, max)) { 51 for (int j = i; j < len; j++) v.at(j) = v.at(i-1); 52 } 53 break; 54 } 55 } 56 } 57 } 58 } 59 return 0; 60} 61

投稿2018/01/01 13:23

退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

toshiyan

2018/01/02 02:14

私の要件をすべて満たしてくれていますね。ベストアンサーを、こちらの正しいコードに変えさせていただきます。回答ありがとうございました!
guest

0

C++など不要。そう、シェル芸ならね!

bash

1$ echo [{1..9},{1..9},{1..9},{1..9}]|tr ' ' '\n'

投稿2017/12/31 04:30

編集2018/05/10 13:15
hichon

総合スコア5737

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

toshiyan

2017/12/31 04:32

回答ありがとうございます。参考になります。
guest

0

ご質問の内容を正確に把握せずに回答してしまいました。大変申し訳ございません。
再帰処理を使用しないとすると以下のような処理が妥当なのではないかと思いました。
※但し私C++は書いたことがないので、javaをイメージして記載してしまいました。
※なので、不適当なプログラムを記載している部分があるかもしれません。
※コメントを受けて修正しました。

C++

1#include <iostream> 2#include <stdexcept> 3#include <string> 4#include <sstream> 5#include <iomanip> 6using namespace std; 7 8// char文字を int型 に変換(数字以外が来た場合は -1 を返却) 9int ctoi(char c) { 10 switch (c) { 11 case '0': 12 return 0; 13 case '1': 14 return 1; 15 case '2': 16 return 2; 17 case '3': 18 return 3; 19 case '4': 20 return 4; 21 case '5': 22 return 5; 23 case '6': 24 return 6; 25 case '7': 26 return 7; 27 case '8': 28 return 8; 29 case '9': 30 return 9; 31 default: 32 return -1; 33 } 34} 35 36// len 文字数の数字を カンマ区切りで出力 37// 但し max 以上の数字が入っている場合は出力を実施しない 38// 出力例: [2,2,2,2,2] 39void printNums(int len, int max) { 40 41 // 出力最大値を取得 42 string maxValue = ""; 43 for (int i = 0; i < len; i++) { 44 maxValue = maxValue + std::to_string(max); 45 } 46 int maxvalue = std::stoi(maxValue); 47 48 // 0 から 出力最大値まで走査 49 for (int i = 1; i <= maxvalue; i++) { 50 51 // 出力対象フラグ初期化 52 bool printFlag = true; 53 54 // 出力対象の数字を文字列に変換 55 std::ostringstream sout; 56 sout << std::setfill('0') << std::setw(5) << i; 57 std::string str = sout.str(); 58 59 // 出力対象に max 以上の数値が含まれている場合は出力処理を実施しない 60 for (int j = 0; j < (int) str.size(); j++) { 61 if (ctoi(str[j]) > max || ctoi(str[j]) == 0) { 62 printFlag = false; 63 break; 64 } 65 } 66 67 // 出力対象の場合は出力を実施 68 if (printFlag) { 69 cout << "["; 70 int length = str.length(); 71 for (int j = 0; j < length; j++) { 72 cout << str[j]; 73 if (length != (j + 1)) { 74 cout << ", "; 75 } 76 } 77 cout << "]" << endl; 78 } 79 80 } 81 82} 83 84// メイン処理 85int main() { 86 87 // 5桁で全ての数字が2以下のものを出力 88 printNums(5, 2); 89 90 // 結果返却 91 return 0; 92 93}

※以下当初の回答
/*******************************************************************/

単純に for文 を4重に回すのではダメなのですか?

C++

1#include <iostream> 2using namespace std; 3 4int main() { 5 6 // 1桁目を 1 から 9 まで走査 7 for (int i = 1; i < 10; i++) { 8 9 // 2桁目を 1 から 9 まで走査 10 for (int j = 1; j < 10; j++) { 11 12 // 3桁目を 1 から 9 まで走査 13 for (int k = 1; k < 10; k++) { 14 15 // 4桁目を 1 から 9 まで走査 16 for (int l = 1; l < 10; l++) { 17 18 // 標準出力 形式:"[i, j, k, l]" 19 cout << "[" << i << ", " << j << ", " << k << ", " << l << "]" << endl; 20 21 } 22 23 } 24 25 } 26 27 } 28 29 // 結果返却 30 return 0; 31 32} 33

投稿2017/12/31 04:12

編集2017/12/31 07:57
yamashita_yuich

総合スコア316

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

toshiyan

2017/12/31 04:16

回答ありがとうございます。要素の数は可変にしたいです…。
yamashita_yuich

2017/12/31 04:59

そしたら、そのi, j, k, l を引数にしたメソッドを作成し、それをmainから呼べばよいのではないでしょうか。
toshiyan

2017/12/31 05:10

すみません。よくわからないので、コードで提示していただけないでしょうか。理解力がなくて申し訳ございません…。
yamashita_yuich

2017/12/31 06:58

当初の回答はご質問を正確に理解していないで記載してしまいました。ご質問を再度読み返したのち、再度プログラムを記載させて頂きました。お役に立てたら幸いです。
toshiyan

2017/12/31 07:42

丁寧な対応ありがとうございます。嬉しいです。 私の方でも実装しましたところ、以下のバグが含まれていました。 ・[1,0,0,0,0]のような配列も出力されてしまう。 ・[1,1,1,2,1]のような、要素が左から右に昇順になっていないものは、出力したくありません。このプログラムでは出力してしまいます。 ・maxが2桁以上の場合に対応していない(これは私の伝え忘れです。すみません…)。 再帰を使って楽に書けるコードを再帰無しで無理に書こうとすると、柔軟性がなくなってしまうものなんですかね…(例えばmaxは一桁の数値にしか対応しない、など)。 一応、私の方で実装したコードを質問内に載せておきます。
yamashita_yuich

2017/12/31 07:56

・[1,0,0,0,0]のような配列も出力されてしまう。 ⇒すいません。これは要件を把握できていませんでした。 ・[1,1,1,2,1]のような、要素が左から右に昇順になって... ⇒そうなんですね。了解しました。 ・maxが2桁以上の場合に対応してい... ⇒そうなんですね。了解しました。 私は再帰処理に抵抗がないので、この場合再帰で書きますが、再帰はわかりづらいという人が一定数いることも事実です。 ただ、このケースの場合、上記要件も取り込んで再帰なしで実装するとなると、冗長になると思います。 まずは、上記要件漏れを修正してソースを更新しておきます。
guest

0

配列に11...11から99...99までの数字全部入れてその条件に当てはまらないものを消していったらどうでしょうか
配列に収まるかはわかりませんが...

投稿2017/12/31 05:24

iwanote

総合スコア295

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

toshiyan

2017/12/31 07:59

回答ありがとうございます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.49%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問