
こんにちは
組み合わせと順列についてです。
順序関係のある要素で構成される集合から一定の数をとり、順列を辞書順で生成する方法がわかりません。
うまく説明できないので、例を示します。
たとえば26文字のアルファベットから4文字を選んで辞書順に生成するプログラムはどのようにやればいいのでしょうか?
このアルファベットの例だと
abcd
abce
abcf
・・・
abcz
abdc
abde
・・・
zyxw
のようになると思います。
要素と長さが決まっている場合で順列を生成する部分は大丈夫です。(C++ STLのnext_permutationにあたる部分)
一応自分なりに考えたやり方は26進数4桁のように考えて、それを1ずつ増やし、全体で2回以上使われていないかを調べる と思ったんですが、あまりスマートじゃないし要素がとびとびのアルファベットのときなどに応用が利かないと思いました。
指摘していただければ補足しますので、よろしくお願いします。
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;
}
回答ありがとうございます。
こんなやり方もあるんですね。
さっきのでも工夫すればできたと思いますけどこれだと一部かえるだけで使いまわせますね。
とても参考になりました!
本当にありがとうございました。
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;
}
なるほど!
完璧ですね!
確かにこういう全探索かけば辞書順になりますね。
排他的論理輪でビット落としたりしてるのも参考になります。
本当にありがとうございました。
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で並び替えればいんじゃないかと。
回答ありがとうございます。
これだとコードが短い上にわかりやすくていいですね。
next_permutationの使い方がとても勉強になりました。
本当にありがとうございました。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
C++でShowCursorを使いたい。
-
標準の例外の全種類と、発生す...
-
snprintfが使用できない。
-
string型の固定長文字列を配列...
-
switch文のエラーについて
-
OpenCVでRAW画像(カラー)を開...
-
CStringとString
-
VC++ iostreamの不具合(?)
-
#define中の#のエスケープ
-
std::lower_boundについて
-
#include "fstream.h"
-
コンパイルできません
-
「Aに対するBの割合」と「Aに対...
-
「指定されたキャストは有効で...
-
Enterキーを押されたら次の処理...
-
C言語での引数の省略方法
-
信頼区間の1.96や1.65ってどこ...
-
エクセルで可視セルにのみ値貼...
-
DWORDの実際の型は何でしょうか
-
Aの値からBの値を除するとは??
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
VC++で文字列から任意の文字を...
-
なぜ、C++の標準ヘッダをインク...
-
switch文のエラーについて
-
VxWorks 6.4ソケット接続につい...
-
gccでコンパイル時のエラー
-
iostream インクルード時に発生...
-
#include "fstream.h"
-
【C++】ヘッダ内でstringを格納...
-
#defineの使い方について
-
構文エラーが出ているのですが...
-
C言語のポインターで詰まっている
-
std::map の const 修飾について
-
C++での <iostream.h>と<iostre...
-
enumの値から定義名を文字列化...
-
MingwでC++のソースがコンパイ...
-
違い
-
VC++で
-
C++で日本語の処理がしたいです
-
継承されたABのクラスのポイン...
-
C++でShowCursorを使いたい。
おすすめ情報