![](http://oshiete.xgoo.jp/images/v2/pc/qa/question_title.png?5a7ff87)
![](http://oshiete.xgoo.jp/images/v2/common/profile/M/noimageicon_setting_12.png?5a7ff87)
例えば1,2,3を一列に並べるという順列の問題(1→2→3、1→3→2、2→1→3、2→3→1、3→1→2、3→2→1の3!=6通り)
は再帰などを使って解けますが、
千の位(3,2)、百の位(1,4,7)、十の位(6)、一の位(2,6)
のような各位の組合せの問題を解くにはどうすればよいでしょうか?
3→1→6→2、3→1→6→6、3→4→6→2、3→4→6→6、3→7→6→2、3→7→6→6、2→1→6→2、2→1→6→6、2→4→6→2、2→4→6→6、2→7→6→2、2→7→6→6
上記の例の総組合せの数は2×3×1×2=12(各位の掛算)になりますが、アドバイスをお願いします。
開発言語はGNU Cで、コンパイラはgccです。
No.2ベストアンサー
- 回答日時:
(1)1,2,3を一列に並べる
/* "123"の順列を表示する */
#include <stdio.h>
#include <string.h>
#include <malloc.h>
static unsigned count;
void choice(char *select,char *list){
int len,i,j;
char *newSelect,*newList,*p;
len=strlen(list);
if(len==1){
printf("%s%c\n",select, *list);
count++;
return;
}
newSelect=(char*)malloc(strlen(select)+2);
newList =(char*)malloc(len);
for(i=0;i<len;i++){
for(j=0,p=newList;j<=len;j++){ /* 選んだ1文字を除く文字列を作る */
if(j!=i)
*p++=list[j];
}
sprintf(newSelect,"%s%c", select, list[i]);
choice(newSelect, newList);
}
free(newSelect);
free(newList);
}
void main(void){
count=0;
choice("","123");
printf("%u通り\n",count);
}
(2)千の位(3,2)、百の位(1,4,7)、十の位(6)、一の位(2,6)
/* [32][147][6][26]の順列を表示する */
#include <stdio.h>
#include <string.h>
#include <malloc.h>
static unsigned count;
char *table[]={ "32","147","6","26",NULL};
void choice(char *select, int level){
char *newSelect,*p;
if(table[level]==NULL){
count++;
printf("%s\n",select);
return;
}
newSelect=(char*)malloc(strlen(select)+2);
p=table[level];
while(*p){
sprintf(newSelect, "%s%c", select, *p++);
choice(newSelect, level+1);
}
free(newSelect);
}
void main(void){
count=0;
choice("",0);
printf("%u通り\n",count);
}
この回答への補足
お返事ありがとうございます。
とても詳しくソースコードまで書いていただいて申し訳ないのですが、千の位の候補の3,2を"32"というリテラル文字列で扱うのではなく、int comb[][]={{3,1,6,2},{2,4,,6},{,7,,}}という2次元配列のようなもので扱いたいと思っています。そして各位にどれだけ値が入っているかを記憶しておくint check[]={2,3,1,2}という1次元配列を用意して、この二つの配列で総組み合わせを求められないかと考えていました。つまり各位の値をリテラル文字列のようにまとめるのではなく、各値をそれぞれ一つのデータとして扱って組み合わせたいと思っています。私の説明が不足していて申し訳ございませんでした。文章がうまくまとめられておらず分かりずらいと思いますが、もしよろしければアドバイスをお願いいたします。
No.5
- 回答日時:
No.1のコーディング例です。
再帰を使っています。(インデントを全角の空白にしています)
#include <stdio.h>
#define N 4
int comb[][N]={{3,2,0},{1,4,7},{6,0,0},{2,6,0}};
int check[N]={2,3,1,2};
int kotae[N];
void hyouji(void) {
int i;
for (i=0; i<N; i++) {
printf("%d ",kotae[i]);
}
printf("\n");
}
void naraberu(int n) {
int i;
if (n==N) {
hyouji();
} else {
for (i=0; i<check[n]; i++) {
kotae[n] = comb[n][i];
naraberu(n+1);
}
}
}
int main(void) {
naraberu(0);
return 0;
}
諸事情により回答が遅くなってしまい大変申し訳ございませんでした。
アドバイスいただいたサンプルプログラムは大変わかりやすく、参考になりました。
combやcheck配列を再起関数のローカル変数として扱わないようにする点にはじめ気づかず、格闘していましたが無事動作することができました。
また機会があればアドバイスのほうよろしくお願いいたします。
最後にお礼が遅くなってすみませんでした。
どうもありがとうございました。
No.4
- 回答日時:
#3の補足
combの内容(並び)が#2の補足で示されているものと異なりますが、
配列の下位のモノが並列に変化する
(comb[][i]のようなこと)
方が私にとってなじみがよく好みですのでそう書いております。
もちろん
comb[i][]のようにアクセスしてもかまいません。
同じことです。
老婆心にて。
諸事情によりお返事が遅くなってしまい大変申し訳ございませんでした。
BLUEPIXYさんのサンプルプログラムを参考にcomb[i][]のようにアクセスして試してみたところ動作することが確認できました。
今回は何度もご丁寧な回答をしていただいてとても感謝しています。
また機会があればアドバイスのほうよろしくお願いいたします。最後にお返事が遅くなって本当にすみませんでした。どうもありがとうございました。
No.3
- 回答日時:
#2の補足について
int comb[4][4]={
{3,2,0,0},
{1,4,7,0},
{6,0,0,0},
{2,6,0,0}
};
int check [4]={ 2,3,1,2 };
は、#2(2)のプログラムを
char table[4][4] = {
{'3','2' ,'\0','\0'},
{'1','4' ,'7' ,'\0'},
{'6','\0','\0','\0'},
{'2','6' ,'\0','\0'}
};
と見なすと
int check [4]={ 2,3,1,2 };
は、あらかじめstrlenしたと見ると
ほとんど同じだということがわかります。
組み合わせる数を
int select[4];
の様に表現するか
あるいは、
int select=0;
として、
select = select * 10 + n;
のように集計するかは、お好みでやればいいかと思います。
No.1
- 回答日時:
一例ですが、下記の手順を実行する関数を作成すれば良いのではないでしょうか。
step 1)
さらに下位があればstep 2 ~ 3を実行し、なければ空列を値として返す。
step 2)
下位の順列を得る(再帰呼び出しでも可能)。
step 3)
現在位置の数(例えば、百の位ならば、1,4,7)それぞれに、上で得た下位の順列それぞれを連結させ、これで得られる全ての列を値として返す。
以上
お返事ありがとうございます。
なかなかプログラムのスキルやアルゴリズムの知識がないため、アドバイスがあまり理解ができなかったのですが、頑張ってみたいと思います。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- Excel(エクセル) エクセル関数の変わった使い方 3 2022/05/13 17:12
- その他(学校・勉強) 中学受験レベルの社会の問題についての質問です。 新潟、千葉、鹿児島のうち乳牛の飼育数の多い県を答える 1 2022/10/22 01:30
- 数学 数的推理の問題です。 次の条件を満たす全ての数の平均値の一の位はいくらか。 ○3桁から6桁の自然数 8 2022/04/28 01:21
- Excel(エクセル) Excelグラフについて 1 2023/05/12 16:26
- 物理学 物理の単位 4 2022/08/20 23:01
- 物理学 2つの点電荷による電位が0でも電荷の移動は起こる? 2 2023/06/29 20:15
- 大学受験 娘の大学受験勉強 6 2022/06/30 19:58
- 数学 パズルWaterSortの解は必ず存在するの? 5 2022/10/13 06:50
- HTML・CSS CSS上での計算を行うためのルールについて教えてください。 3 2022/08/15 14:43
- ホテル・旅館 Tripadvisor ホテルの口コミ・ランキングは 信頼できますか? 3 2023/07/09 12:44
関連するカテゴリからQ&Aを探す
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
fgetsなどのときのstdinのバッ...
-
charでの計算?
-
'const char *' 型は 'char *' ...
-
文字列から空白を取り除きたい...
-
エンディアン:2バイトのデー...
-
C言語のfor文です。 繰り返しの...
-
テキストデータをそのままバイ...
-
charからLPTSTRへの変換方法
-
atoi( ) の反対をやりたい
-
C言語です
-
C言語プログラミングについて(...
-
C言語、リダイレクト
-
Win32APIでのエディットボック...
-
int型からchar型への変換
-
CStringをwchar_tに変換したい
-
【C言語】文字型と整数型の違い
-
strncpyと_tcsncpy_sのヌルの扱...
-
double型の値をchar配列に変換...
-
ソースコードエラー
-
【C言語】テキストファイル内の...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
fgetsなどのときのstdinのバッ...
-
C言語のfor文です。 繰り返しの...
-
文字列から空白を取り除きたい...
-
charからLPTSTRへの変換方法
-
charでの計算?
-
配列をnビットシフトする
-
CStringをwchar_tに変換したい
-
c++ 文字列を入力して、一文字...
-
str系関数を使わずに二つの文字...
-
間接操作のレベルとは
-
int main()の・・・
-
C言語の入力した文字を反転させ...
-
atoi( ) の反対をやりたい
-
switch文で文字を比較すること...
-
テキストデータをそのままバイ...
-
Win32APIでのエディットボック...
-
double型の値をchar配列に変換...
-
干支のプログラム
-
コンパイルエラー invalid ope...
-
間接参照のレベルが異なっています
おすすめ情報