简体   繁体   English

在C ++中生成复合排列的绝佳方法

[英]Elegant Way To Generate Composite Permutations in C++

I have a class Test which contains two vectors of a Letter class, a user defined type for which the less-than operator (<) has been implemented. 我有一个Test类,其中包含两个Letter类的向量,这是一个用户定义的类型,已经实现了小于运算符(<)。 How can I best generate all possible permutations of Test? 如何最好地生成Test的所有可能排列?

class Test
{
  vector<Letter> letter_box_a;
  vector<Letter> letter_box_b;
}

So if letter_box_a contains the letters A and B and letter_box_b contains C and D the valid permutations of Test would be (AB)(CD), (BA)(CD), (AB)(DC) and (BA)(DC). 因此,如果letter_box_a包含字母A和B,而letter_box_b包含字母C和D,则Test的有效排列将为(AB)(CD),(BA)(CD),(AB)(DC)和(BA)(DC)。

Although I am able to brute force it, I was trying to write a better (more elegant/efficient) function which would internally call std::next_permutation on the underlying containers allowing me to do 虽然我可以蛮力,但是我试图编写一个更好的(更优雅/更有效)的函数,该函数在底层容器上内部调用std :: next_permutation,使我能够

Test test;
while (test.set_next_permutation())
{
    // Do the stuff
}

but it appears to be a bit trickier than I first anticipated. 但这似乎比我最初预期的要复杂。 I don't necessarily need an STL solution but would like an elegant solution. 我不一定需要STL解决方案,但想要一个优雅的解决方案。

If you want to use std::next_permutation , you need a nested loop for each vector you are permuting: 如果要使用std::next_permutation ,则需要对要排列的每个向量进行嵌套循环:

std::string s0 = "ab";
std::string s1 = "cd";

do
{
    do
    {
        cout << s0 << "" << s1 << endl;
    } while (std::next_permutation(s0.begin(), s0.end()));
} while (std::next_permutation(s1.begin(), s1.end()));

Output: 输出:

abcd
bacd
abdc
badc

And, in the class: 并且,在课堂上:

class Foo
{
public:
    Foo(std::string_view arg_a, std::string_view arg_b)
        : a(arg_a)
        , b(arg_b)
        , last(false)
    { }

    void reset_permutations()
    {
        last = false;
    }

    bool next_permutation(std::string& r)
    {
        if (last)
            return false;

        if (not std::next_permutation(a.begin(), a.end()))
            if (not std::next_permutation(b.begin(), b.end()))
                last = true;

        r = a + b;
        return true;
    }

private:
    std::string a, b;
    bool last;
};

int main(int argc, const char *argv[])
{
    Foo foo("ab", "cd");
    string s;
    while (foo.next_permutation(s))
        cout << s << endl;
    return 0;
}

I would think you could do something like 我想你可以做些类似的事情

bool Test::set_next_permutation() {
    auto &a = letter_box_a, &b = letter_box_b;  // entirely to shorten the next line
    return std::next_permutation(a.start(), a.end()) || std::next_permutation(b.start(), b.end());
}

(Of course, a while loop will skip the initial permutation in any case. You want a do ... while loop instead.) (当然,在任何情况下, while循环都会跳过初始排列。您需要使用do ... while循环。)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM