
こんにちは
組み合わせと順列についてです。
順序関係のある要素で構成される集合から一定の数をとり、順列を辞書順で生成する方法がわかりません。
うまく説明できないので、例を示します。
たとえば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で質問しましょう!
似たような質問が見つかりました
- 数学 順序集合における「反射律」の役割について 9 2022/05/09 23:01
- 英語 「材料を入れる順番が重要です」を英語にすると 3 2023/04/08 13:21
- その他(プログラミング・Web制作) パイソンのプログラミングについての質問です 2 2023/05/22 12:39
- Java Java 南京錠 2 2023/02/04 11:46
- Access(アクセス) AccessVBAで降順にするテーブル作成クエリを使用して作成したテーブルを削除し同一のテーブル作成 1 2023/01/06 11:17
- 数学 前順序集合についての違和感なんですが、全順序と違ってすべての要素の間に順序があるわけではないですよね 3 2022/08/09 00:05
- Visual Basic(VBA) エクセルVBAについて 2 2023/01/31 16:21
- その他(プログラミング・Web制作) プログラミング pythonの問題について 2 2022/04/19 00:41
- Ruby 初心者プログラミング 3 2022/10/12 11:31
- Excel(エクセル) ExcelのIF関数について 4 2023/05/24 12:54
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
shared_ptr クラスについて
-
C言語のポインターで詰まっている
-
VC++で文字列から任意の文字を...
-
修正箇所の指摘のお願い(文字列...
-
ヘッダーファイルがインクルー...
-
Pascalへの変換について
-
C++ 平均値、最大値と最小値の...
-
C++での <iostream.h>と<iostre...
-
enumの値から定義名を文字列化...
-
コンパイルできません
-
_CRT_SECURE_NO_DEPRECATE が効...
-
winpcapを用いたプログラミング
-
このプログラミング誰か教えて...
-
C++で2次元配列charをループしたい
-
JPEGやPNGが読めるLoadImage関数
-
ユークリッドの除去法アルゴリズム
-
2重の(?)の#include
-
C言語
-
vc++の使い方について
-
std::wstringのメモリリークに...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
VC++で文字列から任意の文字を...
-
なぜ、C++の標準ヘッダをインク...
-
構文エラーが出ているのですが...
-
enumの値から定義名を文字列化...
-
JPEGやPNGが読めるLoadImage関数
-
std::map の const 修飾について
-
VS2019でofstreamが未定義になる
-
_tcscat がうまくいきません(V...
-
空ENTERの判別
-
構造体配列のvectorへの変換と...
-
switch文のエラーについて
-
std::wstringのメモリリークに...
-
#define中の#のエスケープ
-
C++でShowCursorを使いたい。
-
findnext();について
-
【C++】ヘッダ内でstringを格納...
-
#include "fstream.h"
-
CStringとString
-
#defineの使い方について
-
iostream インクルード時に発生...
おすすめ情報