• ベストアンサー
※ ChatGPTを利用し、要約された質問です(原文:組み合わせと順列 アルゴリズム)

組み合わせと順列のアルゴリズムについて

このQ&Aのポイント
  • 組み合わせと順列のアルゴリズムについての質問です。順序関係のある要素で構成される集合から一定の数を取り、順列を辞書順で生成する方法がわかりません。
  • 例を示しながら質問します。たとえば、26文字のアルファベットから4文字を選んで辞書順に生成するプログラムはどのように実装すれば良いでしょうか?
  • 順列の生成方法に関しては、自分なりに考えた方法もありますが、スマートではないと感じています。また、要素がとびとびのアルファベットの場合にも応用できないか心配です。ご教示いただければ幸いです。

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

  • ベストアンサー
回答No.4

これでどうだ。 #include <iostream> #include <string> #include <array> #include <algorithm> using namespace std; // nPr : 13枚のカードから5枚選んで並べる int main() { const int N = 13; const int R = 5; string rank = "23456789TJQKA"; // select = { -1, -1, ... -1, 0, 1, 2, 3, 4 } array<int,N> select; fill(select.begin(), select.end(), -1); iota(select.end()-R, select.end(), 0); int perm = 0; do { ++perm; string result(R,' '); for ( int i = 0; i < N; ++i ) { if ( select[i] >= 0 ) result[select[i]] = rank[i]; } cout << result << endl; } while ( next_permutation(select.begin(), select.end()) ); cout << perm << endl; }

ainobakuda
質問者

お礼

回答ありがとうございます。 こんなやり方もあるんですね。 さっきのでも工夫すればできたと思いますけどこれだと一部かえるだけで使いまわせますね。 とても参考になりました! 本当にありがとうございました。

その他の回答 (3)

回答No.3

#define ALPHABET_NUM 4 にしたら4文字になります。

回答No.2

#1の方法だと左側のアルファベットより若い文字は出力されないのでは? つまり質問者の例にあるような "abdc" や "zyxw" といった文字列は出力されないはず。 とりあえずあまりスマートなコードではないけどどうぞ。 #include <stdio.h> #define ALPHABET_NUM 2 static char buffer[ ALPHABET_NUM + 1 ]; void permutate( unsigned int alpha, int depth ) { if( ALPHABET_NUM <= depth ) { buffer[ depth ] = '\0'; printf( "%s\n", buffer ); return; } unsigned int mask = 1; for( int bit = 0; bit < 26; bit++ ) { if( alpha & mask ) { buffer[ depth ] = 'a' + bit; permutate( alpha ^ mask, depth + 1 ); } mask = mask << 1; } } int main() { unsigned int alpha = 0x3FFFFFF; permutate( alpha, 0 ); return 0; }

ainobakuda
質問者

お礼

なるほど! 完璧ですね! 確かにこういう全探索かけば辞書順になりますね。 排他的論理輪でビット落としたりしてるのも参考になります。 本当にありがとうございました。

ainobakuda
質問者

補足

#1さんのもさらにnext_permutationを使うことでできるのであっていると思います。

回答No.1

next_permutationで26個から4個えらびだしてみた。 #include <iostream> #include <string> #include <algorithm> using namespace std; int main() { string alpha = "abcdefghijklmnopqrstuvwxyz"; string digit = "00000000000000000000001111"; do { string result; for ( string::size_type i = 0; i < digit.size(); ++i ) { if ( digit[i] == '1' ) result += alpha[i]; } cout << result << endl; } while ( next_permutation(digit.begin(), digit.end()) ); } あとは result をnext_permutationで並び替えればいんじゃないかと。

ainobakuda
質問者

お礼

回答ありがとうございます。 これだとコードが短い上にわかりやすくていいですね。 next_permutationの使い方がとても勉強になりました。 本当にありがとうございました。