问题-递归函数返回文本文件排列

时间:2019-05-11 14:36:02

标签: c++

基本上,我们有一项家庭作业,以c ++创建一个程序,该程序打开一个文本文件(“ input.txt ”),并输出到另一个文件(“ output.txt” ”),使用递归算法对输入文件的文本行进行排列。

我曾尝试实现递归函数,但似乎无法将其包裹住。我想输入和输出文件虽然不错(我认为)。

任何建议将不胜感激:)

#include <iostream>
#include <fstream>
#include <string>
#include <vector>

using namespace std;

string data; 
string file_contents; 

string permute()
{
string result;

ifstream inFile;
inFile.open("input.txt");   
int a = 0;
while (getline(inFile, file_contents))
{
    a++;
}
if (a == 1)
{
    ofstream OutFile;
}
else
{   
    ofstream OutFile;
}
return result;
}//perm

void accessFile()
{
ifstream inFile;
inFile.open("input.txt");   
if (!inFile.is_open())
{
    cout << "Error openning input file" << endl;
}
else 
{   
    while (getline(inFile, data))                                       
    {
        file_contents += data;
        file_contents.push_back('\n');
    }
    inFile.close();
}
ofstream OutFile;
OutFile.open("output.txt");
if(OutFile.fail())
{
    cout << "Error openning output file." << endl;
}
else
{
    OutFile << file_contents;
    permute();
    OutFile.close();
}
}//File

int main()
{
cout << "do you want to run the program?" << endl;
string input;
cin >> input;
if (input == "yes")
{
    accessFile();
}
else
{
exit;
}

return 0;
}//main

让我们说输入是:

Line One
Line Two
Line Three

预期输出为:

Line One
Line Two
Line Three

Line One
Line Three
Line Two

Line Two
Line One
Line Three

Line Two
Line Three
Line One

Line Three
Line One
Line Two

Line Three
Line Two
Line One

4 个答案:

答案 0 :(得分:1)

我已将代码修改为@cmdLP建议。为了利用C ++语言的功能,您应该使用bool next_permutation (BidirectionalIterator first, BidirectionalIterator last);函数模板。

如果您不知道它是如何工作的,则应查看http://www.cplusplus.com/reference/algorithm/next_permutation/

我不得不将file_contents的类型更改为std::vector<string>,因为next_permutation不能与单个字符串一起使用。

#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <algorithm>    // std::next_permutation

using namespace std;

string data;
std::vector<string> file_contents;

string permute() {
    string result;

    do {
        for(auto a: file_contents)
            result += a + " ";
        result += "\n";
    } while ( std::next_permutation(file_contents.begin(),file_contents.end()) );

    return result;
}

void accessFile() {
    ifstream inFile;
    inFile.open("input.txt");
    if (!inFile.is_open())
    {
        cout << "Error openning input file" << endl;
    }
    else
    {
        while (getline(inFile, data))
        {
            file_contents.push_back(data);
        }
        inFile.close();
    }
    ofstream OutFile;
    OutFile.open("output.txt");
    if(OutFile.fail())
    {
        cout << "Error openning output file." << endl;
    }
    else
    {
        // OutFile << file_contents;
        string result = permute();
        OutFile << result;
        OutFile.close();
    }
}//File

int main()
{
cout << "do you want to run the program?" << endl;
string input;
cin >> input;
if (input == "yes")
{
    accessFile();
}
else
{
exit(1);
}

return 0;
}//main

答案 1 :(得分:0)

如@cmdLP建议。在C ++中,我们可以使用C ++的功能,尤其是算法。放弃原始示例,这里提供了更现代的C ++解决方案:

// We want to use the stream input iterator and beeing able to read a complete line (and not words only)
class CompleteLine {
public:
    // Friend: Overload extraction operator for this class. Read complete line
    friend std::istream& operator>>(std::istream& is, CompleteLine& cl) {std::getline(is, cl.completeLine); return is; }
    operator std::string() const { return completeLine; } // Return the previously read line
protected:
    std::string completeLine{};
};

// Permute the lines of a file
void permute(const std::string& inFileName, const std::string& outFileName)
{
    std::ifstream inFileStream{ inFileName }; // Open the input file (will be closed by destructor)
    if (!inFileStream) {     // ! is overloaded
        std::cerr << "Could Not open infile: '" << inFileName << "'\n";
    }
    else {
        // Read all lines into a vector of strings. The string will contain the whole line
        std::vector<std::string> fileAsLines{ std::istream_iterator<CompleteLine>(inFileStream),std::istream_iterator<CompleteLine>() };

        std::ofstream outFileStream{ outFileName }; // Open the input file (will be closed by destructor)
        if (!outFileStream) {  // ! is overloaded
            std::cerr << "Could Not open outfile: '" << outFileName << "'\n";
        }
        else {
            // Sort strings (lines in file) 
            std::sort(fileAsLines.begin(), fileAsLines.end());
            do {
                // Ouput complete vector, so all strings (lines) of the file
                std::copy(fileAsLines.begin(), fileAsLines.end(), std::ostream_iterator<std::string>(outFileStream, "\n"));
                outFileStream << '\n';  // To make it easier to read the output
            } while (std::next_permutation(fileAsLines.begin(), fileAsLines.end())); // Next permutation of vector
        }
    }
}

希望这会有所帮助

答案 2 :(得分:0)

正如其他人所建议的,可以使用'std :: next_permutation'解决问题。 但是我认为@Mustafa Kalzi想到的是对如何创建这种算法有更好的理解。 我知道这是一个过大的问题,但是我发现这个问题很有趣,可以解决,并且可以算是数学问题。 考虑到“ std :: next_permutation”的某些缺点,我为置换问题创建了另一种通用算法。

我们已经做出了很多努力,将排列作为一个对象,该排列仅取决于可能的配置数量并且可以通过,  比较并最终由几个不同的对象使用,在那里可以为用户提供几乎完整的控制!

#include <iostream>
#include <fstream>
#include <string>
#include <vector>

/* Copyright (C) 2019 AKL.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
 */

/*just a simple rotator for an array of size(size_) elements.
 std::rotate is to cumbersome and needs sorting*/
template<typename value_t__, typename size_t__>
void rotation(value_t__* , size_t__ size_, decltype(size_) = 1);
/*an all encompassing function template for finding permutations of an array elements
 based on the inputed configuration value.
 since the it is ignorant to the contents of the array, it can be used with number of
 pointers but not for the iterators.
 in the case of iterators it is best to first fill a normal array with consecutive numbers
 then use the content as an index for operator[] of any container!
 please note that the main overhead is to create and fill the input array for each permutation
 but as it was stated contents remain untouched in contrast to std::next_permutation*/
template<typename value_t__, typename size_t__>
void permutation(value_t__* , size_t__ size_,
        decltype(size_));
/*Optionally an all-in-one class template to have incremental/decremental fully functional counter-like object
 which also includes the index array.
 in contrast to std::next_permutation, main advantages are  to have a method to know how many permutations
 have been passed by comparing it to other objects/values like a value and going forward and backward
 through permutations and not having to sort any thing before hand as it not sensitive to contents*/
template<typename size_t__ = std::size_t>
class permutations {
public:
    /*most useful and many of the required member functions for such classes
     ***please note that extra safety mechanisms like range check and safety against 0 size are not included***
     but these are easy to overcome by the user, so one can choose to optimize the usage for speed or safety!*/
    permutations(size_t__);
    permutations(const permutations&);
    void set_configuration(size_t__);
    size_t__& operator[](size_t__);
    size_t__ operator[](size_t__) const;
    size_t__ get_possibilities() const;
    permutations& operator++();
    permutations& operator--();
    permutations operator++(int);
    permutations operator--(int);
    operator size_t__() const;
    ~permutations();
private:
    size_t__ size_v;
    size_t__ possibilities;
    size_t__ configuration;
    size_t__* index;
};


/*assuming that the first argument to the program is the name of
 input file and the second argument would be the name of output file
 in posix it can be executed like:
./program_name input_file_name.txt output_file_name.txt 
*/
int main(int argc, char* argv[]) {
    //checking if the right arguments have been entered
    if ((not argc) or (argc > 3)) {
        std::cout << "wrong number of arguments " << argc - 1 << "should be 2"
                << std::endl;
        return -1;
    }
    //opening the input file;
    std::ifstream in_file(argv[1]);
    //checking if the file is opened correctly
    if (not in_file.is_open()) {
        std::cout << "can't open input file" << argv[1] << std::endl;
        return -1;
    }
    //creating a vector for  lines
    std::vector<std::string> lines;
    //filling the string vector by the reading from the input file lines
    for (std::string one_line; std::getline(in_file, one_line);
            lines.push_back(one_line))
        ;
    //creating an integer and filling it with the number of lines
    const std::size_t lines_count(lines.size());
    //permutations class templates are not able to handle 0 input so lets produce an error if that is the case
    if (not lines_count) {
        std::cout << argv[1] << " has zero lines!" << std::endl;
        return -1;
    }
    std::cout << argv[1] << " has " << lines_count << " lines" << std::endl;
    //creating a permutations object to find right vector index for permutations
    permutations<> permutation_counter(lines_count);
    //getting the number of total possible permutations. optional!
    const std::size_t possible_permutations(
            permutation_counter.get_possibilities());
    std::cout << "number of possible permutations is " << possible_permutations
            << std::endl;
    /*alternatively this also can be done  with permutation function
     one only needs to first create an array for the indexes but
     filling the index array might be tedious*/
    //creating and opening the output file
    std::ofstream out_file(argv[2]);
    //checking if the file is opened correctly
    if (not out_file.is_open()) {
        std::cout << "can't open output file" << argv[2] << std::endl;
        return -1;
    }
    //it is good to know how much of work is done for large files later!
    std::size_t done_percentage(0);
    //everything is set. now lets start going forward trough the permutations and writing to the output file!
    do {
        out_file << "********** permutation " << permutation_counter
                << " **********" << std::endl;
        for (std::size_t lines_counter(0); lines_counter < lines_count;
                out_file << lines[permutation_counter[lines_counter++]]
                        << std::endl)
            ;
        out_file << std::endl;
        //it is good to know how much of work is done for large files now!
        std::size_t done_percentage_now(
                (permutation_counter * 100) / possible_permutations);
        if (done_percentage_now != done_percentage) {
            done_percentage = done_percentage_now;
            std::cout << done_percentage << " % is done " << std::endl;
        }
    } while (++permutation_counter);
    /*alternatively --permutation_counter would also work to go backward trough the permutations!
     permutation_counter++/permutation_counter-- also work like post increment/decrement operators!
     by choosing any number from 0 to possible_permutations it is possible to go half or to a
     certain point  trough permutations!
     in addition by changing index array by using operator[] it would be possible to change any
     index there for the respective line or choose to only do the permutation for certain lines
     and/or even keep the rest unchanged!*/
    std::cout << "!!!finished!!!" << std::endl;
    return 0;
}

//definition for all functions.

template<typename value_t__, typename size_t__>
void rotation(value_t__* p_, size_t__ size_, decltype(size_) amount_) {
    for (size_t__ begin(0); begin < amount_; ++begin) {
        size_t__ index(begin);
        value_t__ backup(p_[index]);
        for (; (index += amount_) < size_; p_[index - amount_] = p_[index])
            ;
        p_[index - amount_] = backup;
    }
}

template<typename value_t__, typename size_t__>
void permutation(value_t__* p_, size_t__ size_,
        decltype(size_) configuration_) {
    /*above the size of 3 there is a simple regular formula,
     which is a combination of rotation of all elements in the current level then
     repeating a similar procedure for lower levels by recursive calls*/
    if (size_ > 3) {
        size_t__ factorial(--size_);
        for (size_t__ counter(size_); --counter; factorial *= counter)
            ;
        rotation(p_, size_ + 1, configuration_ / factorial);
        permutation(p_ + 1, size_, configuration_ % factorial);
        return;
    }
    /*case of size 3 is not regular but luckily very small so lets cover it as a switch-case statements.
     can easily be understood if one writes all the possibilities on a piece of paper (3 cm x 4 cm)*/
    if (size_ == 3) {
        switch (configuration_) {
        case 1:
            rotation(p_ + 1, 2);
            return;
        case 2:
            rotation(p_, 3);
            return;
        case 3:
            rotation(p_, 3);
            rotation(p_ + 1, 2);
            return;
        case 4:
            rotation(p_, 3, 2);
            return;
        case 5:
            rotation(p_, 3, 2);
            rotation(p_ + 1, 2);
            return;
        default:
            if (configuration_ > 5)
                permutation(p_, size_, configuration_ % 6);
            return;
        }
    }
    //case of size 2 is regular but it is after case of size 3. interestingly it is as tiny as one if statement!
    if (size_ == 2 and configuration_ % 2)
        rotation(p_, 2);
    //there is no permutation for case of size 1 and there is not even a case for lower sizes!
}


template<typename size_t__>
permutations<size_t__>::permutations(size_t__ size_v_) :
        size_v(size_v_), possibilities(size_v_), configuration(0), index(
                new size_t__[size_v_]) {
    for (; --size_v_; possibilities *= index[size_v_] = size_v_)
        ;
    index[0] = 0;
}
template<typename size_t__>
permutations<size_t__>::permutations(const permutations& another_) :
        size_v(another_.size_v), possibilities(another_.possibilities), configuration(
                another_.configuration), index(new size_t__[size_v]) {
    size_t__* another__index(another_.index);
    for (size_t__ counter(size_v); counter--; index[counter] =
            another__index[counter])
        ;
}
template<typename size_t__>
void permutations<size_t__>::set_configuration(size_t__ v_) {
    configuration = v_;
}
template<typename size_t__>
size_t__&
permutations<size_t__>::operator[](size_t__ index_) {
    return index[index_];
}
template<typename size_t__>
size_t__ permutations<size_t__>::operator[](size_t__ index_) const {
    return index[index_];
}
template<typename size_t__>
size_t__ permutations<size_t__>::get_possibilities() const {
    return possibilities;
}
template<typename size_t__>
permutations<size_t__>&
permutations<size_t__>::operator++() {
    if (not (++configuration < possibilities))
        configuration = 0;
    for (size_t__ counter(size_v); counter--; index[counter] = counter)
        ;
    permutation(index, size_v, configuration);
    return *this;
}
template<typename size_t__>
permutations<size_t__>&
permutations<size_t__>::operator--() {
    if (not configuration--)
        configuration = possibilities - 1;
    for (size_t__ counter(size_v); counter--; index[counter] = counter)
        ;
    permutation(index, size_v, configuration);
    return *this;
}
template<typename size_t__>
permutations<size_t__> permutations<size_t__>::operator++(int) {
    permutations back(*this);
    ++(*this);
    return back;
}
template<typename size_t__>
permutations<size_t__> permutations<size_t__>::operator--(int) {
    permutations back(*this);
    --(*this);
    return back;
}
template<typename size_t__>
permutations<size_t__>::operator size_t__() const {
    return configuration;
}

template<typename size_t__>
permutations<size_t__>::~permutations() {
    delete[] index;
}

给出输入文件:

line 0
line 1
line 2
line 3
line 4

结果输出文件:


********** permutation 0 **********
line 0
line 1
line 2
line 3
line 4

********** permutation 1 **********
line 0
line 1
line 2
line 4
line 3

********** permutation 2 **********
line 0
line 1
line 3
line 4
line 2

********** permutation 3 **********
line 0
line 1
line 3
line 2
line 4

********** permutation 4 **********
line 0
line 1
line 4
line 3
line 2

********** permutation 5 **********
line 0
line 1
line 4
line 2
line 3

********** permutation 6 **********
line 0
line 2
line 3
line 4
line 1

********** permutation 7 **********
line 0
line 2
line 3
line 1
line 4

********** permutation 8 **********
line 0
line 2
line 4
line 1
line 3

********** permutation 9 **********
line 0
line 2
line 4
line 3
line 1

********** permutation 10 **********
line 0
line 2
line 1
line 4
line 3

********** permutation 11 **********
line 0
line 2
line 1
line 3
line 4

********** permutation 12 **********
line 0
line 3
line 4
line 1
line 2

********** permutation 13 **********
line 0
line 3
line 4
line 2
line 1

********** permutation 14 **********
line 0
line 3
line 1
line 2
line 4

********** permutation 15 **********
line 0
line 3
line 1
line 4
line 2

********** permutation 16 **********
line 0
line 3
line 2
line 1
line 4

********** permutation 17 **********
line 0
line 3
line 2
line 4
line 1

********** permutation 18 **********
line 0
line 4
line 2
line 3
line 1

********** permutation 19 **********
line 0
line 4
line 2
line 1
line 3

********** permutation 20 **********
line 0
line 4
line 3
line 1
line 2

********** permutation 21 **********
line 0
line 4
line 3
line 2
line 1

********** permutation 22 **********
line 0
line 4
line 1
line 3
line 2

********** permutation 23 **********
line 0
line 4
line 1
line 2
line 3

********** permutation 24 **********
line 1
line 2
line 3
line 4
line 0

********** permutation 25 **********
line 1
line 2
line 3
line 0
line 4

********** permutation 26 **********
line 1
line 2
line 4
line 0
line 3

********** permutation 27 **********
line 1
line 2
line 4
line 3
line 0

********** permutation 28 **********
line 1
line 2
line 0
line 4
line 3

********** permutation 29 **********
line 1
line 2
line 0
line 3
line 4

********** permutation 30 **********
line 1
line 3
line 4
line 0
line 2

********** permutation 31 **********
line 1
line 3
line 4
line 2
line 0

********** permutation 32 **********
line 1
line 3
line 0
line 2
line 4

********** permutation 33 **********
line 1
line 3
line 0
line 4
line 2

********** permutation 34 **********
line 1
line 3
line 2
line 0
line 4

********** permutation 35 **********
line 1
line 3
line 2
line 4
line 0

********** permutation 36 **********
line 1
line 4
line 0
line 2
line 3

********** permutation 37 **********
line 1
line 4
line 0
line 3
line 2

********** permutation 38 **********
line 1
line 4
line 2
line 3
line 0

********** permutation 39 **********
line 1
line 4
line 2
line 0
line 3

********** permutation 40 **********
line 1
line 4
line 3
line 2
line 0

********** permutation 41 **********
line 1
line 4
line 3
line 0
line 2

********** permutation 42 **********
line 1
line 0
line 3
line 4
line 2

********** permutation 43 **********
line 1
line 0
line 3
line 2
line 4

********** permutation 44 **********
line 1
line 0
line 4
line 2
line 3

********** permutation 45 **********
line 1
line 0
line 4
line 3
line 2

********** permutation 46 **********
line 1
line 0
line 2
line 4
line 3

********** permutation 47 **********
line 1
line 0
line 2
line 3
line 4

********** permutation 48 **********
line 2
line 3
line 4
line 1
line 0

********** permutation 49 **********
line 2
line 3
line 4
line 0
line 1

********** permutation 50 **********
line 2
line 3
line 1
line 0
line 4

********** permutation 51 **********
line 2
line 3
line 1
line 4
line 0

********** permutation 52 **********
line 2
line 3
line 0
line 1
line 4

********** permutation 53 **********
line 2
line 3
line 0
line 4
line 1

********** permutation 54 **********
line 2
line 4
line 1
line 0
line 3

********** permutation 55 **********
line 2
line 4
line 1
line 3
line 0

********** permutation 56 **********
line 2
line 4
line 0
line 3
line 1

********** permutation 57 **********
line 2
line 4
line 0
line 1
line 3

********** permutation 58 **********
line 2
line 4
line 3
line 0
line 1

********** permutation 59 **********
line 2
line 4
line 3
line 1
line 0

********** permutation 60 **********
line 2
line 1
line 0
line 3
line 4

********** permutation 61 **********
line 2
line 1
line 0
line 4
line 3

********** permutation 62 **********
line 2
line 1
line 3
line 4
line 0

********** permutation 63 **********
line 2
line 1
line 3
line 0
line 4

********** permutation 64 **********
line 2
line 1
line 4
line 3
line 0

********** permutation 65 **********
line 2
line 1
line 4
line 0
line 3

********** permutation 66 **********
line 2
line 0
line 4
line 1
line 3

********** permutation 67 **********
line 2
line 0
line 4
line 3
line 1

********** permutation 68 **********
line 2
line 0
line 1
line 3
line 4

********** permutation 69 **********
line 2
line 0
line 1
line 4
line 3

********** permutation 70 **********
line 2
line 0
line 3
line 1
line 4

********** permutation 71 **********
line 2
line 0
line 3
line 4
line 1

********** permutation 72 **********
line 3
line 4
line 2
line 0
line 1

********** permutation 73 **********
line 3
line 4
line 2
line 1
line 0

********** permutation 74 **********
line 3
line 4
line 0
line 1
line 2

********** permutation 75 **********
line 3
line 4
line 0
line 2
line 1

********** permutation 76 **********
line 3
line 4
line 1
line 0
line 2

********** permutation 77 **********
line 3
line 4
line 1
line 2
line 0

********** permutation 78 **********
line 3
line 2
line 0
line 1
line 4

********** permutation 79 **********
line 3
line 2
line 0
line 4
line 1

********** permutation 80 **********
line 3
line 2
line 1
line 4
line 0

********** permutation 81 **********
line 3
line 2
line 1
line 0
line 4

********** permutation 82 **********
line 3
line 2
line 4
line 1
line 0

********** permutation 83 **********
line 3
line 2
line 4
line 0
line 1

********** permutation 84 **********
line 3
line 0
line 1
line 4
line 2

********** permutation 85 **********
line 3
line 0
line 1
line 2
line 4

********** permutation 86 **********
line 3
line 0
line 4
line 2
line 1

********** permutation 87 **********
line 3
line 0
line 4
line 1
line 2

********** permutation 88 **********
line 3
line 0
line 2
line 4
line 1

********** permutation 89 **********
line 3
line 0
line 2
line 1
line 4

********** permutation 90 **********
line 3
line 1
line 2
line 0
line 4

********** permutation 91 **********
line 3
line 1
line 2
line 4
line 0

********** permutation 92 **********
line 3
line 1
line 0
line 4
line 2

********** permutation 93 **********
line 3
line 1
line 0
line 2
line 4

********** permutation 94 **********
line 3
line 1
line 4
line 0
line 2

********** permutation 95 **********
line 3
line 1
line 4
line 2
line 0

********** permutation 96 **********
line 4
line 1
line 2
line 3
line 0

********** permutation 97 **********
line 4
line 1
line 2
line 0
line 3

********** permutation 98 **********
line 4
line 1
line 3
line 0
line 2

********** permutation 99 **********
line 4
line 1
line 3
line 2
line 0

********** permutation 100 **********
line 4
line 1
line 0
line 3
line 2

********** permutation 101 **********
line 4
line 1
line 0
line 2
line 3

********** permutation 102 **********
line 4
line 2
line 3
line 0
line 1

********** permutation 103 **********
line 4
line 2
line 3
line 1
line 0

********** permutation 104 **********
line 4
line 2
line 0
line 1
line 3

********** permutation 105 **********
line 4
line 2
line 0
line 3
line 1

********** permutation 106 **********
line 4
line 2
line 1
line 0
line 3

********** permutation 107 **********
line 4
line 2
line 1
line 3
line 0

********** permutation 108 **********
line 4
line 3
line 0
line 1
line 2

********** permutation 109 **********
line 4
line 3
line 0
line 2
line 1

********** permutation 110 **********
line 4
line 3
line 1
line 2
line 0

********** permutation 111 **********
line 4
line 3
line 1
line 0
line 2

********** permutation 112 **********
line 4
line 3
line 2
line 1
line 0

********** permutation 113 **********
line 4
line 3
line 2
line 0
line 1

********** permutation 114 **********
line 4
line 0
line 2
line 3
line 1

********** permutation 115 **********
line 4
line 0
line 2
line 1
line 3

********** permutation 116 **********
line 4
line 0
line 3
line 1
line 2

********** permutation 117 **********
line 4
line 0
line 3
line 2
line 1

********** permutation 118 **********
line 4
line 0
line 1
line 3
line 2

********** permutation 119 **********
line 4
line 0
line 1
line 2
line 3


控制台对话和消息:

./program input.txt output.txt
input.txt has 5 lines
number of possible permutations is 120
1 % is done 
2 % is done 
3 % is done 
4 % is done 
5 % is done 
6 % is done 
7 % is done 
8 % is done 
9 % is done 
10 % is done 
11 % is done 
12 % is done 
13 % is done 
14 % is done 
15 % is done 
16 % is done 
17 % is done 
18 % is done 
19 % is done 
20 % is done 
21 % is done 
22 % is done 
23 % is done 
24 % is done 
25 % is done 
26 % is done 
27 % is done 
28 % is done 
29 % is done 
30 % is done 
31 % is done 
32 % is done 
33 % is done 
34 % is done 
35 % is done 
36 % is done 
37 % is done 
38 % is done 
39 % is done 
40 % is done 
41 % is done 
42 % is done 
43 % is done 
44 % is done 
45 % is done 
46 % is done 
47 % is done 
48 % is done 
49 % is done 
50 % is done 
51 % is done 
52 % is done 
53 % is done 
54 % is done 
55 % is done 
56 % is done 
57 % is done 
58 % is done 
59 % is done 
60 % is done 
61 % is done 
62 % is done 
63 % is done 
64 % is done 
65 % is done 
66 % is done 
67 % is done 
68 % is done 
69 % is done 
70 % is done 
71 % is done 
72 % is done 
73 % is done 
74 % is done 
75 % is done 
76 % is done 
77 % is done 
78 % is done 
79 % is done 
80 % is done 
81 % is done 
82 % is done 
83 % is done 
84 % is done 
85 % is done 
86 % is done 
87 % is done 
88 % is done 
89 % is done 
90 % is done 
91 % is done 
92 % is done 
93 % is done 
94 % is done 
95 % is done 
96 % is done 
97 % is done 
98 % is done 
99 % is done 
!!!finished!!!


该代码具有很好的注释性和自我解释能力。在主函数之前的开头声明函数和类模板是解决此类问题的另一种通用方法。主要功能中的其余代码用于展示如何使用这些模板,并且其结构或多或少类似于其他人所做的。最后,在主函数之后最后给出了函数的完整定义。

理解该问题的关键是如何处理不规则的4个变量,因为3!(3 x 2 x 6)大于变量(3)的数量,而2!(2 x 1)大于不大于变量(2)的数量,因此很难确定如何找到4个变量以下情况的旋转和排列。但是有趣的是,超过该阈值将变得非常规则和容易!

基于表示可能排列的数字,人们只需找到旋转值和先前级别的排列值。例如,考虑4变量的情况,我将其指定为问题的4级,并且是User对递归函数的第一次调用。共4!(4 x 3 x 2 x 1)= 24种可能性。给定数字20作为某个置换的表示,将20除以3!(6)即可找到旋转的表示,并将20的余数除以3!(6)作为级别3置换的表示,是对函数本身的第二次调用和第一次递归调用。

对于'std :: next_permutation',一定不要忘记必须首先对容器进行排序,否则它不会产生所有排列。这也意味着排列的排列是在用户控制之外的,特别是如果希望具有与原始输入相同的第一配置时。而且它也没有提供一种方法来了解排列演化的状态。

提供的此替代解决方案(在GNU LGPL版本2和更高版本中)还封装了一些其他有用的功能。我能想到的一个主要缺点是无法使用迭代器。在为每个排列填充索引数组而导致的开销方面,除去(仅从主要功能而不是模板中)主要功能(进度报告等)并针对10行的输入文件执行了速度测试之后,此方法与使用'std :: next_permutation'(57.2 vs 57.9秒)之间几乎没有差异。还需要注意的是,与写入文件和流所需的过程相比,这两种算法所需的过程可能都太少了,从而使我的速度测试变得毫无用处!

如果这不是他的初衷,或者我的代码不符合他的喜好,我向@Mustafa Kalzi致歉!

请随时发表评论,提供建议/更正并提出问题!祝好运!

答案 3 :(得分:0)

@MustafaKalzi,为便于比较和简化起见,我编辑了代码,改为使用std :: next_permutation。这也很容易理解,如果您更倾向于使用标准库,则可以使用它。 排列计数和进度报告已被省略,您以后可以轻松地添加它。

#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <algorithm>

/*assuming that the first argument to the program is the name of
 input file and the second argument would be the name of output file*/
int main(int argc, char* argv[]) {
    //checking if the right arguments have been entered
    if ((not argc) or (argc > 3)) {
        std::cerr << "wrong number of arguments " << argc - 1 << "should be 2"
                << std::endl;
        return -1;
    }
    //opening the input file;
    std::ifstream in_file(argv[1]);
    //checking if the file is opened correctly
    if (not in_file.is_open()) {
        std::cerr << "can't open input file" << argv[1] << std::endl;
        return -1;
    }
    //creating a vector for  lines
    std::vector<std::string> lines;
    //filling the string vector by the reading from the input file lines
    for (std::string one_line; std::getline(in_file, one_line);
            lines.push_back(one_line))
        ;
    //creating an integer and filling it with the number of lines
    const std::size_t lines_count(lines.size());
    //producing an error if there is no line  in the file
    if (not lines_count) {
        std::cerr << argv[1] << " has zero lines!" << std::endl;
        return -1;
    }
    std::cout << argv[1] << " has " << lines_count << " lines" << std::endl;
    //sorting the vector in order to use std::next permutation afterwards
    std::sort(lines.begin(), lines.end());
    //creating and opening the output file
    std::ofstream out_file(argv[2]);
    //checking if the file is opened correctly
    if (not out_file.is_open()) {
        std::cerr << "can't open output file" << argv[2] << std::endl;
        return -1;
    }
    //everything is set. now lets start going forward trough the permutations and writing to the output file!
    do {
        for (std::size_t lines_counter(0); lines_counter < lines_count;
                out_file << lines[lines_counter++] << std::endl)
            ;
        out_file << std::endl;
    } while (std::next_permutation(lines.begin(), lines.end()));
    std::cout << "!!!finished!!!" << std::endl;
    return 0;
}

输入文件

line 0
line 1
line 2
line 3
line 4

输出文件

line 0
line 1
line 2
line 3
line 4

line 0
line 1
line 2
line 4
line 3

line 0
line 1
line 3
line 2
line 4

line 0
line 1
line 3
line 4
line 2

line 0
line 1
line 4
line 2
line 3

line 0
line 1
line 4
line 3
line 2

line 0
line 2
line 1
line 3
line 4

line 0
line 2
line 1
line 4
line 3

line 0
line 2
line 3
line 1
line 4

line 0
line 2
line 3
line 4
line 1

line 0
line 2
line 4
line 1
line 3

line 0
line 2
line 4
line 3
line 1

line 0
line 3
line 1
line 2
line 4

line 0
line 3
line 1
line 4
line 2

line 0
line 3
line 2
line 1
line 4

line 0
line 3
line 2
line 4
line 1

line 0
line 3
line 4
line 1
line 2

line 0
line 3
line 4
line 2
line 1

line 0
line 4
line 1
line 2
line 3

line 0
line 4
line 1
line 3
line 2

line 0
line 4
line 2
line 1
line 3

line 0
line 4
line 2
line 3
line 1

line 0
line 4
line 3
line 1
line 2

line 0
line 4
line 3
line 2
line 1

line 1
line 0
line 2
line 3
line 4

line 1
line 0
line 2
line 4
line 3

line 1
line 0
line 3
line 2
line 4

line 1
line 0
line 3
line 4
line 2

line 1
line 0
line 4
line 2
line 3

line 1
line 0
line 4
line 3
line 2

line 1
line 2
line 0
line 3
line 4

line 1
line 2
line 0
line 4
line 3

line 1
line 2
line 3
line 0
line 4

line 1
line 2
line 3
line 4
line 0

line 1
line 2
line 4
line 0
line 3

line 1
line 2
line 4
line 3
line 0

line 1
line 3
line 0
line 2
line 4

line 1
line 3
line 0
line 4
line 2

line 1
line 3
line 2
line 0
line 4

line 1
line 3
line 2
line 4
line 0

line 1
line 3
line 4
line 0
line 2

line 1
line 3
line 4
line 2
line 0

line 1
line 4
line 0
line 2
line 3

line 1
line 4
line 0
line 3
line 2

line 1
line 4
line 2
line 0
line 3

line 1
line 4
line 2
line 3
line 0

line 1
line 4
line 3
line 0
line 2

line 1
line 4
line 3
line 2
line 0

line 2
line 0
line 1
line 3
line 4

line 2
line 0
line 1
line 4
line 3

line 2
line 0
line 3
line 1
line 4

line 2
line 0
line 3
line 4
line 1

line 2
line 0
line 4
line 1
line 3

line 2
line 0
line 4
line 3
line 1

line 2
line 1
line 0
line 3
line 4

line 2
line 1
line 0
line 4
line 3

line 2
line 1
line 3
line 0
line 4

line 2
line 1
line 3
line 4
line 0

line 2
line 1
line 4
line 0
line 3

line 2
line 1
line 4
line 3
line 0

line 2
line 3
line 0
line 1
line 4

line 2
line 3
line 0
line 4
line 1

line 2
line 3
line 1
line 0
line 4

line 2
line 3
line 1
line 4
line 0

line 2
line 3
line 4
line 0
line 1

line 2
line 3
line 4
line 1
line 0

line 2
line 4
line 0
line 1
line 3

line 2
line 4
line 0
line 3
line 1

line 2
line 4
line 1
line 0
line 3

line 2
line 4
line 1
line 3
line 0

line 2
line 4
line 3
line 0
line 1

line 2
line 4
line 3
line 1
line 0

line 3
line 0
line 1
line 2
line 4

line 3
line 0
line 1
line 4
line 2

line 3
line 0
line 2
line 1
line 4

line 3
line 0
line 2
line 4
line 1

line 3
line 0
line 4
line 1
line 2

line 3
line 0
line 4
line 2
line 1

line 3
line 1
line 0
line 2
line 4

line 3
line 1
line 0
line 4
line 2

line 3
line 1
line 2
line 0
line 4

line 3
line 1
line 2
line 4
line 0

line 3
line 1
line 4
line 0
line 2

line 3
line 1
line 4
line 2
line 0

line 3
line 2
line 0
line 1
line 4

line 3
line 2
line 0
line 4
line 1

line 3
line 2
line 1
line 0
line 4

line 3
line 2
line 1
line 4
line 0

line 3
line 2
line 4
line 0
line 1

line 3
line 2
line 4
line 1
line 0

line 3
line 4
line 0
line 1
line 2

line 3
line 4
line 0
line 2
line 1

line 3
line 4
line 1
line 0
line 2

line 3
line 4
line 1
line 2
line 0

line 3
line 4
line 2
line 0
line 1

line 3
line 4
line 2
line 1
line 0

line 4
line 0
line 1
line 2
line 3

line 4
line 0
line 1
line 3
line 2

line 4
line 0
line 2
line 1
line 3

line 4
line 0
line 2
line 3
line 1

line 4
line 0
line 3
line 1
line 2

line 4
line 0
line 3
line 2
line 1

line 4
line 1
line 0
line 2
line 3

line 4
line 1
line 0
line 3
line 2

line 4
line 1
line 2
line 0
line 3

line 4
line 1
line 2
line 3
line 0

line 4
line 1
line 3
line 0
line 2

line 4
line 1
line 3
line 2
line 0

line 4
line 2
line 0
line 1
line 3

line 4
line 2
line 0
line 3
line 1

line 4
line 2
line 1
line 0
line 3

line 4
line 2
line 1
line 3
line 0

line 4
line 2
line 3
line 0
line 1

line 4
line 2
line 3
line 1
line 0

line 4
line 3
line 0
line 1
line 2

line 4
line 3
line 0
line 2
line 1

line 4
line 3
line 1
line 0
line 2

line 4
line 3
line 1
line 2
line 0

line 4
line 3
line 2
line 0
line 1

line 4
line 3
line 2
line 1
line 0

控制台消息和通讯:

./program input.txt output.txt
input.txt has 5 lines
!!!finished!!!