- ベストアンサー
4つの数字を用いて重複することなく並べる
題名のとおりなのですが 例えば{1,2,3,4},{2,3,4,1}などです。 これら24通りを[24][4]の要素をもつ2次元配列に入れたいのですがどうすればいいのでしょうか? 一応自分で作ってみたのですが作ってみていかにも冗長であると感じています。 アドバイス、回答よろしくお願いします。 #include <stdio.h> int main(void){ int i,j,n=5,m,p; int l[24][4]={{1,2,3,4},{2,1,3,4},{2,3,1,4},{3,2,1,4},{3,2,4,1},{4,2,3,1}}; for(i=0;i<6;i++){ for(j=0;j<3;j++){ n++; if(!j)for(p=0;p<4;p++)l[n][p]=l[i][p]; else for(p=0;p<4;p++)l[n][p]=l[n-1][p]; m=l[n][0]; l[n][0]=l[n][1]; l[n][1]=l[n][2]; l[n][2]=l[n][3]; l[n][3]=m; } } for(i=0;i<24;i++){ for(j=0;j<4;j++){ printf("%d",l[i][j]); } printf("\n"); } return 0; }
- みんなの回答 (4)
- 専門家の回答
質問者が選んだベストアンサー
私が作ったソースコードは以下のようなものです 簡単な物にするつもりがややこしいコードになってしまいました…… 4つの数字だけでなく、任意の桁数でも機能します。 また「1357」の順列といったものも求められます。 //////////////////////////////////////////////////////////////////////////////// // #include <stdio.h> #include <stdlib.h> #include <math.h> void sample(int len, int *number_list, int *data_list); int main(int argc, char* args[]) { int i, j; int number_list[4], data_list[4 * 24]; // ここで1,2,3,4を設定 for (i = 0; i < 4; i++) number_list[i] = i + 1; // これだと1357を設定 // number_list[0] = 1; // number_list[1] = 3; // number_list[2] = 5; // number_list[3] = 7; // この関数が全ての順列を生成する sample(4, number_list, data_list); for (i = 0; i < 24; i++) { for (j = 0; j < 4; j++) { printf("%d ", data_list[i * 4 + j]); } printf("\n"); } getchar(); return 0; } void sample(int len, int *number_list, int *data_list) { // len : 桁数、最初は4 // number_list: 番号のリスト「1」「2」「3」「4」と入ってたら、これの順列をつくる // data_list : 作成した順列をここに格納して、関数を呼び出した側へ渡す int *ptmp; int i, j, k; int size; int size_prev; if (len == 1) { data_list[0] = number_list[0]; return; } size = 1; for (i = 1; i <= len; i++) { size *= i; } size_prev = size / len; ptmp = (int *)malloc(sizeof(int) * (len - 1) * size_prev); sample(len - 1, &number_list[1], ptmp); for (i = 0; i < len; i++) { for (j = 0; j < size_prev; j++) { data_list[i * len * size_prev + j * len + i] = number_list[0]; for (k = 0; k < len - 1; k++) { data_list[i * len * size_prev + j * len + ((i + k + 1) % len)] = ptmp[j * (len - 1) + (k % (len - 1))]; } } } free(ptmp); }
その他の回答 (3)
C++ でよければ,標準ライブラリのおかげで以下のようにすっきり書けます。 C でも std::next_permutation と同じような動作をする関数を用意してやればすっきり書けると思います。 #include <iostream> #include <algorithm> int main(int argc, char* argv[]) { int x[24][4]; // ここに結果を格納 int tmp[4] = { 1, 2, 3, 4 }; // 順列の生成 for (int i=0 ; i<24 ; i++) { std::copy(tmp, tmp + 4, x[i]); std::next_permutation(tmp, tmp + 4); } // 表示 std::ostream_iterator<int> it(std::cout); for (int i=0 ; i<24 ; i++) { std::copy(x[i], x[i] + 4, it); std::cout << std::endl; } return 0; }
お礼
C言語しか勉強していないので 部分的にしか分りませんが 当たり前なのかもしれませんがちゃんと動きました。 アドバイスありがとうございました。
- winterofmeei
- ベストアンサー率22% (20/88)
> data_list[i * len * size_prev + j * len + ((i + k + 1) % len)] > の部分は > data_list[~][~]の形で書くとどのようになるのでしょうか? このコードで使用しているdata_listは1次元配列のポインタとして使用しているため、2次元配列のdata_list[~][~]の形に書き表すことはできません。 ただ、意味としてはebinamoriさんが使用していた配列lと、 data_list[i * len * size_prev + j * len + k] : l[i * size_prev + j][k] という形で対応します。 data_listの中身は以下のような形になっています。 1次元の配列を2次元として扱っています。 {1,2,3,4, 1,2,4,3 ……} 0番目から3番目までは一つ目の順列 4番目から7番目までは二つ目の順列 ・ ・ ・
お礼
再び回答有難うございます。 勉強になりました。
- tsukasa-12r
- ベストアンサー率65% (358/549)
スピードは期待できませんが、シンプルにこういうのはどうでしょうか。 #include <stdio.h> int iSrc[4] = { 1, 2, 3, 4 }; void main() { int i, j, k, l; int iIndex; int iDst[24][4]; iIndex = 0; for( i=0; i<4; i++ ) { for( j=0; j<4; j++ ) { if( i != j ) { for( k=0; k<4; k++ ) { if( k != i && k != j ) { for( l=0; l<4; l++ ) { if( l != i && l != j && l != k ) { iDst[iIndex][0] = iSrc[i]; iDst[iIndex][1] = iSrc[j]; iDst[iIndex][2] = iSrc[k]; iDst[iIndex][3] = iSrc[l]; iIndex++; } } } } } } } for( iIndex=0; iIndex<24; iIndex++ ) { printf( "%d, %d, %d, %d\n", iDst[iIndex][0], iDst[iIndex][1], iDst[iIndex][2], iDst[iIndex][3] ); } }
お礼
私のと違い iSrcの初期値を入力できるようにすれば どのような数字でも24通りを返してくれる 関数を作れますね。 回答有難うございました。
お礼
回答有難うございます。 data_list[i * len * size_prev + j * len + ((i + k + 1) % len)] の部分は data_list[~][~]の形で書くとどのようになるのでしょうか?